pub struct GASPSync<'a> {
pub last_interaction: u64,
pub unidirectional: bool,
/* private fields */
}Expand description
GASP sync orchestrator.
Coordinates between local GASPStorage and a GASPRemote peer to
synchronize overlay UTXOs. Supports paginated sync and unidirectional mode.
The lifetime 'a allows the storage and remote to borrow from their
environment (e.g., OverlayGASPStorage borrows from the Engine’s storage).
Fields§
§last_interaction: u64Score of last successful interaction with this peer.
unidirectional: boolIf true, only pull from remote — don’t push local UTXOs.
Implementations§
Source§impl<'a> GASPSync<'a>
impl<'a> GASPSync<'a>
Sourcepub fn new(
storage: Box<dyn GASPStorage + 'a>,
remote: Box<dyn GASPRemote + 'a>,
last_interaction: u64,
log_prefix: impl Into<String>,
unidirectional: bool,
) -> Self
pub fn new( storage: Box<dyn GASPStorage + 'a>, remote: Box<dyn GASPRemote + 'a>, last_interaction: u64, log_prefix: impl Into<String>, unidirectional: bool, ) -> Self
Create a new GASP sync orchestrator.
The ancestor fetcher is OFF by default. Use with_ancestor_fetcher to
opt in to chain-backed ancestry hydration (one-time-migration only).
Sourcepub fn with_graph_budget(self, budget: GraphBudget<'a>) -> Self
pub fn with_graph_budget(self, budget: GraphBudget<'a>) -> Self
Bound each graph’s walk by budget and DEFER a graph past it
(bsv-low #555): its partial walk is saved through
GASPStorage::save_deferred_graph, its UTXO is held below the
cursor like a failed one, the sync goes on to the next UTXO, and the
next sync that is served the UTXO RESUMES the walk from the record,
asking only what is still pending. Without a budget nothing is
deferred and sync is unchanged.
Sourcepub fn deferral_stats(&self) -> DeferralStats
pub fn deferral_stats(&self) -> DeferralStats
What the last sync did with deferred graphs (bsv-low #555).
Sourcepub fn graphs_attempted(&self) -> u64
pub fn graphs_attempted(&self) -> u64
How many UTXOs the sync set out to ingest (a new walk, a resume, or a
record held back): the peer served it work it did not hold. A sync
that attempted none was quiet (bsv-low #555, the delta fold’s D-M2:
a quiet sync never counts toward PEER_YIELDLESS_SYNCS_ALLOWED).
Sourcepub fn with_finalized_graph_hook(
self,
hook: Box<dyn FinalizedGraphHook + 'a>,
) -> Self
pub fn with_finalized_graph_hook( self, hook: Box<dyn FinalizedGraphHook + 'a>, ) -> Self
Have hook called after every completed incoming UTXO (bsv-low #552,
see FinalizedGraphHook). Without one sync is unchanged.
Sourcepub fn completed_cursor(&self) -> u64
pub fn completed_cursor(&self) -> u64
The cursor that is safe to persist if sync stopped RIGHT NOW (its
future dropped at a deadline; bsv-low #552). It is the gap guard’s
rule applied to completed scores: never above a completed output, and
strictly below the lowest score of
any UTXO of the current page not yet completed (the one in flight
included) and of any UTXO whose ingest failed, never below the cursor
the sync entered with. The remote serves score >= since, so the next
sync is served everything this one did not finish. After a completed
sync it equals last_interaction.
last_interaction itself is NOT safe after a drop: it is raised to
each UTXO’s score BEFORE that UTXO is ingested, for pagination.
Sourcepub fn graph_in_flight(&self) -> bool
pub fn graph_in_flight(&self) -> bool
Whether a graph was being fetched, walked or anchor-checked when sync
last stopped: true only after a sync future dropped mid-graph
(bsv-low #552). That graph’s nodes died with the storage adapter;
nothing of it was finalized.
Sourcepub fn discarded_graphs(&self) -> u64
pub fn discarded_graphs(&self) -> u64
How many graphs this orchestrator’s last sync discarded because
validate_graph_anchor REFUSED them (a root that does not verify, or
one the topic manager does not admit at the end of the replay; bsv-low
#551). Nothing of a discarded graph is finalized. As in the reference
a refused graph is not a failed UTXO: the cursor advances past it. A
graph whose anchor could not be CHECKED
(GASPError::AnchorUnavailable: a tracker or storage fault, a topic
manager error in the replay) is not counted here: that one fails its
UTXO and is asked for again.
Sourcepub fn anchor_walk_held(&self) -> u64
pub fn anchor_walk_held(&self) -> u64
How many graphs this orchestrator’s last sync HELD because their
anchor’s script walk could not run within the engine’s walk budget
(GASPError::AnchorWalkHeld; bsv-low #592, the E592 lens fold): not
finalized, the UTXO failed and the cursor kept below it, until the
peer serves the root proven. Not counted in discarded_graphs.
Sourcepub fn pruned_inputs(&self) -> u64
pub fn pruned_inputs(&self) -> u64
How many manager-named inputs this orchestrator pruned because the
peer answered that it does not hold them (the D8 decoy rule, see
process_incoming_node). Counted per DISTINCT outpoint per sync
call of this orchestrator, which talks to ONE peer: the same decoy
seen through two peers is counted by each. A pruned branch is NOT a
failed UTXO: the graph completes with what it has and the cursor
advances.
Sourcepub fn with_ancestor_fetcher(
self,
fetcher: Option<Rc<dyn AncestorFetcher + 'a>>,
) -> Self
pub fn with_ancestor_fetcher( self, fetcher: Option<Rc<dyn AncestorFetcher + 'a>>, ) -> Self
Opt in to chain-backed ancestor hydration (OFF by default).
When set, a peer’s inability to serve a needed ancestor during ingest triggers a fallback fetch of that ancestor’s raw tx from chain. This is a deliberate one-time-migration escape hatch — production should NOT call this. Without it, behavior is unchanged.
Sourcepub async fn sync(&mut self, limit: Option<u64>) -> Result<(), GASPError>
pub async fn sync(&mut self, limit: Option<u64>) -> Result<(), GASPError>
Run the sync protocol with the remote peer.
- Request remote’s UTXOs since last interaction (paginated)
- For each unknown UTXO, request the full graph and ingest it
- If bidirectional, push our unknown UTXOs to the remote
Sourcepub async fn defer_in_flight(&self)
pub async fn defer_in_flight(&self)
Save the walk of the graph that was in hand when a deadline dropped
sync (bsv-low #555): the per-peer deadline (D16) defers it like the
per-graph one, so the next pass resumes it instead of walking it
again. No-op without a per-graph budget or with no walk in hand.