v0.3.13-pre.010

This commit is contained in:
2026-09-10 21:02:29 +02:00
parent 0f8f38ff52
commit f636169783
16 changed files with 476 additions and 32 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/snapshot.rs
// version: 4
// version: 5
/// Runtime-neutral boxed future resolving to one newer concrete RAW transaction ingest Worker snapshot.
pub type RawTransactionIngestSnapshotFuture<'a> =
@@ -27,6 +27,10 @@ pub(crate) struct RawTransactionIngestProcessingFrontierProjection {
processing_frontier_slot: std::option::Option<u64>,
oldest_pending_slot: std::option::Option<u64>,
source_state: std::option::Option<crate::RawTransactionIngestSourceState>,
source_total: usize,
source_active: usize,
source_reconnecting: usize,
source_failed: usize,
source_reconnect_total: u64,
source_replay_attempt_total: u64,
source_continuity_gap_total: u64,
@@ -40,6 +44,10 @@ impl crate::RawTransactionIngestProcessingFrontierProjection {
processing_frontier_slot: std::option::Option::None,
oldest_pending_slot: std::option::Option::None,
source_state: std::option::Option::None,
source_total: 0,
source_active: 0,
source_reconnecting: 0,
source_failed: 0,
source_reconnect_total: 0,
source_replay_attempt_total: 0,
source_continuity_gap_total: 0,
@@ -57,6 +65,10 @@ impl crate::RawTransactionIngestProcessingFrontierProjection {
processing_frontier_slot,
oldest_pending_slot,
source_state: std::option::Option::None,
source_total: 0,
source_active: 0,
source_reconnecting: 0,
source_failed: 0,
source_reconnect_total: 0,
source_replay_attempt_total: 0,
source_continuity_gap_total: 0,
@@ -93,6 +105,35 @@ impl crate::RawTransactionIngestProcessingFrontierProjection {
return self;
}
/// Returns a copy carrying source-neutral multi-source lifecycle counts.
pub(crate) const fn with_source_counts(mut self, source_total: usize, source_active: usize, source_reconnecting: usize, source_failed: usize) -> Self {
self.source_total = source_total;
self.source_active = source_active;
self.source_reconnecting = source_reconnecting;
self.source_failed = source_failed;
return self;
}
/// Returns the configured logical source count carried by this private projection.
pub(crate) const fn source_total(&self) -> usize {
return self.source_total;
}
/// Returns the number of sources currently projected Active.
pub(crate) const fn source_active(&self) -> usize {
return self.source_active;
}
/// Returns the number of sources currently projected Reconnecting.
pub(crate) const fn source_reconnecting(&self) -> usize {
return self.source_reconnecting;
}
/// Returns the number of sources currently projected Failed.
pub(crate) const fn source_failed(&self) -> usize {
return self.source_failed;
}
/// Returns the latest source-neutral lifecycle state carried by this private projection.
pub(crate) const fn source_state(&self) -> std::option::Option<crate::RawTransactionIngestSourceState> {
return self.source_state;
@@ -138,6 +179,10 @@ pub struct RawTransactionIngestSnapshot {
processing_frontier_slot: std::option::Option<u64>,
oldest_pending_slot: std::option::Option<u64>,
source_state: std::option::Option<crate::RawTransactionIngestSourceState>,
source_total: usize,
source_active: usize,
source_reconnecting: usize,
source_failed: usize,
source_reconnect_total: u64,
source_replay_attempt_total: u64,
source_continuity_gap_total: u64,
@@ -264,6 +309,30 @@ impl crate::RawTransactionIngestSnapshot {
return self.oldest_pending_slot;
}
/// Returns the configured number of logical live sources for this Worker run.
#[must_use]
pub const fn source_total(&self) -> usize {
return self.source_total;
}
/// Returns the latest number of sources projected Active.
#[must_use]
pub const fn source_active(&self) -> usize {
return self.source_active;
}
/// Returns the latest number of sources projected Reconnecting.
#[must_use]
pub const fn source_reconnecting(&self) -> usize {
return self.source_reconnecting;
}
/// Returns the latest number of sources projected Failed.
#[must_use]
pub const fn source_failed(&self) -> usize {
return self.source_failed;
}
/// Returns the latest source-neutral lifecycle state when the productive source has started.
#[must_use]
pub const fn source_state(&self) -> std::option::Option<crate::RawTransactionIngestSourceState> {
@@ -314,6 +383,10 @@ impl std::fmt::Debug for crate::RawTransactionIngestSnapshot {
.field("processing_frontier_slot", &self.processing_frontier_slot)
.field("oldest_pending_slot", &self.oldest_pending_slot)
.field("source_state", &self.source_state)
.field("source_total", &self.source_total)
.field("source_active", &self.source_active)
.field("source_reconnecting", &self.source_reconnecting)
.field("source_failed", &self.source_failed)
.field("source_reconnect_total", &self.source_reconnect_total)
.field("source_replay_attempt_total", &self.source_replay_attempt_total)
.field("source_continuity_gap_total", &self.source_continuity_gap_total)
@@ -403,6 +476,7 @@ impl crate::RawTransactionIngestSnapshotPublisher {
pub(crate) fn new(
settings: &crate::RawTransactionIngestSettings,
lifecycle: &ksp_worker_api::WorkerLifecycle,
source_total: usize,
) -> (crate::RawTransactionIngestSnapshotPublisher, crate::RawTransactionIngestSnapshotSource) {
let worker = ksp_worker_api::WorkerSnapshot::new(
lifecycle.id().clone(),
@@ -434,6 +508,10 @@ impl crate::RawTransactionIngestSnapshotPublisher {
processing_frontier_slot: std::option::Option::None,
oldest_pending_slot: std::option::Option::None,
source_state: std::option::Option::None,
source_total,
source_active: 0,
source_reconnecting: 0,
source_failed: 0,
source_reconnect_total: 0,
source_replay_attempt_total: 0,
source_continuity_gap_total: 0,
@@ -449,7 +527,14 @@ impl crate::RawTransactionIngestSnapshotPublisher {
self.snapshot.worker.kind().clone(),
self.snapshot.worker.sequence(),
state,
health_for_state(state, self.snapshot.worker.health()),
health_for_state(
state,
self.snapshot.worker.health(),
self.snapshot.source_total,
self.snapshot.source_active,
self.snapshot.source_reconnecting,
self.snapshot.source_failed,
),
ksp_worker_api::WorkerActivity::Idle,
);
self.snapshot.worker = worker;
@@ -530,6 +615,12 @@ impl crate::RawTransactionIngestSnapshotPublisher {
self.snapshot.processing_frontier_slot = projection.processing_frontier_slot();
self.snapshot.oldest_pending_slot = projection.oldest_pending_slot();
self.snapshot.source_state = projection.source_state();
if projection.source_total() > 0 {
self.snapshot.source_total = projection.source_total();
self.snapshot.source_active = projection.source_active();
self.snapshot.source_reconnecting = projection.source_reconnecting();
self.snapshot.source_failed = projection.source_failed();
}
self.snapshot.source_reconnect_total = projection.source_reconnect_total();
self.snapshot.source_replay_attempt_total = projection.source_replay_attempt_total();
self.snapshot.source_continuity_gap_total = projection.source_continuity_gap_total();
@@ -646,7 +737,14 @@ impl crate::RawTransactionIngestSnapshotPublisher {
self.snapshot.worker.kind().clone(),
sequence,
state,
health_for_state(state, self.snapshot.worker.health()),
health_for_state(
state,
self.snapshot.worker.health(),
self.snapshot.source_total,
self.snapshot.source_active,
self.snapshot.source_reconnecting,
self.snapshot.source_failed,
),
activity_for_state(state, admission_queue_depth, in_flight_persistence, self.snapshot.hydration_pending, self.snapshot.source_state),
);
self.snapshot.worker = worker;
@@ -698,8 +796,18 @@ fn checked_optional_counter(current: u64, increment: bool, field: &'static str)
return checked_counter(current, field);
}
fn health_for_state(state: ksp_worker_api::WorkerState, previous: ksp_worker_api::WorkerHealth) -> ksp_worker_api::WorkerHealth {
fn health_for_state(
state: ksp_worker_api::WorkerState,
previous: ksp_worker_api::WorkerHealth,
source_total: usize,
source_active: usize,
source_reconnecting: usize,
source_failed: usize,
) -> ksp_worker_api::WorkerHealth {
return match state {
ksp_worker_api::WorkerState::Running if source_failed > 0 => ksp_worker_api::WorkerHealth::Unhealthy,
ksp_worker_api::WorkerState::Running if source_reconnecting > 0 => ksp_worker_api::WorkerHealth::Degraded,
ksp_worker_api::WorkerState::Running if source_total > 0 && source_active < source_total => ksp_worker_api::WorkerHealth::Degraded,
ksp_worker_api::WorkerState::Running => ksp_worker_api::WorkerHealth::Healthy,
ksp_worker_api::WorkerState::Stopping | ksp_worker_api::WorkerState::Stopped => previous,
ksp_worker_api::WorkerState::Faulted(_) => ksp_worker_api::WorkerHealth::Unhealthy,