1#![warn(rust_2018_idioms)]
2#![forbid(unsafe_code)]
3
4#[macro_use]
5extern crate slog_scope;
6
7use std::{env, time::Duration, vec::Vec};
8
9use actix_http::HttpService;
10use actix_server::Server;
11use actix_service::map_config;
12use actix_web::dev::AppConfig;
13use docopt::Docopt;
14use serde::Deserialize;
15
16use autoconnect_settings::{AppState, Settings};
17use autoconnect_web::{build_app, config, config_router};
18use autopush_common::{
19 db::spawn_pool_periodic_reporter,
20 errors::{ApcErrorKind, Result},
21 logging,
22};
23
24const USAGE: &str = "
25Usage: autoconnect [options]
26
27Options:
28 -h, --help Show this message.
29 --config=CONFIGFILE Connection configuration file path.
30";
31
32#[derive(Debug, Deserialize)]
33struct Args {
34 flag_config: Option<String>,
35}
36
37#[actix_web::main]
38async fn main() -> Result<()> {
39 env_logger::init();
40 let args: Args = Docopt::new(USAGE)
41 .and_then(|d| d.deserialize())
42 .unwrap_or_else(|e| e.exit());
43 let mut filenames = Vec::new();
44 if let Some(config_filename) = args.flag_config {
45 filenames.push(config_filename);
46 }
47 let settings =
48 Settings::with_env_and_config_files(&filenames).map_err(ApcErrorKind::ConfigError)?;
49 logging::init_logging(
50 !settings.human_logs,
51 env!("CARGO_PKG_NAME"),
52 env!("CARGO_PKG_VERSION"),
53 )
54 .expect("Logging failed to initialize");
55 debug!("Starting up autoconnect...");
56
57 if env::var("SENTRY_DSN")
59 .unwrap_or_else(|_| "".to_owned())
60 .is_empty()
61 {
62 print!("SENTRY_DSN not set. Logging disabled.");
63 }
64
65 let _guard = sentry::init(sentry::ClientOptions {
66 release: sentry::release_name!(),
67 session_mode: sentry::SessionMode::Request, auto_session_tracking: true,
69 ..autopush_common::sentry::client_options()
70 });
71
72 let port = settings.port;
73 let router_port = settings.router_port;
74 let actix_max_connections = settings.actix_max_connections;
75 let actix_workers = settings.actix_workers;
76 let app_state = AppState::from_settings(settings)?;
77 app_state.init_and_spawn_megaphone_updater().await?;
78 spawn_pool_periodic_reporter(
79 Duration::from_secs(10),
80 app_state.db.clone(),
81 app_state.metrics.clone(),
82 );
83
84 info!(
85 "Starting autoconnect on port: {} router_port: {} ({})",
86 port,
87 router_port,
88 logging::parallelism_banner()
89 );
90
91 let router_app_state = app_state.clone();
92 let mut builder = Server::build()
93 .bind("autoconnect", ("0.0.0.0", port), move || {
94 let app = build_app!(app_state, config);
95 HttpService::build()
96 .finish(map_config(app, |_| AppConfig::default()))
99 .tcp()
100 })?
101 .bind("autoconnect-router", ("0.0.0.0", router_port), move || {
102 let app = build_app!(router_app_state, config_router);
103 HttpService::build()
104 .finish(map_config(app, |_| AppConfig::default()))
106 .tcp()
107 })?;
108 if let Some(max_connections) = actix_max_connections {
109 builder = builder.max_concurrent_connections(max_connections);
110 }
111 if let Some(workers) = actix_workers {
112 builder = builder.workers(workers);
113 }
114 builder.run().await?;
115
116 info!("Shutting down autoconnect");
117 Ok(())
118}