feat(sandokan-daemon): B1.3 — DaemonEngine + protocolo wire

DaemonEngine: implementación del trait Engine que delega a otro proceso
vía Unix socket. Materializa el patrón horizontal de sandokan (el
binario que arranca primero expone el engine; los demás se le suman).

- protocol.rs — DaemonRequest/DaemonResponse (espejan los métodos de
  Engine) + framing postcard length-prefixed (u32 LE + bytes), con
  MAX_FRAME 16 MiB defensivo.
- client.rs — DaemonEngine: stateless, un round-trip por llamada;
  is_reachable() para el probe de auto().
- server.rs — serve(engine, socket): envuelve cualquier Engine, una
  task por conexión, multi-request por conexión.

EngineError ahora es Serialize/Deserialize (viaja por el wire);
NotFound se propaga tipado a través del socket.

1 test de integración: roundtrip real DaemonEngine ↔ serve ↔ LocalEngine
(list vacío + NotFound propagado). cargo check --workspace verde.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-20 14:04:22 +00:00
parent cba3a9dd6e
commit b7d9d7abd9
8 changed files with 358 additions and 1 deletions
+22
View File
@@ -0,0 +1,22 @@
[package]
name = "sandokan-daemon"
description = "DaemonEngine: orquestador sandokan delegado a otro proceso vía Unix socket (protocolo postcard length-prefixed) + loop servidor."
version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true
publish.workspace = true
[dependencies]
sandokan-core = { path = "../sandokan-core" }
sandokan-lifecycle = { path = "../sandokan-lifecycle" }
async-trait = { workspace = true }
tokio = { workspace = true }
postcard = { workspace = true }
serde = { workspace = true }
ulid = { workspace = true }
tracing = { workspace = true }
[dev-dependencies]
sandokan-local = { path = "../sandokan-local" }
tempfile = { workspace = true }