4.1 KiB
cbd: bundled server + client binary
Context and problem statement
crabidy-server and cbd-tui are separate binaries: the normal setup
runs a long-lived server and attaches TUIs to it. The user wants a
single binary cbd for the one-machine case: starting it starts the
server and connects the TUI to it. Everything else works exactly the
same — same configs, same gRPC wire, same features.
Assumptions (confirmed)
cbd-tui's config (cbd-tui.toml) already carries the server address; the server listens on a constant (0.0.0.0:50051).- Both mains are thin shells over module code: the server's
main.rsholds the command/message enums and the startup sequence; the TUI's holds tracing setup and two loops (orchestrate,run_ui). - The gRPC boundary stays: the bundled TUI talks to the in-process server over localhost exactly like a remote one ("works the same completely"). No in-process transport special-casing.
Decisions
D1 — Both binaries become libraries with thin mains
- crabidy-server:
playback,provider,rpcmove from bin modules to lib modules; the command/message enums and the startup sequence move into the lib (serve(addr)builds orchestrator, queue store, playback, rpc service and serves tonic onaddr).main.rskeeps only stderr tracing setup +serve(LISTEN_ADDR). - cbd-tui: gains
src/lib.rsexposingrun(config)(the two loops and their channels);main.rskeeps file-based tracing setup + config init +run. - Behavior-preserving: no logic changes, only module moves and
crabidy_server::→crate::path rewrites. All existing tests move along unchanged.
Not chosen: cbd spawning crabidy-server as a subprocess — that
needs the second binary installed, which is exactly what "a single
binary" is for.
D2 — cbd = start (or adopt) the server, then run the TUI
New tiny binary crate cbd:
- Tracing goes to the TUI's log file for both halves — the terminal belongs to the TUI, so the server's stderr logging would corrupt it.
- Spawn
crabidy_server::serve(LISTEN_ADDR)on a background task. If the port is already taken (AddrInUse— a standalone server is running), log and carry on: the TUI simply connects to the existing server. Any other server error before readiness is fatal. - Wait for readiness by polling a TCP connect against the configured server address (bounded retries with delay, then a clear error).
- Run the TUI exactly as
cbd-tuiwould, with the samecbd-tui.toml.
Quitting the TUI ends the process — and with it the in-process server. That is inherent to bundling and fine: the current queue is persisted continuously, so the next start restores it (the ≤200 ms persist debounce window is the same loss window as killing the standalone server).
D3 — Out of scope (explicitly)
- An in-process (channel) transport instead of localhost gRPC.
- Daemonizing:
cbdnever outlives its TUI. Users who want a persistent server keep runningcrabidy-server. - CLI subcommands (
cbd server,cbd attach, …) — later if wanted.
Structure
direction: right
cbd: "cbd (one binary)" {
boot: "main: file tracing,\nspawn server, wait, run TUI"
srv: "crabidy-server lib\nserve(addr)"
tui: "cbd-tui lib\nrun(config)"
boot -> srv: "tokio::spawn\n(AddrInUse → adopt)"
boot -> tui: "after TCP readiness"
tui -> srv: "localhost gRPC\n(unchanged wire)"
}
standalone: "crabidy-server bin\n(unchanged)"
remote: "cbd-tui bin\n(unchanged)"
remote -> standalone: "gRPC (remote setup\nkeeps working)"
Risks and open questions
- Port constant: the server listens on
0.0.0.0:50051and the TUI config defaults to localhost; if the user pointscbd-tui.tomlat a remote server,cbdstill starts a local one (and connects to the configured, remote one). Accepted:cbdis the one-machine tool. - Two log producers, one file: server and TUI layers share the bundled tracing subscriber; targets distinguish them.
- Open (future): a
--no-serverflag; graceful server shutdown (flush the persister) on TUI exit.