diff --git a/README.md b/README.md index bbdf73a..c38dccb 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,27 @@ To simply run the server, the command is as follows $ ./relay ``` +To learn about any other tasks, the `--help` flag can be passed +```bash +$ ./relay --help +relay 0.1.0 +An activitypub relay + +USAGE: + relay [FLAGS] [OPTIONS] + +FLAGS: + -h, --help Prints help information + -j, --jobs-only Only process background jobs, do not start the relay server + -n, --no-jobs Only run the relay server, do not process background jobs + -u, --undo Undo whitelisting or blocking domains + -V, --version Prints version information + +OPTIONS: + -b ... A list of domains that should be blocked + -w ... A list of domains that should be whitelisted +``` + To add domains to the blocklist, use the `-b` flag and pass a list of domains ```bash $ ./relay -b asonix.dog blimps.xyz @@ -22,7 +43,12 @@ $ ./relay -uw asonix.dog blimps.xyz ``` Whitelisted domains are only checked against incoming activities if `WHITELIST_MODE` is enabled. -Blocks can be published in the nodeinfo metadata by settings `PUBLISH_BLOCKS` to true +Blocks can be published in the nodeinfo metadata by setting `PUBLISH_BLOCKS` to true + +For advanced setups, it may be useful to run the relay API and the background tasks in separate +processes, possibly on separate hosts. The `-j` and `-n` flags have been provided for this purpose. +By passing `-n`, a relay can be spawned that handles no deliveries. By passing `-j`, a relay will +not be spawned, but any deliveries existing in the database will be processed. ### Subscribing Mastodon admins can subscribe to this relay by adding the `/inbox` route to their relay settings. diff --git a/src/args.rs b/src/args.rs index 25c8dc9..952cd7a 100644 --- a/src/args.rs +++ b/src/args.rs @@ -9,8 +9,22 @@ pub struct Args { #[structopt(short, help = "A list of domains that should be whitelisted")] whitelists: Vec, - #[structopt(short, help = "Undo whitelisting or blocking these domains")] + #[structopt(short, long, help = "Undo whitelisting or blocking domains")] undo: bool, + + #[structopt( + short, + long, + help = "Only process background jobs, do not start the relay server" + )] + jobs_only: bool, + + #[structopt( + short, + long, + help = "Only run the relay server, do not process background jobs" + )] + no_jobs: bool, } impl Args { @@ -29,4 +43,12 @@ impl Args { pub fn undo(&self) -> bool { self.undo } + + pub fn jobs_only(&self) -> bool { + self.jobs_only + } + + pub fn no_jobs(&self) -> bool { + self.no_jobs + } } diff --git a/src/main.rs b/src/main.rs index a9e8bf0..169d515 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use actix::Arbiter; use actix_web::{ http::header::{ContentType, Expires}, middleware::Logger, @@ -92,6 +93,12 @@ async fn main() -> Result<(), anyhow::Error> { let args = Args::new(); + if args.jobs_only() && args.no_jobs() { + return Err(anyhow::Error::msg( + "Either the server or the jobs must be run", + )); + } + if !args.blocks().is_empty() || !args.whitelists().is_empty() { if args.undo() { db.remove_blocks(args.blocks()).await?; @@ -110,9 +117,26 @@ async fn main() -> Result<(), anyhow::Error> { let job_server = create_server(db.clone()); + if args.jobs_only() { + for _ in 0..num_cpus::get() { + let state = state.clone(); + let job_server = job_server.clone(); + + Arbiter::new().exec_fn(move || { + create_workers(state, job_server); + }); + } + actix_rt::signal::ctrl_c().await?; + return Ok(()); + } + + let no_jobs = args.no_jobs(); + let bind_address = config.bind_address(); HttpServer::new(move || { - create_workers(state.clone(), job_server.clone()); + if !no_jobs { + create_workers(state.clone(), job_server.clone()); + } App::new() .wrap(Logger::default()) diff --git a/src/notify.rs b/src/notify.rs index 6db4ec6..e2f5da1 100644 --- a/src/notify.rs +++ b/src/notify.rs @@ -9,7 +9,7 @@ use futures::{ use log::{debug, error, info, warn}; use std::sync::Arc; -async fn handle_notification(state: &State, notif: Notification) { +async fn handle_notification(state: State, notif: Notification) { match notif.channel() { "new_blocks" => { info!("Caching block of {}", notif.payload()); @@ -88,7 +88,7 @@ pub fn spawn(state: State, config: &crate::config::Config) -> Result<(), MyError }); while let Some(n) = stream.next().await { - handle_notification(&state, n).await; + actix::spawn(handle_notification(state.clone(), n)); } drop(client);