- Eliminate the tidal/ self-contained doc mirror; docs now have two canonical homes (root *.md and docs/), with planning/specs/research/reviews moved up - Remove stale .agents/skills and .ai mirrors; canonicalize skills under .claude/ - Add pre-commit hook + scripts/check-docs.sh doc-guard + scripts/install-hooks.sh - Implement M0-M10 seven-dimension review findings across engine, net, server, and tidalctl (durability, replication, query, WAL, storage, CLI hardening)
64 lines
1.8 KiB
Rust
64 lines
1.8 KiB
Rust
//! `status` command -- report WAL state, checkpoint, and directory layout.
|
|
|
|
use serde::Serialize;
|
|
|
|
use crate::{
|
|
CliError, EXIT_DEGRADED,
|
|
commands::paths::DirsOutput,
|
|
json::render_json,
|
|
wal_state::{WalState, gather_wal_state},
|
|
};
|
|
|
|
/// `status` command output.
|
|
///
|
|
/// `wal` carries the gathered [`WalState`] on success, or an `{"error": ...}`
|
|
/// envelope when the WAL could not be inspected — modeled as an untagged enum
|
|
/// so serde emits exactly one of the two shapes without a discriminant tag.
|
|
#[derive(Serialize)]
|
|
struct StatusOutput<'a> {
|
|
version: &'a str,
|
|
build_hash: &'a str,
|
|
status: &'a str,
|
|
wal: WalField,
|
|
dirs: DirsOutput,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(untagged)]
|
|
enum WalField {
|
|
State(WalState),
|
|
Error { error: String },
|
|
}
|
|
|
|
pub(crate) fn run(base: &std::path::Path, pretty: bool) -> Result<(String, i32), CliError> {
|
|
let paths = tidaldb::Paths::new(base);
|
|
let wal_dir = paths.wal_dir();
|
|
|
|
let version = env!("CARGO_PKG_VERSION");
|
|
let build_hash = tidaldb::BUILD_HASH;
|
|
|
|
// Determine WAL state.
|
|
let wal_result = gather_wal_state(&wal_dir);
|
|
|
|
// An unreadable WAL (directory present but segments/checkpoint can't be
|
|
// read) is degraded, not a clean empty store: exit code 2, mirroring
|
|
// `diagnostics`. A script using `tidalctl status --path X && deploy` must
|
|
// not treat a corrupt WAL as success.
|
|
let (status, wal, exit_code) = match wal_result {
|
|
Ok(wal) if wal.segments > 0 => ("ok", WalField::State(wal), 0),
|
|
Ok(wal) => ("empty", WalField::State(wal), 0),
|
|
Err(e) => ("error", WalField::Error { error: e }, EXIT_DEGRADED),
|
|
};
|
|
|
|
let output = StatusOutput {
|
|
version,
|
|
build_hash,
|
|
status,
|
|
wal,
|
|
dirs: DirsOutput::new(&paths),
|
|
};
|
|
|
|
let rendered = render_json(&output, pretty)?;
|
|
Ok((rendered, exit_code))
|
|
}
|