Skip to main content

Crate zenkey_fleet

Crate zenkey_fleet 

Source
Expand description

Fleet engine for keyspace-v2 tooling (issue #15).

The shared core of zenctl and zengui: everything a bus explorer needs that is not presentation, in five layers — see The map below. The RFC 05 §2.1 fan-in discipline lives in exactly one place (bus::query::fleet_get, moved verbatim from zenctl — target All, consolidation None, attribution by the reply’s own key); the liveliness roster, registry-slice sets, and the schema-aware decode seam build on it.

Sessions opened here are deliberately un-namespaced (RFC 09 §5): an explorer sees the wire as it really is, full keys included — that is what lets it spot a leak. Do not “fix” this by setting a namespace.

§The map

Five strata, and the arrow between them only ever points one way. A sample enters at the top and leaves at the bottom as something a frontend can draw:

  bus/     holds a session      →  observations
  model/   holds values         →  meaning
  judge/   holds meaning        →  verdicts
  report/  the serialized shapes every layer above hands out
  tape/    traffic as a thing: captured, replayed, manufactured, timed
  • bus — everything whose job needs a live session. session, query, monitor, write, serve, admin, scout, seed, blob, roster, discover, producer, body. The RFC 05 §2.1 fan-in discipline lives here exactly once, in bus::query::fleet_get (moved verbatim from zenctl — target All, consolidation None, attribution by the reply’s own key), and everything in the layer that asks the fleet a question goes through it. This layer returns observations and never a verdict about one.

    Its event sources are Streams (#343), not only recv loops: EventStream::into_stream, SeededSubscriber (a direct impl), RosterWatch::changes, and a stream() on ScoutStream, Responder, MockResponder and MatchingEvents. The last four borrow rather than consume, because the &self receiver is what lets a query be answered while its stream is held and a scout be stopped after one; a blanket impl Stream would have taken &mut self and spent that. The recv/next methods stay — a loop is still the clearer shape for a drain that also selects on something else, and every consumer in this workspace does.

    watchdog is the one that is not a Stream but a Straw (#397): it yields transitions and returns a WatchdogSummary, with the acknowledged monitor teardown between the two. That is a shape Stream has no room for, and the only reason this crate speaks a second streaming vocabulary at all.

  • model — everything that can do its job from values already in hand. facts, registry, project, stats, tree, skeleton, diff, decode, retain, plus the two mechanisms every long-running projection shares (bounded, examples). Nothing here takes a session, and that is load-bearing: it is what lets a frontend replay a .zrec through the same projections it runs live.

  • judge — everything that takes a position. doctor, expect, condition, field, why, cutover, retired, budget, and judge::common for the vocabulary they share. The honesty rules (RFC 13, v1.24) bite hardest here, so the layer states them once.

  • report — every serde-pinned wire shape in the crate, split by domain. Its module doc carries the placement rule, which is the answer to “where does this struct go?” whenever the struct has a Serialize on it.

  • tape — traffic as a thing rather than an event. record, ingest, generate, synth, bench. It sits beside the others rather than under them because it both reads from the bus and writes back to it.

Placing a new module. Ask, in order: does it need a session (bus/), can it answer from values in hand (model/), does it say whether something is wrong (judge/), does it turn a stream into a recording or back (tape/)? A new serde-pinned struct is not a module question at all — it goes to report, by the rule stated there.

What is deliberately not here: configuration. Where the operator keeps their connection contexts is zenkey-explorer-config’s job; this crate has no stratum for ~/.config, and forcing dirs and toml on a library consumer so two binaries could read a TOML file was the tell.

Re-exports§

pub use bus::body::BodySource;decode
pub use bus::body::PrepareMode;decode
pub use bus::body::PrepareSpec;decode
pub use bus::body::PreparedBody;decode
pub use bus::body::encode_encoding;decode
pub use bus::body::prepare_publish;decode
pub use bus::body::prepare_request;decode
pub use judge::condition::CondWindow;decode
pub use judge::condition::Condition;decode
pub use judge::condition::DoctorWatch;decode
pub use judge::condition::Eval;decode
pub use judge::condition::RuleState;decode
pub use judge::condition::WatchdogSpec;decode
pub use judge::condition::watchdog;decode
pub use judge::doctor::DoctorSpec;decode
pub use judge::doctor::run_doctor;decode
pub use judge::expect::ExpectSpec;decode
pub use judge::expect::QosCheck;decode
pub use judge::expect::run_expect;decode
pub use judge::field::DeclaredPaths;decode
pub use judge::field::FieldObservation;decode
pub use judge::field::FieldSpec;decode
pub use judge::field::KeyFieldContext;decode
pub use judge::field::KeyFields;decode
pub use judge::field::PathStats;decode
pub use judge::field::run_field;decode
pub use model::decode::DEFAULT_MAX_PRODUCERS;decode
pub use model::decode::DecodedSample;decode
pub use model::decode::DescribedSchema;decode
pub use model::decode::Rendering;decode
pub use model::decode::SchemaStore;decode
pub use model::decode::Sealed;decode
pub use model::decode::StoreBounds;decode
pub use model::decode::decode_sample;decode
pub use model::decode::prewarm;decode
pub use model::decode::schema_drift;decode
pub use model::decode::schema_dump;decode
pub use model::decode::schemas_for_type;decode
pub use model::decode::totality_gaps;decode
pub use tape::generate::GenPattern;decode
pub use tape::generate::GenSpec;decode
pub use tape::generate::MockProducer;decode
pub use tape::generate::build_plan;decode
pub use tape::generate::run_gen;decode
pub use tape::generate::serve_describe;decode
pub use tape::generate::synthetic_marker;decode
pub use tape::synth::Synth;decode
pub use bus::admin::AdminEntry;
pub use bus::admin::admin_doc_omits_loopback;
pub use bus::admin::admin_get;
pub use bus::admin::admin_get_within;
pub use bus::admin::declared_entities;
pub use bus::admin::origin_attachments;
pub use bus::admin::render_dot;
pub use bus::admin::routers;
pub use bus::admin::state_coverage;
pub use bus::admin::storages;
pub use bus::admin::topology;
pub use bus::blob::BlobFetchSpec;blob
pub use bus::blob::FETCH_PRIORITY;blob
pub use bus::blob::blob_fetch;blob
pub use bus::blob::blob_probe;blob
pub use bus::blob::blob_tree_index;blob
pub use bus::blob::BlobTarget;
pub use bus::blob::blob_list;
pub use bus::blob::declared_by;
pub use bus::discover::AliveToken;
pub use bus::discover::discover_bases;
pub use bus::monitor::EventStream;
pub use bus::monitor::FleetEvent;
pub use bus::monitor::Monitor;
pub use bus::monitor::MonitorCore;
pub use bus::monitor::MonitorSpec;
pub use bus::monitor::SampleSource;
pub use bus::monitor::SampleView;
pub use bus::monitor::StampProvenance;
pub use bus::monitor::StreamItem;
pub use bus::monitor::WatchId;
pub use bus::producer::BringUp;
pub use bus::producer::LiveProducer;
pub use bus::producer::ReservedError;
pub use bus::producer::Responder;
pub use bus::query::Answer;
pub use bus::query::DEFAULT_MAX_REPLIES;
pub use bus::query::FetchOutcome;
pub use bus::query::FetchSpec;
pub use bus::query::FetchedValue;
pub use bus::query::FleetAnswer;
pub use bus::query::GetOpts;
pub use bus::query::RepeatingQuery;
pub use bus::query::RepeatingRegistry;
pub use bus::query::ServedSlice;
pub use bus::query::StateSample;
pub use bus::query::declare_repeating;
pub use bus::query::declare_repeating_any;
pub use bus::query::fetch_stored;
pub use bus::query::fetch_value;
pub use bus::query::fleet_get;
pub use bus::query::fleet_registry;
pub use bus::query::fleet_registry_by_origin;
pub use bus::query::fleet_registry_raw;
pub use bus::query::state_snapshot;
pub use bus::roster::BridgeMatch;
pub use bus::roster::RosterChange;
pub use bus::roster::RosterWatch;
pub use bus::roster::apply_token;
pub use bus::roster::bridge_resolve;
pub use bus::roster::node_info;
pub use bus::roster::node_rows;
pub use bus::roster::roster;
pub use bus::roster::token_identity;
pub use bus::scout::ScoutStream;
pub use bus::scout::scout;
pub use bus::seed::SeedItem;
pub use bus::seed::SeedPolicy;
pub use bus::seed::SeededSubscriber;
pub use bus::seed::seed_subscribe;
pub use bus::serve::MockResponder;
pub use bus::serve::ServedQuery;
pub use bus::serve::declare_responder;
pub use bus::session::Fleet;
pub use bus::session::OPEN_TIMEOUT;
pub use bus::session::OpenFailure;
pub use bus::session::open;
pub use bus::session::open_reporting;
pub use bus::session::open_reporting_within;
pub use bus::session::open_with_config;
pub use bus::write::CallSpec;
pub use bus::write::CallTarget;
pub use bus::write::MatchingEvents;
pub use bus::write::Publication;
pub use bus::write::RetireClass;
pub use bus::write::call;
pub use bus::write::check_retire;
pub use bus::write::declare_publication;
pub use judge::budget::BudgetObservation;
pub use judge::budget::join_budget;
pub use judge::common::EXPANSION_CAP;
pub use judge::common::data_plane_scopes;
pub use judge::common::new_prefix;
pub use model::bounded::DEFAULT_MAX_KEYS;
pub use model::facts::ClassKind;
pub use model::facts::OriginKind;
pub use model::facts::SubjectFacts;
pub use model::facts::V1Facts;
pub use model::registry::SliceSource;
pub use model::registry::UnionOutcome;
pub use model::skeleton::DeclRef;
pub use model::skeleton::Evidence;
pub use model::skeleton::NodeStats;
pub use model::skeleton::SkeletonChunk;
pub use model::skeleton::SkeletonCoverage;
pub use model::skeleton::SkeletonNode;
pub use model::skeleton::merge;
pub use model::tree::TreeNode;
pub use model::tree::TreeRow;
pub use model::tree::TreeRows;
pub use model::decode::OBSERVE_LIMIT;decode
pub use model::decode::structural;decode
pub use model::decode::structural_value;decode
pub use tape::record::rfc3339_now;
pub use judge::condition::SilenceEvidence;decode
pub use judge::condition::TickEvidence;decode
pub use judge::condition::judge_doctor_check;decode
pub use judge::condition::judge_origin_down;decode
pub use judge::retired::EntryEvidence;
pub use error::BoxedCause;
pub use error::Error;
pub use error::Result;
pub use error::one_line;
pub use judge::field::DEFAULT_MAX_PATHS;decode
pub use judge::why::is_cause;decode
pub use judge::cutover::run_cutover;
pub use judge::cutover::scope_note as cutover_scope_note;
pub use judge::retired::run_retired;
pub use judge::retired::scope_note as retired_scope_note;
pub use judge::why::StoredLookup;
pub use judge::why::StoredValue;
pub use judge::why::WhyInputs;
pub use judge::why::WhySpec;
pub use judge::why::WireWatch;
pub use judge::why::run_why;
pub use model::diff::ByteDiff;
pub use model::diff::Change;
pub use model::diff::ValueDiff;
pub use model::diff::byte_diff;
pub use model::diff::diff as value_diff;
pub use model::facts::FactsCache;
pub use model::facts::KeyDescription;
pub use model::facts::KeyFacts;
pub use model::facts::KeyShape;
pub use model::facts::Registration;
pub use model::facts::describe_key;
pub use model::registry::SliceSet;
pub use model::retain::RetentionBudget;
pub use model::retain::RetentionStats;
pub use model::skeleton::MergedNode;
pub use model::skeleton::NodeStatus;
pub use model::skeleton::Skeleton;
pub use model::stats::KeyStats;
pub use model::stats::StampClass;
pub use model::stats::StatsTable;
pub use model::tree::KeyTreeSnapshot;
pub use report::BenchReport;
pub use report::CallReport;
pub use report::CollapsedProducer;
pub use report::Coverage;
pub use report::CoverageRow;
pub use report::CutoverReport;
pub use report::DeclaredEntities;
pub use report::DeclaredEntity;
pub use report::DiscoveredBase;
pub use report::DoctorReport;
pub use report::DriftVerdict;
pub use report::EntityKind;
pub use report::ExpectReport;
pub use report::Fault;
pub use report::FieldReport;
pub use report::Freshness;
pub use report::GenPlanEntry;
pub use report::GenReport;
pub use report::HelloView;
pub use report::Judgement;
pub use report::LatencyReport;
pub use report::LatencySummary;
pub use report::NodeInfo;
pub use report::OriginAttachment;
pub use report::ProducerInfo;
pub use report::RecordReport;
pub use report::ReplayReport;
pub use report::RetiredReport;
pub use report::RouterInfo;
pub use report::Rung;
pub use report::RungAnswer;
pub use report::SampleRow;
pub use report::SchemaDrift;
pub use report::SchemaServer;
pub use report::SeedCoverage;
pub use report::StorageInfo;
pub use report::TopologyEdge;
pub use report::TopologyNode;
pub use report::TopologyReport;
pub use report::TotalityGap;
pub use report::ValueSource;
pub use report::WhyReport;
pub use report::WhyVerdict;
pub use report::ZrecHeader;
pub use report::judgement_exit_code;
pub use report::CondState;decode
pub use report::Transition;decode
pub use report::WatchdogSummary;decode
pub use tape::bench::BenchSpec;
pub use tape::bench::run_bench;
pub use tape::ingest::IngestRow;
pub use tape::ingest::StreamLine;
pub use tape::ingest::parse_row;
pub use tape::ingest::parse_stream_line;
pub use tape::record::RecordBounds;
pub use tape::record::ReplayEvent;
pub use tape::record::ReplaySpec;
pub use tape::record::ReplayTarget;
pub use tape::record::ZREC_VERSION;
pub use tape::record::ZrecItem;
pub use tape::record::ZrecReader;
pub use tape::record::ZrecSink;
pub use tape::record::ZrecSource;
pub use tape::record::ZrecWriter;
pub use tape::record::record;
pub use tape::record::replay;
pub use zblob;blob

Modules§

bus
Layer 1 — the bus. Everything that holds a session and talks to Zenoh.
error
The engine’s failure surface — one type, classified by what a caller can do about it.
judge
Layer 3 — the judges. Where an observation becomes a verdict.
model
Layer 2 — the model. What the observations mean, without asking the bus anything.
report
Typed reports — the shared contract between the engine and every frontend.
tape
Layer 4 — the tape. Traffic as a thing: captured, read back, manufactured, measured.

Structs§

Sender
The traits watchdog is driven through (#397), re-exported so a consumer needs them in scope without taking a direct dependency on sipper — and so the version this engine speaks is the one it hands out. A sender used to notify the progress of some Sipper.

Enums§

NotValidateddecode
The #159 conformance verdict, re-exported so frontends never reach around the engine for it. Why a payload was not validated. A reason is not a failure: most of these are ordinary states of a live bus (O4 — “not asked” is not “no”).
Verdictdecode
The #159 conformance verdict, re-exported so frontends never reach around the engine for it. Did the payload conform to its declared schema?

Constants§

DECLARE_TIMEOUT
How long a declaration may take before this crate calls it a failure.

Traits§

Sipper
The traits watchdog is driven through (#397), re-exported so a consumer needs them in scope without taking a direct dependency on sipper — and so the version this engine speaks is the one it hands out. A sipper is both a Stream that produces a bunch of progress and a Future that produces some final output.
Straw
The traits watchdog is driven through (#397), re-exported so a consumer needs them in scope without taking a direct dependency on sipper — and so the version this engine speaks is the one it hands out. A Straw is a Sipper that can fail.