v0.3.12-pre.008

This commit is contained in:
2026-09-09 20:42:32 +02:00
parent 90c266d68a
commit 2aa64cf0a4
17 changed files with 879 additions and 47 deletions

View File

@@ -1,16 +1,35 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/snapshot.rs
// version: 3
// version: 4
/// Runtime-neutral boxed future resolving to one newer concrete RAW transaction ingest Worker snapshot.
pub type RawTransactionIngestSnapshotFuture<'a> =
std::pin::Pin<std::boxed::Box<dyn std::future::Future<Output = crate::RawTransactionIngestSnapshot> + std::marker::Send + 'a>>;
/// Private latest-value processing-frontier projection emitted by the productive source task.
/// Source-neutral lifecycle state of the productive RAW transaction ingest source.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum RawTransactionIngestSourceState {
/// The productive source is active.
Active,
/// Transport is performing one bounded reconnect/replay attempt.
Reconnecting,
/// Cooperative source shutdown has started.
Closing,
/// The productive source closed cleanly.
Closed,
/// The productive source reached a terminal failure.
Failed,
}
/// Private latest-value source-processing projection emitted by the productive source task.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) struct RawTransactionIngestProcessingFrontierProjection {
hydration_pending: usize,
processing_frontier_slot: std::option::Option<u64>,
oldest_pending_slot: std::option::Option<u64>,
source_state: std::option::Option<crate::RawTransactionIngestSourceState>,
source_reconnect_total: u64,
source_replay_attempt_total: u64,
source_continuity_gap_total: u64,
}
impl crate::RawTransactionIngestProcessingFrontierProjection {
@@ -20,6 +39,10 @@ impl crate::RawTransactionIngestProcessingFrontierProjection {
hydration_pending: 0,
processing_frontier_slot: std::option::Option::None,
oldest_pending_slot: std::option::Option::None,
source_state: std::option::Option::None,
source_reconnect_total: 0,
source_replay_attempt_total: 0,
source_continuity_gap_total: 0,
};
}
@@ -29,7 +52,15 @@ impl crate::RawTransactionIngestProcessingFrontierProjection {
processing_frontier_slot: std::option::Option<u64>,
oldest_pending_slot: std::option::Option<u64>,
) -> Self {
return Self { hydration_pending, processing_frontier_slot, oldest_pending_slot };
return Self {
hydration_pending,
processing_frontier_slot,
oldest_pending_slot,
source_state: std::option::Option::None,
source_reconnect_total: 0,
source_replay_attempt_total: 0,
source_continuity_gap_total: 0,
};
}
/// Returns the number of source signals still pending hydration/admission processing.
@@ -46,6 +77,41 @@ impl crate::RawTransactionIngestProcessingFrontierProjection {
pub(crate) const fn oldest_pending_slot(&self) -> std::option::Option<u64> {
return self.oldest_pending_slot;
}
/// Returns a copy carrying the latest source reconnect/replay projection.
pub(crate) const fn with_source_continuity(
mut self,
source_state: std::option::Option<crate::RawTransactionIngestSourceState>,
source_reconnect_total: u64,
source_replay_attempt_total: u64,
source_continuity_gap_total: u64,
) -> Self {
self.source_state = source_state;
self.source_reconnect_total = source_reconnect_total;
self.source_replay_attempt_total = source_replay_attempt_total;
self.source_continuity_gap_total = source_continuity_gap_total;
return self;
}
/// 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;
}
/// Returns successful reconnects carried by this private projection.
pub(crate) const fn source_reconnect_total(&self) -> u64 {
return self.source_reconnect_total;
}
/// Returns replay-bearing reconnect attempts carried by this private projection.
pub(crate) const fn source_replay_attempt_total(&self) -> u64 {
return self.source_replay_attempt_total;
}
/// Returns proven replay-retention gaps carried by this private projection.
pub(crate) const fn source_continuity_gap_total(&self) -> u64 {
return self.source_continuity_gap_total;
}
}
/// Complete safe latest-value snapshot of one continuous RAW transaction ingest Worker.
@@ -71,6 +137,10 @@ pub struct RawTransactionIngestSnapshot {
hydration_pending: usize,
processing_frontier_slot: std::option::Option<u64>,
oldest_pending_slot: std::option::Option<u64>,
source_state: std::option::Option<crate::RawTransactionIngestSourceState>,
source_reconnect_total: u64,
source_replay_attempt_total: u64,
source_continuity_gap_total: u64,
}
impl crate::RawTransactionIngestSnapshot {
@@ -193,6 +263,30 @@ impl crate::RawTransactionIngestSnapshot {
pub const fn oldest_pending_slot(&self) -> std::option::Option<u64> {
return self.oldest_pending_slot;
}
/// 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> {
return self.source_state;
}
/// Returns successful automatic Yellowstone reconnects observed by this Worker run.
#[must_use]
pub const fn source_reconnect_total(&self) -> u64 {
return self.source_reconnect_total;
}
/// Returns Yellowstone replay-bearing reconnect attempts observed by this Worker run.
#[must_use]
pub const fn source_replay_attempt_total(&self) -> u64 {
return self.source_replay_attempt_total;
}
/// Returns replay retention gaps conservatively proven by Transport during this Worker run.
#[must_use]
pub const fn source_continuity_gap_total(&self) -> u64 {
return self.source_continuity_gap_total;
}
}
impl std::fmt::Debug for crate::RawTransactionIngestSnapshot {
@@ -219,6 +313,10 @@ impl std::fmt::Debug for crate::RawTransactionIngestSnapshot {
.field("hydration_pending", &self.hydration_pending)
.field("processing_frontier_slot", &self.processing_frontier_slot)
.field("oldest_pending_slot", &self.oldest_pending_slot)
.field("source_state", &self.source_state)
.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)
.finish();
}
}
@@ -335,6 +433,10 @@ impl crate::RawTransactionIngestSnapshotPublisher {
hydration_pending: 0,
processing_frontier_slot: std::option::Option::None,
oldest_pending_slot: std::option::Option::None,
source_state: std::option::Option::None,
source_reconnect_total: 0,
source_replay_attempt_total: 0,
source_continuity_gap_total: 0,
};
let (sender, receiver) = tokio::sync::watch::channel(snapshot.clone());
return (Self { sender, snapshot }, crate::RawTransactionIngestSnapshotSource { receiver });
@@ -427,6 +529,10 @@ impl crate::RawTransactionIngestSnapshotPublisher {
self.snapshot.hydration_pending = projection.hydration_pending();
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();
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();
return self.publish(state, admission_queue_depth, in_flight_persistence);
}
@@ -541,7 +647,7 @@ impl crate::RawTransactionIngestSnapshotPublisher {
sequence,
state,
health_for_state(state, self.snapshot.worker.health()),
activity_for_state(state, admission_queue_depth, in_flight_persistence, self.snapshot.hydration_pending),
activity_for_state(state, admission_queue_depth, in_flight_persistence, self.snapshot.hydration_pending, self.snapshot.source_state),
);
self.snapshot.worker = worker;
self.snapshot.admission_queue_depth = admission_queue_depth;
@@ -556,8 +662,17 @@ fn activity_for_state(
admission_queue_depth: usize,
in_flight_persistence: usize,
hydration_pending: usize,
source_state: std::option::Option<crate::RawTransactionIngestSourceState>,
) -> ksp_worker_api::WorkerActivity {
if admission_queue_depth > 0 || in_flight_persistence > 0 || hydration_pending > 0 {
if admission_queue_depth > 0
|| in_flight_persistence > 0
|| hydration_pending > 0
|| matches!(
source_state,
std::option::Option::Some(crate::RawTransactionIngestSourceState::Reconnecting)
| std::option::Option::Some(crate::RawTransactionIngestSourceState::Closing)
)
{
return ksp_worker_api::WorkerActivity::Active;
}
return match state {