tidaldb/tidalctl/src/commands/status.rs
jx12n ad4134e280 chore: doc consolidation, seven-dimension review fixes, and commit hooks
- 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)
2026-06-08 22:46:28 -06:00

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))
}