diff options
Diffstat (limited to 'tvix/build')
-rw-r--r-- | tvix/build/Cargo.toml | 3 | ||||
-rw-r--r-- | tvix/build/src/bin/tvix-build.rs | 132 |
2 files changed, 135 insertions, 0 deletions
diff --git a/tvix/build/Cargo.toml b/tvix/build/Cargo.toml index 08102a66be50..289dda4d8c0d 100644 --- a/tvix/build/Cargo.toml +++ b/tvix/build/Cargo.toml @@ -5,13 +5,16 @@ edition = "2021" [dependencies] bytes = "1.4.0" +clap = { version = "4.0", features = ["derive", "env"] } itertools = "0.12.0" prost = "0.12.1" thiserror = "1.0.56" tokio = { version = "1.32.0" } +tokio-listener = { version = "0.2.2", features = [ "tonic010" ] } tonic = { version = "0.10.2", features = ["tls", "tls-roots"] } tvix-castore = { path = "../castore" } tracing = "0.1.37" +tracing-subscriber = { version = "0.3.16", features = ["json"] } url = "2.4.0" [dependencies.tonic-reflection] diff --git a/tvix/build/src/bin/tvix-build.rs b/tvix/build/src/bin/tvix-build.rs new file mode 100644 index 000000000000..ed36c8933cae --- /dev/null +++ b/tvix/build/src/bin/tvix-build.rs @@ -0,0 +1,132 @@ +use std::sync::Arc; + +use clap::Parser; +use clap::Subcommand; +use tokio_listener::Listener; +use tokio_listener::SystemOptions; +use tokio_listener::UserOptions; +use tonic::{self, transport::Server}; +use tracing::{info, Level}; +use tracing_subscriber::prelude::*; +use tvix_build::{ + buildservice, + proto::{build_service_server::BuildServiceServer, GRPCBuildServiceWrapper}, +}; +use tvix_castore::blobservice; +use tvix_castore::directoryservice; + +#[cfg(feature = "tonic-reflection")] +use tvix_build::proto::FILE_DESCRIPTOR_SET; +#[cfg(feature = "tonic-reflection")] +use tvix_castore::proto::FILE_DESCRIPTOR_SET as CASTORE_FILE_DESCRIPTOR_SET; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { + /// Whether to log in JSON + #[arg(long)] + json: bool, + + #[arg(long)] + log_level: Option<Level>, + + #[command(subcommand)] + command: Commands, +} +#[derive(Subcommand)] +enum Commands { + /// Runs the tvix-build daemon. + Daemon { + #[arg(long, short = 'l')] + listen_address: Option<String>, + + #[arg(long, env, default_value = "grpc+http://[::1]:8000")] + blob_service_addr: String, + + #[arg(long, env, default_value = "grpc+http://[::1]:8000")] + directory_service_addr: String, + + #[arg(long, env, default_value = "dummy://")] + build_service_addr: String, + }, +} + +#[tokio::main] +async fn main() -> Result<(), Box<dyn std::error::Error>> { + let cli = Cli::parse(); + + // configure log settings + let level = cli.log_level.unwrap_or(Level::INFO); + + let subscriber = tracing_subscriber::registry() + .with( + cli.json.then_some( + tracing_subscriber::fmt::Layer::new() + .with_writer(std::io::stderr.with_max_level(level)) + .json(), + ), + ) + .with( + (!cli.json).then_some( + tracing_subscriber::fmt::Layer::new() + .with_writer(std::io::stderr.with_max_level(level)) + .pretty(), + ), + ); + + tracing::subscriber::set_global_default(subscriber).expect("Unable to set global subscriber"); + + match cli.command { + Commands::Daemon { + listen_address, + blob_service_addr, + directory_service_addr, + build_service_addr, + } => { + // initialize stores + let blob_service = blobservice::from_addr(&blob_service_addr).await?; + let directory_service = directoryservice::from_addr(&directory_service_addr).await?; + + let build_service = buildservice::from_addr( + &build_service_addr, + Arc::from(blob_service), + Arc::from(directory_service), + ) + .await?; + + let listen_address = listen_address + .unwrap_or_else(|| "[::]:8000".to_string()) + .parse() + .unwrap(); + + let mut server = Server::builder(); + + #[allow(unused_mut)] + let mut router = server.add_service(BuildServiceServer::new( + GRPCBuildServiceWrapper::new(build_service), + )); + + #[cfg(feature = "tonic-reflection")] + { + let reflection_svc = tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build()?; + router = router.add_service(reflection_svc); + } + + info!(listen_address=%listen_address, "listening"); + + let listener = Listener::bind( + &listen_address, + &SystemOptions::default(), + &UserOptions::default(), + ) + .await?; + + router.serve_with_incoming(listener).await?; + } + } + + Ok(()) +} |