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",
|
"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]]
|
[[package]]
|
||||||
name = "nohash-hasher"
|
name = "nohash-hasher"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
|
@ -75,6 +75,16 @@ rec {
|
||||||
# File a bug if you depend on any for non-debug work!
|
# File a bug if you depend on any for non-debug work!
|
||||||
debug = internal.debugCrate { inherit packageId; };
|
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 {
|
"tvix-build" = rec {
|
||||||
packageId = "tvix-build";
|
packageId = "tvix-build";
|
||||||
build = internal.buildRustCrateWithFeatures {
|
build = internal.buildRustCrateWithFeatures {
|
||||||
|
@ -7419,6 +7429,72 @@ rec {
|
||||||
features = { };
|
features = { };
|
||||||
resolvedDefaultFeatures = [ "compile-tests" ];
|
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 {
|
"nohash-hasher" = rec {
|
||||||
crateName = "nohash-hasher";
|
crateName = "nohash-hasher";
|
||||||
version = "0.2.0";
|
version = "0.2.0";
|
||||||
|
|
|
@ -29,6 +29,7 @@ members = [
|
||||||
"nix-compat",
|
"nix-compat",
|
||||||
"nix-compat-derive",
|
"nix-compat-derive",
|
||||||
"nix-compat-derive-tests",
|
"nix-compat-derive-tests",
|
||||||
|
"nix-daemon",
|
||||||
"serde",
|
"serde",
|
||||||
"store",
|
"store",
|
||||||
"tracing",
|
"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