2021-09-19 14:53:37 +00:00
|
|
|
use preserves_schema::Codec;
|
|
|
|
|
2022-01-19 13:40:50 +00:00
|
|
|
use std::io;
|
2021-08-09 13:19:00 +00:00
|
|
|
use std::path::PathBuf;
|
2021-07-03 07:03:52 +00:00
|
|
|
use std::sync::Arc;
|
2020-05-17 11:30:18 +00:00
|
|
|
|
2021-08-11 21:48:04 +00:00
|
|
|
use structopt::StructOpt;
|
2020-05-17 11:30:18 +00:00
|
|
|
|
2021-07-03 07:03:52 +00:00
|
|
|
use syndicate::actor::*;
|
|
|
|
use syndicate::dataspace::*;
|
2021-09-23 19:46:10 +00:00
|
|
|
use syndicate::enclose;
|
2021-08-28 16:50:55 +00:00
|
|
|
use syndicate::relay;
|
|
|
|
use syndicate::schemas::service;
|
|
|
|
use syndicate::schemas::transport_address;
|
2022-01-19 13:40:50 +00:00
|
|
|
use syndicate::trace;
|
2020-05-17 11:30:18 +00:00
|
|
|
|
2021-10-07 15:00:04 +00:00
|
|
|
use syndicate::value::Map;
|
2021-08-13 01:40:48 +00:00
|
|
|
use syndicate::value::NestedValue;
|
|
|
|
|
2021-09-28 10:53:11 +00:00
|
|
|
mod counter;
|
2021-09-24 14:15:26 +00:00
|
|
|
mod dependencies;
|
2021-08-27 14:19:14 +00:00
|
|
|
mod gatekeeper;
|
2021-09-19 14:53:37 +00:00
|
|
|
mod language;
|
2021-09-28 10:53:11 +00:00
|
|
|
mod lifecycle;
|
2021-08-27 14:19:14 +00:00
|
|
|
mod protocol;
|
2021-10-07 15:00:04 +00:00
|
|
|
mod script;
|
2021-08-27 14:19:14 +00:00
|
|
|
mod services;
|
2020-05-18 08:44:57 +00:00
|
|
|
|
2023-10-05 07:47:22 +00:00
|
|
|
#[cfg(feature = "jemalloc")]
|
2023-10-04 19:28:47 +00:00
|
|
|
#[global_allocator]
|
|
|
|
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
|
|
|
|
|
2021-08-28 16:50:55 +00:00
|
|
|
mod schemas {
|
|
|
|
include!(concat!(env!("OUT_DIR"), "/src/schemas/mod.rs"));
|
|
|
|
}
|
|
|
|
|
2023-01-28 21:45:48 +00:00
|
|
|
use language::Language;
|
2021-09-19 14:53:37 +00:00
|
|
|
use language::language;
|
2021-08-28 16:50:55 +00:00
|
|
|
use schemas::internal_services;
|
|
|
|
|
2021-08-11 21:48:04 +00:00
|
|
|
#[derive(Clone, StructOpt)]
|
|
|
|
struct ServerConfig {
|
2021-08-28 16:55:02 +00:00
|
|
|
#[structopt(short = "p", long = "port")]
|
2021-08-11 21:48:04 +00:00
|
|
|
ports: Vec<u16>,
|
|
|
|
|
|
|
|
#[structopt(short = "s", long = "socket")]
|
|
|
|
sockets: Vec<PathBuf>,
|
2021-08-25 14:11:15 +00:00
|
|
|
|
2021-08-25 14:11:24 +00:00
|
|
|
#[structopt(long)]
|
|
|
|
inferior: bool,
|
|
|
|
|
2021-08-25 14:11:15 +00:00
|
|
|
#[structopt(long)]
|
|
|
|
debt_reporter: bool,
|
2021-08-30 10:08:11 +00:00
|
|
|
|
|
|
|
#[structopt(short = "c", long)]
|
|
|
|
config: Vec<PathBuf>,
|
2021-10-05 10:41:26 +00:00
|
|
|
|
|
|
|
#[structopt(long)]
|
|
|
|
no_banner: bool,
|
2022-01-19 13:40:50 +00:00
|
|
|
|
|
|
|
#[structopt(short = "t", long)]
|
|
|
|
trace_file: Option<PathBuf>,
|
2021-08-11 21:48:04 +00:00
|
|
|
}
|
|
|
|
|
2020-05-17 11:30:18 +00:00
|
|
|
#[tokio::main]
|
2023-01-30 13:25:58 +00:00
|
|
|
async fn main() -> ActorResult {
|
2021-08-11 21:48:04 +00:00
|
|
|
let config = Arc::new(ServerConfig::from_args());
|
2021-08-09 13:19:00 +00:00
|
|
|
|
2021-10-05 10:41:26 +00:00
|
|
|
syndicate::convenient_logging()?;
|
|
|
|
|
|
|
|
if !config.no_banner && !config.inferior {
|
2020-06-01 08:02:39 +00:00
|
|
|
const BRIGHT_GREEN: &str = "\x1b[92m";
|
2020-06-01 08:12:18 +00:00
|
|
|
const RED: &str = "\x1b[31m";
|
2020-06-01 08:02:39 +00:00
|
|
|
const GREEN: &str = "\x1b[32m";
|
|
|
|
const NORMAL: &str = "\x1b[0m";
|
|
|
|
const BRIGHT_YELLOW: &str = "\x1b[93m";
|
2020-06-01 08:12:18 +00:00
|
|
|
|
2021-10-05 10:41:26 +00:00
|
|
|
eprintln!(r"{} ______ {}", GREEN, NORMAL);
|
|
|
|
eprintln!(r"{} / {}\_{}\{} ", GREEN, BRIGHT_GREEN, GREEN, NORMAL);
|
|
|
|
eprintln!(r"{} / {},{}__/{} \ {} ____ __", GREEN, RED, BRIGHT_GREEN, GREEN, NORMAL);
|
|
|
|
eprintln!(r"{} /{}\__/ \{},{} \{} _______ ______ ____/ /_/________ / /____", GREEN, BRIGHT_GREEN, RED, GREEN, NORMAL);
|
|
|
|
eprintln!(r"{} \{}/ \__/ {}/{} / ___/ / / / __ \/ __ / / ___/ __ \/ __/ _ \", GREEN, BRIGHT_GREEN, GREEN, NORMAL);
|
|
|
|
eprintln!(r"{} \ {}'{} \__{}/ {} _\_ \/ /_/ / / / / /_/ / / /__/ /_/ / /_/ __/", GREEN, RED, BRIGHT_GREEN, GREEN, NORMAL);
|
|
|
|
eprintln!(r"{} \____{}/{}_/ {} /____/\__, /_/ /_/\____/_/\___/\__/_/\__/\___/", GREEN, BRIGHT_GREEN, GREEN, NORMAL);
|
|
|
|
eprintln!(r" /____/");
|
|
|
|
eprintln!(r"");
|
2023-01-09 08:30:46 +00:00
|
|
|
eprintln!(r" {}version {} [syndicate {}]{}", BRIGHT_YELLOW, env!("CARGO_PKG_VERSION"), syndicate::syndicate_package_version(), NORMAL);
|
2021-10-05 10:41:26 +00:00
|
|
|
eprintln!(r"");
|
|
|
|
eprintln!(r" documentation & reference material: https://syndicate-lang.org/");
|
|
|
|
eprintln!(r" source code & bugs: https://git.syndicate-lang.org/syndicate-lang/syndicate-rs");
|
|
|
|
eprintln!(r"");
|
2020-06-01 08:02:39 +00:00
|
|
|
}
|
|
|
|
|
2021-07-21 21:29:53 +00:00
|
|
|
tracing::trace!("startup");
|
2020-06-01 08:12:18 +00:00
|
|
|
|
2022-01-19 13:40:50 +00:00
|
|
|
let trace_collector = config.trace_file.clone().map(
|
|
|
|
|p| Ok::<trace::TraceCollector, io::Error>(trace::TraceCollector::ascii(
|
|
|
|
io::BufWriter::new(std::fs::File::create(p)?))))
|
|
|
|
.transpose()?;
|
|
|
|
|
|
|
|
Actor::top(trace_collector, move |t| {
|
|
|
|
let server_config_ds = Cap::new(&t.create(Dataspace::new(Some(AnyValue::symbol("config")))));
|
|
|
|
let log_ds = Cap::new(&t.create(Dataspace::new(Some(AnyValue::symbol("log")))));
|
2021-08-28 16:50:55 +00:00
|
|
|
|
|
|
|
if config.inferior {
|
2021-08-28 16:55:08 +00:00
|
|
|
tracing::info!("inferior server instance");
|
2022-01-19 13:40:50 +00:00
|
|
|
t.spawn(Some(AnyValue::symbol("parent")), enclose!((server_config_ds) move |t| {
|
2021-10-07 15:00:04 +00:00
|
|
|
protocol::run_io_relay(t,
|
|
|
|
relay::Input::Bytes(Box::pin(tokio::io::stdin())),
|
|
|
|
relay::Output::Bytes(Box::pin(tokio::io::stdout())),
|
|
|
|
server_config_ds)
|
|
|
|
}));
|
2021-08-28 16:50:55 +00:00
|
|
|
}
|
|
|
|
|
2023-01-30 16:29:25 +00:00
|
|
|
let gatekeeper = Cap::guard(Language::arc(), t.create(
|
2021-10-07 15:00:04 +00:00
|
|
|
syndicate::entity(Arc::clone(&server_config_ds))
|
2023-02-08 17:01:38 +00:00
|
|
|
.on_asserted(gatekeeper::handle_resolves)));
|
|
|
|
gatekeeper::handle_binds(t, &server_config_ds)?;
|
2021-07-03 07:03:52 +00:00
|
|
|
|
2021-10-07 15:00:04 +00:00
|
|
|
let mut env = Map::new();
|
|
|
|
env.insert("config".to_owned(), AnyValue::domain(Arc::clone(&server_config_ds)));
|
|
|
|
env.insert("log".to_owned(), AnyValue::domain(Arc::clone(&log_ds)));
|
|
|
|
env.insert("gatekeeper".to_owned(), AnyValue::domain(Arc::clone(&gatekeeper)));
|
2021-08-28 16:50:55 +00:00
|
|
|
|
2021-09-24 14:15:26 +00:00
|
|
|
dependencies::boot(t, Arc::clone(&server_config_ds));
|
2021-10-07 15:00:04 +00:00
|
|
|
services::config_watcher::on_demand(t, Arc::clone(&server_config_ds));
|
|
|
|
services::daemon::on_demand(t, Arc::clone(&server_config_ds), Arc::clone(&log_ds));
|
2021-08-28 12:39:00 +00:00
|
|
|
services::debt_reporter::on_demand(t, Arc::clone(&server_config_ds));
|
2021-10-07 15:00:04 +00:00
|
|
|
services::tcp_relay_listener::on_demand(t, Arc::clone(&server_config_ds));
|
|
|
|
services::unix_relay_listener::on_demand(t, Arc::clone(&server_config_ds));
|
2021-08-28 16:50:55 +00:00
|
|
|
|
2021-08-27 14:19:14 +00:00
|
|
|
if config.debt_reporter {
|
2021-09-24 14:15:26 +00:00
|
|
|
server_config_ds.assert(t, language(), &service::RunService {
|
2022-01-07 16:18:00 +00:00
|
|
|
service_name: language().unparse(&internal_services::DebtReporter {
|
|
|
|
interval_seconds: (1.0).into(),
|
|
|
|
}),
|
2021-08-28 12:39:00 +00:00
|
|
|
});
|
2021-08-27 14:19:14 +00:00
|
|
|
}
|
|
|
|
|
2021-08-27 13:31:18 +00:00
|
|
|
for port in config.ports.clone() {
|
2021-09-24 14:15:26 +00:00
|
|
|
server_config_ds.assert(t, language(), &service::RunService {
|
2021-09-19 14:53:37 +00:00
|
|
|
service_name: language().unparse(&internal_services::TcpRelayListener {
|
|
|
|
addr: transport_address::Tcp {
|
|
|
|
host: "0.0.0.0".to_owned(),
|
|
|
|
port: (port as i32).into(),
|
2021-10-07 15:00:04 +00:00
|
|
|
},
|
|
|
|
gatekeeper: gatekeeper.clone(),
|
2021-09-19 14:53:37 +00:00
|
|
|
}),
|
2021-08-28 16:50:55 +00:00
|
|
|
});
|
2021-08-27 13:31:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for path in config.sockets.clone() {
|
2021-09-24 14:15:26 +00:00
|
|
|
server_config_ds.assert(t, language(), &service::RunService {
|
2021-09-19 14:53:37 +00:00
|
|
|
service_name: language().unparse(&internal_services::UnixRelayListener {
|
|
|
|
addr: transport_address::Unix {
|
|
|
|
path: path.to_str().expect("representable UnixListener path").to_owned(),
|
2021-10-07 15:00:04 +00:00
|
|
|
},
|
|
|
|
gatekeeper: gatekeeper.clone(),
|
2021-09-19 14:53:37 +00:00
|
|
|
}),
|
2021-08-28 16:50:55 +00:00
|
|
|
});
|
2021-08-27 13:31:18 +00:00
|
|
|
}
|
|
|
|
|
2021-08-30 10:08:11 +00:00
|
|
|
for path in config.config.clone() {
|
2021-09-24 14:15:26 +00:00
|
|
|
server_config_ds.assert(t, language(), &service::RunService {
|
2021-09-19 14:53:37 +00:00
|
|
|
service_name: language().unparse(&internal_services::ConfigWatcher {
|
|
|
|
path: path.to_str().expect("representable ConfigWatcher path").to_owned(),
|
2021-10-07 15:00:04 +00:00
|
|
|
env: internal_services::ConfigEnv(env.clone()),
|
2021-09-19 14:53:37 +00:00
|
|
|
}),
|
2021-08-30 10:08:11 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-01-19 13:40:50 +00:00
|
|
|
t.spawn(Some(AnyValue::symbol("logger")), enclose!((log_ds) move |t| {
|
2021-10-01 20:07:28 +00:00
|
|
|
let n_unknown: AnyValue = AnyValue::symbol("-");
|
|
|
|
let n_pid: AnyValue = AnyValue::symbol("pid");
|
|
|
|
let n_line: AnyValue = AnyValue::symbol("line");
|
|
|
|
let n_service: AnyValue = AnyValue::symbol("service");
|
|
|
|
let n_stream: AnyValue = AnyValue::symbol("stream");
|
|
|
|
let e = syndicate::during::entity(())
|
|
|
|
.on_message(move |(), _t, captures: AnyValue| {
|
2021-10-04 12:40:39 +00:00
|
|
|
if let Some(captures) = captures.value_owned().into_sequence() {
|
|
|
|
let mut captures = captures.into_iter();
|
|
|
|
let timestamp = captures.next()
|
|
|
|
.and_then(|t| t.value_owned().into_string())
|
|
|
|
.unwrap_or_else(|| "-".to_owned());
|
|
|
|
if let Some(mut d) = captures.next()
|
|
|
|
.and_then(|d| d.value_owned().into_dictionary())
|
|
|
|
{
|
|
|
|
let pid = d.remove(&n_pid).unwrap_or_else(|| n_unknown.clone());
|
|
|
|
let service = d.remove(&n_service).unwrap_or_else(|| n_unknown.clone());
|
|
|
|
let line = d.remove(&n_line).unwrap_or_else(|| n_unknown.clone());
|
|
|
|
let stream = d.remove(&n_stream).unwrap_or_else(|| n_unknown.clone());
|
|
|
|
let message = format!("{} {:?}[{:?}] {:?}: {:?}",
|
|
|
|
timestamp,
|
|
|
|
service,
|
|
|
|
pid,
|
|
|
|
stream,
|
|
|
|
line);
|
|
|
|
if d.is_empty() {
|
2021-10-07 19:28:20 +00:00
|
|
|
tracing::info!(target: "", "{}", message);
|
2021-10-04 12:40:39 +00:00
|
|
|
} else {
|
2021-10-07 19:28:20 +00:00
|
|
|
tracing::info!(target: "", "{} {:?}", message, d);
|
2021-10-04 12:40:39 +00:00
|
|
|
}
|
2021-10-01 20:07:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
.create_cap(t);
|
2021-10-07 15:00:04 +00:00
|
|
|
log_ds.assert(t, language(), &syndicate::schemas::dataspace::Observe {
|
2021-10-04 12:40:39 +00:00
|
|
|
pattern: syndicate_macros::pattern!(<log $ $>),
|
2021-10-01 20:07:28 +00:00
|
|
|
observer: e,
|
|
|
|
});
|
|
|
|
Ok(())
|
|
|
|
}));
|
|
|
|
|
2021-08-27 13:31:18 +00:00
|
|
|
Ok(())
|
|
|
|
}).await??;
|
2020-05-17 11:30:18 +00:00
|
|
|
|
2021-10-08 14:37:26 +00:00
|
|
|
wait_for_all_actors_to_stop(std::time::Duration::from_secs(2)).await;
|
|
|
|
|
2020-05-17 11:30:18 +00:00
|
|
|
Ok(())
|
|
|
|
}
|