feat(tvix/nix-daemon): Initial skeleton for nix-daemon
The goal is to create a drop-in replacement nix-daemon that nix-cpp can use as a `daemon` store. Change-Id: Ie092047dcc6a24a3b8d8d1b808f3e6fd2c493bf2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12711 Reviewed-by: flokli <flokli@flokli.de> Tested-by: BuildkiteCI
This commit is contained in:
parent
eb2ca5f079
commit
9e294db820
6 changed files with 213 additions and 0 deletions
17
tvix/Cargo.lock
generated
17
tvix/Cargo.lock
generated
|
@ -2343,6 +2343,23 @@ dependencies = [
|
|||
"trybuild",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix-daemon"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"clap",
|
||||
"futures",
|
||||
"mimalloc",
|
||||
"nix-compat",
|
||||
"tokio",
|
||||
"tokio-listener",
|
||||
"tracing",
|
||||
"tvix-castore",
|
||||
"tvix-store",
|
||||
"tvix-tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nohash-hasher"
|
||||
version = "0.2.0"
|
||||
|
|
|
@ -75,6 +75,16 @@ rec {
|
|||
# File a bug if you depend on any for non-debug work!
|
||||
debug = internal.debugCrate { inherit packageId; };
|
||||
};
|
||||
"nix-daemon" = rec {
|
||||
packageId = "nix-daemon";
|
||||
build = internal.buildRustCrateWithFeatures {
|
||||
packageId = "nix-daemon";
|
||||
};
|
||||
|
||||
# Debug support which might change between releases.
|
||||
# File a bug if you depend on any for non-debug work!
|
||||
debug = internal.debugCrate { inherit packageId; };
|
||||
};
|
||||
"tvix-build" = rec {
|
||||
packageId = "tvix-build";
|
||||
build = internal.buildRustCrateWithFeatures {
|
||||
|
@ -7419,6 +7429,72 @@ rec {
|
|||
features = { };
|
||||
resolvedDefaultFeatures = [ "compile-tests" ];
|
||||
};
|
||||
"nix-daemon" = rec {
|
||||
crateName = "nix-daemon";
|
||||
version = "0.1.0";
|
||||
edition = "2021";
|
||||
crateBin = [
|
||||
{
|
||||
name = "nix-daemon";
|
||||
path = "src/bin/nix-daemon.rs";
|
||||
requiredFeatures = [ ];
|
||||
}
|
||||
];
|
||||
src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-daemon; };
|
||||
dependencies = [
|
||||
{
|
||||
name = "async-trait";
|
||||
packageId = "async-trait";
|
||||
}
|
||||
{
|
||||
name = "clap";
|
||||
packageId = "clap";
|
||||
features = [ "derive" "env" ];
|
||||
}
|
||||
{
|
||||
name = "futures";
|
||||
packageId = "futures";
|
||||
}
|
||||
{
|
||||
name = "mimalloc";
|
||||
packageId = "mimalloc";
|
||||
}
|
||||
{
|
||||
name = "nix-compat";
|
||||
packageId = "nix-compat";
|
||||
}
|
||||
{
|
||||
name = "tokio";
|
||||
packageId = "tokio";
|
||||
features = [ "fs" "macros" "net" "rt" "rt-multi-thread" "signal" ];
|
||||
}
|
||||
{
|
||||
name = "tokio-listener";
|
||||
packageId = "tokio-listener";
|
||||
}
|
||||
{
|
||||
name = "tracing";
|
||||
packageId = "tracing";
|
||||
}
|
||||
{
|
||||
name = "tvix-castore";
|
||||
packageId = "tvix-castore";
|
||||
}
|
||||
{
|
||||
name = "tvix-store";
|
||||
packageId = "tvix-store";
|
||||
}
|
||||
{
|
||||
name = "tvix-tracing";
|
||||
packageId = "tvix-tracing";
|
||||
}
|
||||
];
|
||||
features = {
|
||||
"default" = [ "otlp" ];
|
||||
"otlp" = [ "tvix-tracing/otlp" ];
|
||||
};
|
||||
resolvedDefaultFeatures = [ "default" "otlp" ];
|
||||
};
|
||||
"nohash-hasher" = rec {
|
||||
crateName = "nohash-hasher";
|
||||
version = "0.2.0";
|
||||
|
|
|
@ -29,6 +29,7 @@ members = [
|
|||
"nix-compat",
|
||||
"nix-compat-derive",
|
||||
"nix-compat-derive-tests",
|
||||
"nix-daemon",
|
||||
"serde",
|
||||
"store",
|
||||
"tracing",
|
||||
|
|
24
tvix/nix-daemon/Cargo.toml
Normal file
24
tvix/nix-daemon/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "nix-daemon"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.83"
|
||||
clap = { workspace = true, features = ["derive", "env"] }
|
||||
futures = { workspace = true }
|
||||
mimalloc = { workspace = true }
|
||||
nix-compat = { path = "../nix-compat" }
|
||||
tvix-castore = { path = "../castore" }
|
||||
tvix-store = { path = "../store" }
|
||||
tvix-tracing = { path = "../tracing" }
|
||||
tokio = { workspace = true, features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] }
|
||||
tokio-listener = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
default = ["otlp"]
|
||||
otlp = ["tvix-tracing/otlp"]
|
5
tvix/nix-daemon/default.nix
Normal file
5
tvix/nix-daemon/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{ depot, ... }:
|
||||
|
||||
depot.tvix.crates.workspaceMembers.nix-daemon.build.override {
|
||||
runTests = true;
|
||||
}
|
90
tvix/nix-daemon/src/bin/nix-daemon.rs
Normal file
90
tvix/nix-daemon/src/bin/nix-daemon.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
use clap::Parser;
|
||||
use mimalloc::MiMalloc;
|
||||
use std::error::Error;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio_listener::SystemOptions;
|
||||
use tvix_store::utils::{construct_services, ServiceUrlsGrpc};
|
||||
|
||||
#[global_allocator]
|
||||
static GLOBAL: MiMalloc = MiMalloc;
|
||||
|
||||
/// Run Nix-compatible store daemon backed by tvix.
|
||||
#[derive(Parser)]
|
||||
struct Cli {
|
||||
#[clap(flatten)]
|
||||
service_addrs: ServiceUrlsGrpc,
|
||||
|
||||
/// The address to listen on. Must be a unix domain socket.
|
||||
#[clap(flatten)]
|
||||
listen_args: tokio_listener::ListenerAddressLFlag,
|
||||
|
||||
#[cfg(feature = "otlp")]
|
||||
/// Whether to configure OTLP. Set --otlp=false to disable.
|
||||
#[arg(long, default_missing_value = "true", default_value = "true", num_args(0..=1), require_equals(true), action(clap::ArgAction::Set))]
|
||||
otlp: bool,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
let tracing_handle = {
|
||||
let mut builder = tvix_tracing::TracingBuilder::default();
|
||||
builder = builder.enable_progressbar();
|
||||
#[cfg(feature = "otlp")]
|
||||
{
|
||||
if cli.otlp {
|
||||
builder = builder.enable_otlp("tvix.daemon");
|
||||
}
|
||||
}
|
||||
builder.build()?
|
||||
};
|
||||
|
||||
tokio::select! {
|
||||
res = tokio::signal::ctrl_c() => {
|
||||
res?;
|
||||
if let Err(e) = tracing_handle.force_shutdown().await {
|
||||
eprintln!("failed to shutdown tracing: {e}");
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
res = run(cli) => {
|
||||
if let Err(e) = tracing_handle.shutdown().await {
|
||||
eprintln!("failed to shutdown tracing: {e}");
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let (_blob_service, _directory_service, _path_info_service, _nar_calculation_service) =
|
||||
construct_services(cli.service_addrs).await?;
|
||||
|
||||
let listen_address = cli.listen_args.listen_address.unwrap_or_else(|| {
|
||||
"/tmp/tvix-daemon.sock"
|
||||
.parse()
|
||||
.expect("invalid fallback listen address")
|
||||
});
|
||||
|
||||
let mut listener = tokio_listener::Listener::bind(
|
||||
&listen_address,
|
||||
&SystemOptions::default(),
|
||||
&cli.listen_args.listener_options,
|
||||
)
|
||||
.await?;
|
||||
|
||||
while let Ok((mut connection, _)) = listener.accept().await {
|
||||
tokio::spawn(async move {
|
||||
let ucred = connection
|
||||
.try_borrow_unix()
|
||||
.and_then(|u| u.peer_cred().ok());
|
||||
|
||||
// For now we just write the connected process credentials into the connection.
|
||||
let _ = connection
|
||||
.write_all(format!("Hello {:?}", ucred).as_bytes())
|
||||
.await;
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue