docs(console): clarify API and persistence boundaries
This commit is contained in:
@@ -3,6 +3,15 @@
|
||||
//! Component bytes and WIT packages remain filesystem artifacts. This module
|
||||
//! persists service manifests, deployments, metrics, the bounded event
|
||||
//! history, and service-scoped Host KV entries.
|
||||
//!
|
||||
//! There are two write paths:
|
||||
//!
|
||||
//! - [`Persistence::sync`] stores a complete control-plane snapshot.
|
||||
//! - [`Persistence::record_invocations`] applies ordered metric deltas.
|
||||
//!
|
||||
//! Callers serialize these paths with the Console persistence mutex. Existing
|
||||
//! service counters are intentionally owned by the delta path; a snapshot
|
||||
//! updates their manifest and timestamp without replacing those counters.
|
||||
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
@@ -55,6 +64,10 @@ pub(crate) struct StoredKvEntry {
|
||||
}
|
||||
|
||||
/// One invocation's durable metric delta and event.
|
||||
///
|
||||
/// The caller assigns the event ID before enqueueing the update. A missing
|
||||
/// service row is tolerated because unregister may race queued telemetry; the
|
||||
/// event is still retained for diagnostics.
|
||||
pub(crate) struct InvocationUpdate {
|
||||
pub service_key: String,
|
||||
pub failed: bool,
|
||||
@@ -64,6 +77,10 @@ pub(crate) struct InvocationUpdate {
|
||||
}
|
||||
|
||||
/// Serialized access to the Toasty database connection.
|
||||
///
|
||||
/// This mutex protects a single Toasty [`Db`] handle. It is separate from the
|
||||
/// higher-level Console persistence mutex, which coordinates whole snapshot
|
||||
/// and invocation-delta operations before they acquire this connection.
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Persistence {
|
||||
db: Arc<Mutex<Db>>,
|
||||
@@ -131,6 +148,11 @@ impl Persistence {
|
||||
}
|
||||
|
||||
/// Atomically upserts a Console snapshot and prunes expired events.
|
||||
///
|
||||
/// The input is authoritative for services and deployments: rows omitted
|
||||
/// from those collections are removed. Events older than the oldest
|
||||
/// supplied retained event are pruned. Existing invocation counters are
|
||||
/// preserved because [`Self::record_invocations`] owns counter changes.
|
||||
pub async fn sync(
|
||||
&self,
|
||||
services: Vec<StoredService>,
|
||||
@@ -178,6 +200,8 @@ impl Persistence {
|
||||
}
|
||||
}
|
||||
|
||||
// Console stores events newest-first, so the last element is the
|
||||
// oldest ID that should survive snapshot pruning.
|
||||
if let Some(oldest_event) = events.last() {
|
||||
StoredEvent::filter(StoredEvent::fields().id().lt(oldest_event.id))
|
||||
.delete()
|
||||
@@ -217,6 +241,9 @@ impl Persistence {
|
||||
}
|
||||
|
||||
/// Atomically records invocation deltas and their bounded event history.
|
||||
///
|
||||
/// All supplied updates commit together. Metrics use saturating arithmetic
|
||||
/// so corrupted or extremely old databases cannot wrap counters.
|
||||
pub(crate) async fn record_invocations(
|
||||
&self,
|
||||
updates: Vec<InvocationUpdate>,
|
||||
@@ -268,6 +295,8 @@ impl Persistence {
|
||||
service_id: &str,
|
||||
entry_key: &str,
|
||||
) -> toasty::Result<Option<Vec<u8>>> {
|
||||
// The namespace is the stable service ID rather than its revision.
|
||||
// Deploying a new revision therefore preserves application state.
|
||||
let mut db = self.db.lock().await;
|
||||
Ok(
|
||||
StoredKvEntry::filter_by_service_id_and_entry_key(service_id, entry_key)
|
||||
@@ -284,6 +313,8 @@ impl Persistence {
|
||||
entry_key: String,
|
||||
value: Vec<u8>,
|
||||
) -> toasty::Result<()> {
|
||||
// Upsert makes a retry after an ambiguous Host timeout idempotent for
|
||||
// the same `(service_id, entry_key, value)`.
|
||||
let mut db = self.db.lock().await;
|
||||
StoredKvEntry::upsert_by_service_id_and_entry_key(service_id, entry_key)
|
||||
.value(value)
|
||||
|
||||
Reference in New Issue
Block a user