v0.3.11-pre.007

This commit is contained in:
2026-09-08 11:32:41 +02:00
parent 355c5d1e9a
commit ed6c0ac10c
12 changed files with 1239 additions and 58 deletions

View File

@@ -0,0 +1,253 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/persistence.rs
// version: 1
#[derive(Clone, Copy)]
enum PortResponse {
Outcome(ksp_store_lib::RawEntityWriteOutcome, ksp_store_lib::RawObservationWriteOutcome),
Conflict,
StoreFailure,
}
struct FakePersistencePort {
calls: std::sync::atomic::AtomicUsize,
network: ksp_store_lib::RawNetworkId,
normal_mode_seen: std::sync::atomic::AtomicBool,
response: PortResponse,
}
impl FakePersistencePort {
fn new(network: ksp_store_lib::RawNetworkId, response: PortResponse) -> Self {
return Self {
calls: std::sync::atomic::AtomicUsize::new(0),
network,
normal_mode_seen: std::sync::atomic::AtomicBool::new(false),
response,
};
}
}
impl crate::RawTransactionIngestPersistencePort for FakePersistencePort {
fn network_matches(&self, network: &ksp_store_lib::RawNetworkId) -> bool {
return &self.network == network;
}
fn persist_acquisition<'a>(
&'a self,
_transaction: ksp_store_lib::RawTransaction,
_observation: ksp_store_lib::RawTransactionObservation,
mode: ksp_store_lib::RawTransactionAcquisitionMode,
) -> ksp_store_lib::StoreApiFuture<'a, ksp_store_lib::Result<ksp_store_lib::RawAcquisitionWriteOutcome>> {
self.calls.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
self.normal_mode_seen.store(mode == ksp_store_lib::RawTransactionAcquisitionMode::Normal, std::sync::atomic::Ordering::Release);
let response = self.response;
return std::boxed::Box::pin(async move {
return match response {
PortResponse::Outcome(entity, observation) => std::result::Result::Ok(ksp_store_lib::RawAcquisitionWriteOutcome::new(entity, observation)),
PortResponse::Conflict => std::result::Result::Err(ksp_core_lib::Error::new(ksp_store_lib::ERROR_CODE_RAW_CONFLICT, "synthetic conflict")),
PortResponse::StoreFailure => std::result::Result::Err(ksp_core_lib::Error::new(
ksp_core_lib::ErrorCode::new("synthetic_store", "write_failed"),
"synthetic remote failure text that must not escape",
)),
};
});
}
}
fn acquisition(network_name: &str, signature_byte: u8) -> std::option::Option<ksp_raw_transaction_lib::RawTransactionAcquisition> {
let network = match ksp_store_lib::RawNetworkId::new(network_name) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let signature = ksp_store_lib::RawTransactionSignature::new([signature_byte; 64]);
let material = ksp_raw_transaction_lib::RawTransactionMaterial::binary_base64(
network,
signature,
42,
std::option::Option::Some(1_700_000_000),
"AQID",
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
);
let transaction = match ksp_raw_transaction_lib::canonicalize_raw_transaction(material) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let provider = match ksp_store_lib::RawProvenanceCode::new("deterministic-harness") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let protocol = match ksp_store_lib::RawProvenanceCode::new("internal") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let method = match ksp_store_lib::RawProvenanceCode::new("persistence") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_700_000_000_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let provenance = ksp_store_lib::RawAcquisitionProvenance::new(provider, protocol, method, ksp_store_lib::RawAcquisitionOrigin::Live, received_at);
return std::option::Option::Some(ksp_raw_transaction_lib::assemble_raw_transaction_acquisition(
transaction,
ksp_store_lib::RawObservationKey::new([signature_byte; 32]),
provenance,
));
}
fn network(name: &str) -> std::option::Option<ksp_store_lib::RawNetworkId> {
return match ksp_store_lib::RawNetworkId::new(name) {
std::result::Result::Ok(value) => std::option::Option::Some(value),
std::result::Result::Err(_) => std::option::Option::None,
};
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_normal_mode_classifies_new_idempotent_and_purged_outcomes() {
let cases = [
(
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::Inserted, ksp_store_lib::RawObservationWriteOutcome::Inserted),
crate::RawTransactionIngestEntityPersistence::Inserted,
crate::RawTransactionIngestObservationPersistence::Inserted,
),
(
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::AlreadyPresent, ksp_store_lib::RawObservationWriteOutcome::Inserted),
crate::RawTransactionIngestEntityPersistence::AlreadyPresent,
crate::RawTransactionIngestObservationPersistence::Inserted,
),
(
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::AlreadyPresent, ksp_store_lib::RawObservationWriteOutcome::AlreadyPresent),
crate::RawTransactionIngestEntityPersistence::AlreadyPresent,
crate::RawTransactionIngestObservationPersistence::AlreadyPresent,
),
(
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::SkippedPurged, ksp_store_lib::RawObservationWriteOutcome::NotRecorded),
crate::RawTransactionIngestEntityPersistence::SkippedPurged,
crate::RawTransactionIngestObservationPersistence::NotRecorded,
),
];
for (index, (response, expected_entity, expected_observation)) in cases.into_iter().enumerate() {
let network = match network("mainnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let port = FakePersistencePort::new(network, response);
let acquisition = match acquisition("mainnet", index as u8 + 1) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let result = crate::persist_raw_transaction_ingest_acquisition(&port, acquisition).await;
assert!(result.is_ok());
let outcome = match result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(outcome.entity(), expected_entity);
assert_eq!(outcome.observation(), expected_observation);
assert!(port.normal_mode_seen.load(std::sync::atomic::Ordering::Acquire));
assert_eq!(port.calls.load(std::sync::atomic::Ordering::Acquire), 1);
}
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_content_conflict_maps_to_terminal_worker_code_without_remote_text() {
let network = match network("mainnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let port = FakePersistencePort::new(network, PortResponse::Conflict);
let acquisition = match acquisition("mainnet", 9) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let result = crate::persist_raw_transaction_ingest_acquisition(&port, acquisition).await;
let error = match result {
std::result::Result::Ok(_) => return,
std::result::Result::Err(value) => value,
};
assert_eq!(error.code(), crate::ERROR_CODE_RAW_TRANSACTION_INGEST_CONTENT_CONFLICT);
assert!(error.context().is_empty());
assert!(!std::format!("{error:?}").contains("synthetic conflict"));
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_store_failure_keeps_only_safe_lower_error_code() {
let network = match network("mainnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let port = FakePersistencePort::new(network, PortResponse::StoreFailure);
let acquisition = match acquisition("mainnet", 10) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let result = crate::persist_raw_transaction_ingest_acquisition(&port, acquisition).await;
let error = match result {
std::result::Result::Ok(_) => return,
std::result::Result::Err(value) => value,
};
assert_eq!(error.code(), crate::ERROR_CODE_RAW_TRANSACTION_INGEST_STORE_FAILED);
assert_eq!(error.context().len(), 2);
assert_eq!(error.context()[0].value(), "synthetic_store");
assert_eq!(error.context()[1].value(), "write_failed");
assert!(!std::format!("{error:?}").contains("synthetic remote failure text"));
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_rehydrated_or_impossible_store_outcomes_are_runtime_invalid() {
let cases = [
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::Rehydrated, ksp_store_lib::RawObservationWriteOutcome::Inserted),
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::Inserted, ksp_store_lib::RawObservationWriteOutcome::AlreadyPresent),
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::SkippedPurged, ksp_store_lib::RawObservationWriteOutcome::Inserted),
];
for (index, response) in cases.into_iter().enumerate() {
let network = match network("mainnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let port = FakePersistencePort::new(network, response);
let acquisition = match acquisition("mainnet", index as u8 + 20) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let result = crate::persist_raw_transaction_ingest_acquisition(&port, acquisition).await;
let error = match result {
std::result::Result::Ok(_) => continue,
std::result::Result::Err(value) => value,
};
assert_eq!(error.code(), crate::ERROR_CODE_RAW_TRANSACTION_INGEST_RUNTIME_INVALID);
assert_eq!(error.context().len(), 1);
assert_eq!(error.context()[0].value(), "persistence.store_outcome_invalid");
}
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_store_network_mismatch_is_rejected_before_write() {
let network = match network("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let port = FakePersistencePort::new(
network,
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::Inserted, ksp_store_lib::RawObservationWriteOutcome::Inserted),
);
let acquisition = match acquisition("mainnet", 30) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let result = crate::persist_raw_transaction_ingest_acquisition(&port, acquisition).await;
let error = match result {
std::result::Result::Ok(_) => return,
std::result::Result::Err(value) => value,
};
assert_eq!(error.code(), crate::ERROR_CODE_RAW_TRANSACTION_INGEST_RUNTIME_INVALID);
assert_eq!(error.context()[0].value(), "persistence.store_network_mismatch");
assert_eq!(port.calls.load(std::sync::atomic::Ordering::Acquire), 0);
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime.rs
// version: 3
// version: 4
struct ActiveTaskGuard {
active: std::sync::Arc<std::sync::atomic::AtomicUsize>,
@@ -251,3 +251,284 @@ async fn pre_005_supervisor_reaps_completed_source_task_and_still_joins_live_chi
assert_eq!(active.load(std::sync::atomic::Ordering::Acquire), 0);
return;
}
#[derive(Clone, Copy)]
enum RuntimePortResponse {
Conflict,
StoreFailure,
SuccessBlocked,
}
struct RuntimePersistencePort {
active: std::sync::atomic::AtomicUsize,
completed: std::sync::atomic::AtomicUsize,
max_active: std::sync::atomic::AtomicUsize,
network: ksp_store_lib::RawNetworkId,
normal_mode_seen: std::sync::atomic::AtomicBool,
notify: tokio::sync::Notify,
released: std::sync::atomic::AtomicBool,
response: RuntimePortResponse,
}
impl RuntimePersistencePort {
fn new(network: ksp_store_lib::RawNetworkId, response: RuntimePortResponse, released: bool) -> Self {
return Self {
active: std::sync::atomic::AtomicUsize::new(0),
completed: std::sync::atomic::AtomicUsize::new(0),
max_active: std::sync::atomic::AtomicUsize::new(0),
network,
normal_mode_seen: std::sync::atomic::AtomicBool::new(false),
notify: tokio::sync::Notify::new(),
released: std::sync::atomic::AtomicBool::new(released),
response,
};
}
fn release(&self) {
self.released.store(true, std::sync::atomic::Ordering::Release);
self.notify.notify_waiters();
return;
}
fn update_max_active(&self, current: usize) {
let mut observed = self.max_active.load(std::sync::atomic::Ordering::Acquire);
while current > observed {
match self.max_active.compare_exchange_weak(observed, current, std::sync::atomic::Ordering::AcqRel, std::sync::atomic::Ordering::Acquire) {
std::result::Result::Ok(_) => return,
std::result::Result::Err(value) => observed = value,
}
}
return;
}
}
impl crate::RawTransactionIngestPersistencePort for RuntimePersistencePort {
fn network_matches(&self, network: &ksp_store_lib::RawNetworkId) -> bool {
return &self.network == network;
}
fn persist_acquisition<'a>(
&'a self,
_transaction: ksp_store_lib::RawTransaction,
_observation: ksp_store_lib::RawTransactionObservation,
mode: ksp_store_lib::RawTransactionAcquisitionMode,
) -> ksp_store_lib::StoreApiFuture<'a, ksp_store_lib::Result<ksp_store_lib::RawAcquisitionWriteOutcome>> {
self.normal_mode_seen.store(mode == ksp_store_lib::RawTransactionAcquisitionMode::Normal, std::sync::atomic::Ordering::Release);
let response = self.response;
return std::boxed::Box::pin(async move {
if matches!(response, RuntimePortResponse::SuccessBlocked) {
let current = self.active.fetch_add(1, std::sync::atomic::Ordering::AcqRel) + 1;
self.update_max_active(current);
while !self.released.load(std::sync::atomic::Ordering::Acquire) {
self.notify.notified().await;
}
self.active.fetch_sub(1, std::sync::atomic::Ordering::AcqRel);
self.completed.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
return std::result::Result::Ok(ksp_store_lib::RawAcquisitionWriteOutcome::new(
ksp_store_lib::RawEntityWriteOutcome::Inserted,
ksp_store_lib::RawObservationWriteOutcome::Inserted,
));
}
if matches!(response, RuntimePortResponse::Conflict) {
self.completed.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
return std::result::Result::Err(ksp_core_lib::Error::new(ksp_store_lib::ERROR_CODE_RAW_CONFLICT, "synthetic conflict"));
}
self.completed.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
return std::result::Result::Err(ksp_core_lib::Error::new(
ksp_core_lib::ErrorCode::new("synthetic_store", "write_failed"),
"synthetic store failure",
));
});
}
}
fn runtime_ingress(network: &ksp_store_lib::RawNetworkId, signature_byte: u8) -> std::option::Option<crate::RawTransactionIngress> {
let signature = ksp_store_lib::RawTransactionSignature::new([signature_byte; 64]);
let material = ksp_raw_transaction_lib::RawTransactionMaterial::binary_base64(
network.clone(),
signature,
42,
std::option::Option::Some(1_700_000_000),
"AQID",
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
);
let provider = match ksp_store_lib::RawProvenanceCode::new("deterministic-harness") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let protocol = match ksp_store_lib::RawProvenanceCode::new("internal") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let method = match ksp_store_lib::RawProvenanceCode::new("runtime") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_700_000_000_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let provenance = ksp_store_lib::RawAcquisitionProvenance::new(provider, protocol, method, ksp_store_lib::RawAcquisitionOrigin::Live, received_at);
return std::option::Option::Some(crate::RawTransactionIngress { material, network: network.clone(), provenance, source_key: [signature_byte; 32] });
}
fn settings_with_persistence_concurrency(concurrency: usize) -> std::option::Option<crate::RawTransactionIngestSettings> {
let network = match ksp_store_lib::RawNetworkId::new("mainnet") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let worker_id = match ksp_worker_api::WorkerId::new("raw-ingest-runtime-persistence-001") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
return match crate::RawTransactionIngestSettings::new(network, worker_id, 8, concurrency, std::time::Duration::from_secs(5)) {
std::result::Result::Ok(value) => std::option::Option::Some(value),
std::result::Result::Err(_) => std::option::Option::None,
};
}
async fn wait_for_completed(port: &std::sync::Arc<RuntimePersistencePort>, expected: usize) -> bool {
for _ in 0..128 {
if port.completed.load(std::sync::atomic::Ordering::Acquire) == expected {
return true;
}
tokio::task::yield_now().await;
}
return port.completed.load(std::sync::atomic::Ordering::Acquire) == expected;
}
async fn wait_for_max_active(port: &std::sync::Arc<RuntimePersistencePort>, expected: usize) -> bool {
for _ in 0..128 {
if port.max_active.load(std::sync::atomic::Ordering::Acquire) == expected {
return true;
}
tokio::task::yield_now().await;
}
return port.max_active.load(std::sync::atomic::Ordering::Acquire) == expected;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_runtime_bounds_in_flight_store_persistence_to_configured_concurrency() {
let settings = match settings_with_persistence_concurrency(2) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let network = settings.network().clone();
let port = std::sync::Arc::new(RuntimePersistencePort::new(network.clone(), RuntimePortResponse::SuccessBlocked, false));
let runtime_port: super::PersistencePort = port.clone();
let handle = match super::start_foundation_with_port_and_source_spawner(
settings,
tokio::runtime::Handle::current(),
std::option::Option::Some(runtime_port),
move |children, _stop_receiver, admission_sender| {
let _abort_handle = children.spawn(async move {
for signature_byte in 1..=4 {
let ingress = match runtime_ingress(&network, signature_byte) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
if admission_sender.send(ingress).await.is_err() {
return;
}
}
return;
});
},
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert!(wait_for_max_active(&port, 2).await);
assert_eq!(port.active.load(std::sync::atomic::Ordering::Acquire), 2);
assert_eq!(port.max_active.load(std::sync::atomic::Ordering::Acquire), 2);
port.release();
assert!(wait_for_completed(&port, 4).await);
assert!(port.normal_mode_seen.load(std::sync::atomic::Ordering::Acquire));
assert_eq!(port.max_active.load(std::sync::atomic::Ordering::Acquire), 2);
assert!(handle.request_stop());
let terminal = handle.wait_terminal().await;
let terminal = match terminal {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(terminal, ksp_worker_api::WorkerState::Stopped);
assert_eq!(port.active.load(std::sync::atomic::Ordering::Acquire), 0);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_content_conflict_becomes_terminal_after_private_drain() {
let settings = match settings_with_persistence_concurrency(1) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let network = settings.network().clone();
let port = std::sync::Arc::new(RuntimePersistencePort::new(network.clone(), RuntimePortResponse::Conflict, true));
let runtime_port: super::PersistencePort = port.clone();
let handle = match super::start_foundation_with_port_and_source_spawner(
settings,
tokio::runtime::Handle::current(),
std::option::Option::Some(runtime_port),
move |children, _stop_receiver, admission_sender| {
let _abort_handle = children.spawn(async move {
let ingress = match runtime_ingress(&network, 11) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let _sent = admission_sender.send(ingress).await;
return;
});
},
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let terminal = handle.wait_terminal().await;
let terminal = match terminal {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(terminal, ksp_worker_api::WorkerState::Faulted(crate::ERROR_CODE_RAW_TRANSACTION_INGEST_CONTENT_CONFLICT));
assert_eq!(port.completed.load(std::sync::atomic::Ordering::Acquire), 1);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_007_store_failure_becomes_terminal_without_exposing_remote_error_text() {
let settings = match settings_with_persistence_concurrency(1) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let network = settings.network().clone();
let port = std::sync::Arc::new(RuntimePersistencePort::new(network.clone(), RuntimePortResponse::StoreFailure, true));
let runtime_port: super::PersistencePort = port.clone();
let handle = match super::start_foundation_with_port_and_source_spawner(
settings,
tokio::runtime::Handle::current(),
std::option::Option::Some(runtime_port),
move |children, _stop_receiver, admission_sender| {
let _abort_handle = children.spawn(async move {
let ingress = match runtime_ingress(&network, 12) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let _sent = admission_sender.send(ingress).await;
return;
});
},
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let terminal = handle.wait_terminal().await;
let terminal = match terminal {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(terminal, ksp_worker_api::WorkerState::Faulted(crate::ERROR_CODE_RAW_TRANSACTION_INGEST_STORE_FAILED));
assert_eq!(port.completed.load(std::sync::atomic::Ordering::Acquire), 1);
assert!(!std::format!("{handle:?}").contains("synthetic store failure"));
return;
}