swactor-development-history/datastore/CHANGES.md

94 lines
4.9 KiB
Markdown
Raw Permalink Normal View History

2026-02-23 05:07:59 +00:00
# Unified Swactor Node with Datastore Dashboard Management
This document summarizes the changes on the `datastore-dashboard` branch.
## Problem
The swactor ecosystem had two separate binaries with no overlap:
- **`swactor-node`** (in `runtime-dashboard`) — distribution + dashboard, no datastore
- **`swactor-store-node`** (in `swactor-datastore`) — datastore + optional dashboard, no distribution
The dashboard's `/datastore` page was read-only (stats via SSE). The standalone datastore had its own management UI on a separate port. Neither binary gave you the full picture.
## Solution
A single batteries-included `swactor-node` crate that combines distribution, dashboard, and datastore. The dashboard now supports full datastore CRUD and lifecycle management. Old binaries remain as lightweight alternatives.
**Quick start:**
```
cargo xtask dev-node
```
Opens an iroh node with in-memory datastore on dashboard port 9090.
## What Changed
### New files
| File | Purpose |
|------|---------|
| `crates/swactor-node/Cargo.toml` | Unified node crate — depends on `runtime-dashboard`, `swactor-datastore`, and `distribution` |
| `crates/swactor-node/src/main.rs` | Combined binary with CLI: `--transport` (iroh default), `--storage-path`, `--no-datastore`, `--dashboard-port`, etc. Main loop merges distribution ticking with datastore GC/dissemination |
| `crates/datastore/src/bridge.rs` | `DatastoreBridge` — implements the dashboard's provider trait by sending actor messages and polling responses. `DatastoreNodeFactory` — spawns a fresh set of datastore actors on demand (used by the start/stop UI) |
### Modified files
**`Cargo.toml` (workspace root)**
- Added `"crates/swactor-node"` to workspace members.
**`crates/datastore/src/lib.rs`**
- Added `pub mod bridge` behind `#[cfg(feature = "node")]`.
**`crates/runtime-dashboard/src/datastore_collector.rs`**
- Expanded `DatastoreStatsProvider` trait with CRUD methods: `list_objects`, `get_object`, `get_data`, `put_data`, `delete_object`, `node_status`, `is_running`, `shutdown_datastore`. All have default impls returning `Err("not supported")` so existing `DatastoreMetrics` impl compiles unchanged.
- Added `ListScope` enum (`Local` / `Swarm`).
- Added `DatastoreFactory` trait for starting datastores from the dashboard.
**`crates/runtime-dashboard/src/lib.rs`**
- Added `datastore_factory` field to `DashboardHandle`.
- Added `set_datastore_factory()` and `datastore_provider()` methods.
- Threads factory through to `spawn_http_server()`.
**`crates/runtime-dashboard/src/server.rs`**
- Switched route matching from path-only to `(method, path)` tuples.
- Added 8 new API routes under `/api/datastore/`:
- `GET /api/datastore/list` — list objects (local or swarm scope)
- `GET /api/datastore/get` — object metadata + manifest
- `GET /api/datastore/data` — download raw bytes
- `GET /api/datastore/status` — node identity
- `POST /api/datastore/put` — upload data
- `POST /api/datastore/delete` — delete object
- `POST /api/datastore/start` — start datastore via factory
- `POST /api/datastore/shutdown` — stop datastore
- SSE `datastore` event now wraps the snapshot in an envelope: `{"is_running": bool, "snapshot": ...}`.
**`crates/runtime-dashboard/src/datastore_html.rs`**
- Full rewrite merging the monitoring dashboard (SSE-driven stats, event timeline, transfers) with the management UI from `ui_html.rs`:
- Upload panel (file input + optional name)
- Objects table with Origin column (local/remote badges) and action buttons (download, delete)
- Detail modal (hash, name, size, node, tags, chunk list)
- Toast notifications
- Lifecycle buttons: Start Datastore / Stop (shown based on `is_running` from SSE)
**`xtask/src/main.rs`**
- Added `dev-node` subcommand: builds and runs the unified node with happy defaults (iroh transport, port 9090, 3 actors, in-memory datastore).
- Options: `--port`, `--actors`, `--storage`, `--no-datastore`, `--tcp`, `--listen`, `--release`.
## Design Decisions
- **Iroh is the default transport.** TCP is available via `--tcp` flag or `--transport tcp`.
- **Datastore is on by default** (in-memory). Disable with `--no-datastore`.
- **Dashboard-only API** — no separate datastore HTTP port. The dashboard serves all CRUD routes.
- **Factory pattern** — even when started with `--no-datastore`, the dashboard can start/stop a datastore at runtime via `DatastoreNodeFactory`.
- **No circular dependencies** — `swactor-node` sits atop the dependency graph: `swactor-node` -> `runtime-dashboard` + `swactor-datastore[node]`. The bridge trait lives in `runtime-dashboard` with default method impls.
- **Old binaries kept** — `runtime-dashboard`'s `swactor-node` and `swactor-datastore`'s `swactor-store-node` still work as lightweight alternatives.
## Verification
```
cargo build -p swactor-node -p runtime-dashboard -p swactor-datastore # clean, 0 warnings
cargo test -p swactor -p distribution -p runtime-dashboard -p swactor-datastore -p swactor-node # 323 tests pass
```