aboutsummaryrefslogblamecommitdiff
path: root/src/garage/server.rs
blob: 739dedbefd89ba194fd3dbeef82de1d5cbc0930d (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
 





                               
                             
                                   
                               
                                 
                               
 
                    
 
                                                     

                                                  











                                                                                   





                                                                 
 
                                                                   

                                                    
                                                   
                                                        
                                                                                                  
 
                                                        

                                                                 




                                                                         
                                                                                       
 
                                             













                                                     

                                                       
                                                                                                                 
 








                                                             


                                                                   



                                                                   
                                             
                          





                                                                           
                                     




                                
use std::path::PathBuf;

use tokio::sync::watch;

use garage_util::background::*;
use garage_util::config::*;
use garage_util::error::Error;

use garage_admin::metrics::*;
use garage_admin::tracing_setup::*;
use garage_api::run_api_server;
use garage_model::garage::Garage;
use garage_web::run_web_server;

use crate::admin::*;

async fn wait_from(mut chan: watch::Receiver<bool>) {
	while !*chan.borrow() {
		if chan.changed().await.is_err() {
			return;
		}
	}
}

pub async fn run_server(config_file: PathBuf) -> Result<(), Error> {
	info!("Loading configuration...");
	let config = read_config(config_file).expect("Unable to read config file");

	info!("Opening database...");
	let mut db_path = config.metadata_dir.clone();
	db_path.push("db");
	let db = sled::Config::default()
		.path(&db_path)
		.cache_capacity(config.sled_cache_capacity)
		.flush_every_ms(Some(config.sled_flush_every_ms))
		.open()
		.expect("Unable to open sled DB");

	info!("Initialize admin web server and metric backend...");
	let admin_server_init = AdminServer::init();

	info!("Initializing background runner...");
	let watch_cancel = netapp::util::watch_ctrl_c();
	let (background, await_background_done) = BackgroundRunner::new(16, watch_cancel.clone());

	info!("Initializing Garage main data store...");
	let garage = Garage::new(config.clone(), db, background);

	info!("Initialize tracing...");
	if let Some(export_to) = config.admin_api.otlp_export_traces_to {
		init_tracing(&export_to, garage.system.id)?;
	}

	let run_system = tokio::spawn(garage.system.clone().run(watch_cancel.clone()));

	info!("Create admin RPC handler...");
	AdminRpcHandler::new(garage.clone());

	info!("Initializing API server...");
	let api_server = tokio::spawn(run_api_server(
		garage.clone(),
		wait_from(watch_cancel.clone()),
	));

	info!("Initializing web server...");
	let web_server = tokio::spawn(run_web_server(
		garage.clone(),
		wait_from(watch_cancel.clone()),
	));

	info!("Configure and run admin web server...");
	let admin_server =
		tokio::spawn(admin_server_init.run(config.admin_api.bind_addr, wait_from(watch_cancel.clone())));

	// Stuff runs

	// When a cancel signal is sent, stuff stops
	if let Err(e) = api_server.await? {
		warn!("API server exited with error: {}", e);
	}
	if let Err(e) = web_server.await? {
		warn!("Web server exited with error: {}", e);
	}
	if let Err(e) = admin_server.await? {
		warn!("Admin web server exited with error: {}", e);
	}

	// Remove RPC handlers for system to break reference cycles
	garage.system.netapp.drop_all_handlers();

	// Await for netapp RPC system to end
	run_system.await?;

	// Break last reference cycles so that stuff can terminate properly
	garage.break_reference_cycles();
	drop(garage);

	// Await for all background tasks to end
	await_background_done.await?;

	info!("Cleaning up...");

	Ok(())
}