v0.3.6-pre.009-fix.001

This commit is contained in:
2026-09-01 16:17:22 +02:00
parent b861a1e3b8
commit 75b2d7e7f1
16 changed files with 366 additions and 233 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-job-backfill-lib/src/discovery.rs
// version: 4
// version: 5
/// Network-scoped identity of one discovered transaction candidate before canonical signature decoding.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
@@ -8,7 +8,7 @@ pub struct BackfillCandidateIdentity {
signature: crate::BackfillSignature,
}
impl BackfillCandidateIdentity {
impl crate::BackfillCandidateIdentity {
/// Creates one candidate identity from its logical network and encoded transaction signature.
#[must_use]
pub fn new(network: ksp_store_lib::RawNetworkId, signature: crate::BackfillSignature) -> Self {
@@ -31,20 +31,20 @@ impl BackfillCandidateIdentity {
/// One deterministic transaction candidate produced by bounded discovery.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BackfillCandidate {
identity: BackfillCandidateIdentity,
identity: crate::BackfillCandidateIdentity,
discovered_slot: std::option::Option<u64>,
}
impl BackfillCandidate {
impl crate::BackfillCandidate {
/// Creates one candidate from a network-scoped identity and optional discovery slot.
#[must_use]
pub fn new(identity: BackfillCandidateIdentity, discovered_slot: std::option::Option<u64>) -> Self {
pub fn new(identity: crate::BackfillCandidateIdentity, discovered_slot: std::option::Option<u64>) -> Self {
return Self { identity, discovered_slot };
}
/// Returns the network-scoped candidate identity.
#[must_use]
pub const fn identity(&self) -> &BackfillCandidateIdentity {
pub const fn identity(&self) -> &crate::BackfillCandidateIdentity {
return &self.identity;
}
@@ -70,7 +70,7 @@ pub enum BackfillDiscoveryBoundary {
AfterAnchorNotReached,
}
impl BackfillDiscoveryBoundary {
impl crate::BackfillDiscoveryBoundary {
/// Returns the stable diagnostic code for this boundary.
#[must_use]
pub const fn code(self) -> &'static str {
@@ -94,19 +94,19 @@ impl BackfillDiscoveryBoundary {
pub struct BackfillDiscovery {
network: ksp_store_lib::RawNetworkId,
scope_fingerprint: crate::BackfillScopeFingerprint,
candidates: std::vec::Vec<BackfillCandidate>,
candidates: std::vec::Vec<crate::BackfillCandidate>,
pages_fetched: usize,
boundary: BackfillDiscoveryBoundary,
boundary: crate::BackfillDiscoveryBoundary,
}
impl BackfillDiscovery {
impl crate::BackfillDiscovery {
/// Creates one internally validated bounded discovery value.
pub(crate) fn new(
network: ksp_store_lib::RawNetworkId,
scope_fingerprint: crate::BackfillScopeFingerprint,
candidates: std::vec::Vec<BackfillCandidate>,
candidates: std::vec::Vec<crate::BackfillCandidate>,
pages_fetched: usize,
boundary: BackfillDiscoveryBoundary,
boundary: crate::BackfillDiscoveryBoundary,
) -> Self {
return Self { network, scope_fingerprint, candidates, pages_fetched, boundary };
}
@@ -125,7 +125,7 @@ impl BackfillDiscovery {
/// Returns discovered candidates in deterministic processing order.
#[must_use]
pub fn candidates(&self) -> &[BackfillCandidate] {
pub fn candidates(&self) -> &[crate::BackfillCandidate] {
return self.candidates.as_slice();
}
@@ -137,7 +137,7 @@ impl BackfillDiscovery {
/// Returns the reason discovery stopped.
#[must_use]
pub const fn boundary(&self) -> BackfillDiscoveryBoundary {
pub const fn boundary(&self) -> crate::BackfillDiscoveryBoundary {
return self.boundary;
}
@@ -148,7 +148,7 @@ impl BackfillDiscovery {
}
}
impl std::fmt::Debug for BackfillDiscovery {
impl std::fmt::Debug for crate::BackfillDiscovery {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter
.debug_struct("BackfillDiscovery")
@@ -206,7 +206,7 @@ impl SignaturePageSource for ksp_onchain_transport_lib::HttpTransportPool {
pub async fn discover_backfill_candidates(
transport: &ksp_onchain_transport_lib::HttpTransportPool,
request: &crate::BackfillRequest,
) -> ksp_core_lib::Result<BackfillDiscovery> {
) -> ksp_core_lib::Result<crate::BackfillDiscovery> {
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
job_id = request.job_id().as_str(),
@@ -239,7 +239,7 @@ pub(crate) async fn discover_backfill_candidates_cancellable(
transport: &ksp_onchain_transport_lib::HttpTransportPool,
request: &crate::BackfillRequest,
cancellation: &crate::BackfillCancellationSignal,
) -> ksp_core_lib::Result<BackfillDiscovery> {
) -> ksp_core_lib::Result<crate::BackfillDiscovery> {
return discover_with_source(transport, request, std::option::Option::Some(cancellation)).await;
}
@@ -247,7 +247,7 @@ async fn discover_with_source<S>(
source: &S,
request: &crate::BackfillRequest,
cancellation: std::option::Option<&crate::BackfillCancellationSignal>,
) -> ksp_core_lib::Result<BackfillDiscovery>
) -> ksp_core_lib::Result<crate::BackfillDiscovery>
where
S: SignaturePageSource,
{
@@ -261,22 +261,22 @@ where
};
}
fn discover_explicit(request: &crate::BackfillRequest) -> ksp_core_lib::Result<BackfillDiscovery> {
fn discover_explicit(request: &crate::BackfillRequest) -> ksp_core_lib::Result<crate::BackfillDiscovery> {
let signatures = match request.scope().signatures() {
std::option::Option::Some(signatures) => signatures,
std::option::Option::None => return std::result::Result::Err(discovery_invalid("scope.signatures")),
};
let mut candidates = std::vec::Vec::with_capacity(signatures.len());
for signature in signatures {
let identity = BackfillCandidateIdentity::new(request.network().clone(), signature.clone());
candidates.push(BackfillCandidate::new(identity, std::option::Option::None));
let identity = crate::BackfillCandidateIdentity::new(request.network().clone(), signature.clone());
candidates.push(crate::BackfillCandidate::new(identity, std::option::Option::None));
}
return std::result::Result::Ok(BackfillDiscovery::new(
return std::result::Result::Ok(crate::BackfillDiscovery::new(
request.network().clone(),
request.scope_fingerprint(),
candidates,
0,
BackfillDiscoveryBoundary::ExplicitInput,
crate::BackfillDiscoveryBoundary::ExplicitInput,
));
}
@@ -284,7 +284,7 @@ async fn discover_older<S>(
source: &S,
request: &crate::BackfillRequest,
cancellation: std::option::Option<&crate::BackfillCancellationSignal>,
) -> ksp_core_lib::Result<BackfillDiscovery>
) -> ksp_core_lib::Result<crate::BackfillDiscovery>
where
S: SignaturePageSource,
{
@@ -304,10 +304,10 @@ where
let mut pages_fetched = 0_usize;
let boundary = loop {
if candidates.len() >= request.max_candidates() {
break BackfillDiscoveryBoundary::CandidateLimit;
break crate::BackfillDiscoveryBoundary::CandidateLimit;
}
if pages_fetched >= request.max_pages() {
break BackfillDiscoveryBoundary::PageLimit;
break crate::BackfillDiscoveryBoundary::PageLimit;
}
let remaining = request.max_candidates() - candidates.len();
let page_limit = std::cmp::min(request.page_size(), remaining);
@@ -345,33 +345,33 @@ where
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
if seen.insert(signature.clone()) {
let identity = BackfillCandidateIdentity::new(request.network().clone(), signature);
candidates.push(BackfillCandidate::new(identity, std::option::Option::Some(entry.slot)));
let identity = crate::BackfillCandidateIdentity::new(request.network().clone(), signature);
candidates.push(crate::BackfillCandidate::new(identity, std::option::Option::Some(entry.slot)));
if candidates.len() >= request.max_candidates() {
break;
}
}
}
if page_len < page_limit {
break BackfillDiscoveryBoundary::RpcBoundary;
break crate::BackfillDiscoveryBoundary::RpcBoundary;
}
let next_before = match next_before {
std::option::Option::Some(next_before) => next_before,
std::option::Option::None => break BackfillDiscoveryBoundary::RpcBoundary,
std::option::Option::None => break crate::BackfillDiscoveryBoundary::RpcBoundary,
};
if before.as_deref() == std::option::Option::Some(next_before.as_str()) {
return std::result::Result::Err(discovery_stalled());
}
before = std::option::Option::Some(next_before.as_str().to_owned());
};
return std::result::Result::Ok(BackfillDiscovery::new(request.network().clone(), request.scope_fingerprint(), candidates, pages_fetched, boundary));
return std::result::Result::Ok(crate::BackfillDiscovery::new(request.network().clone(), request.scope_fingerprint(), candidates, pages_fetched, boundary));
}
async fn discover_after<S>(
source: &S,
request: &crate::BackfillRequest,
cancellation: std::option::Option<&crate::BackfillCancellationSignal>,
) -> ksp_core_lib::Result<BackfillDiscovery>
) -> ksp_core_lib::Result<crate::BackfillDiscovery>
where
S: SignaturePageSource,
{
@@ -385,12 +385,12 @@ where
};
let until = anchor.as_str().to_owned();
let mut before = std::option::Option::<std::string::String>::None;
let mut nearest = std::collections::VecDeque::<BackfillCandidate>::with_capacity(request.max_candidates());
let mut nearest = std::collections::VecDeque::<crate::BackfillCandidate>::with_capacity(request.max_candidates());
let mut seen = std::collections::HashSet::<crate::BackfillSignature>::new();
let mut pages_fetched = 0_usize;
let boundary = loop {
if pages_fetched >= request.max_pages() {
break BackfillDiscoveryBoundary::AfterAnchorNotReached;
break crate::BackfillDiscoveryBoundary::AfterAnchorNotReached;
}
let config = ksp_onchain_transport_lib::SolanaSignaturesForAddressConfig::new(
before.clone(),
@@ -426,26 +426,26 @@ where
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
if seen.insert(signature.clone()) {
let identity = BackfillCandidateIdentity::new(request.network().clone(), signature);
nearest.push_back(BackfillCandidate::new(identity, std::option::Option::Some(entry.slot)));
let identity = crate::BackfillCandidateIdentity::new(request.network().clone(), signature);
nearest.push_back(crate::BackfillCandidate::new(identity, std::option::Option::Some(entry.slot)));
if nearest.len() > request.max_candidates() {
nearest.pop_front();
}
}
}
if page_len < request.page_size() {
break BackfillDiscoveryBoundary::RpcBoundary;
break crate::BackfillDiscoveryBoundary::RpcBoundary;
}
let next_before = match next_before {
std::option::Option::Some(next_before) => next_before,
std::option::Option::None => break BackfillDiscoveryBoundary::RpcBoundary,
std::option::Option::None => break crate::BackfillDiscoveryBoundary::RpcBoundary,
};
if before.as_deref() == std::option::Option::Some(next_before.as_str()) {
return std::result::Result::Err(discovery_stalled());
}
before = std::option::Option::Some(next_before.as_str().to_owned());
};
return std::result::Result::Ok(BackfillDiscovery::new(
return std::result::Result::Ok(crate::BackfillDiscovery::new(
request.network().clone(),
request.scope_fingerprint(),
nearest.into_iter().collect(),