sgns::TxPruner¶
The real prune-cycle service (PRUNE-04). More...
#include <TxPruner.hpp>
Public Functions¶
| Name | |
|---|---|
| outcome::result< std::shared_ptr< TxPruner > > | New(NodeType node_type, const PruningConfig & config) Fail-closed factory (the construction gate). |
| bool | IsPermanentStop(const std::error_code & error) Whether a RunCycle error is a permanent-stop class. |
| void | SetCycleInterruptHookForTest(std::function< bool(int step)> hook) Test-only interruption seam for the cycle. |
| outcome::result< PruneCycleStats > | RunCycle(crdt::GlobalDB & globaldb, TransactionManager & transaction_manager, UTXOManager & utxo_manager, uint64_t generation) Runs ONE erase cycle over the passed dependencies. |
| PruneStatus | GetPruneStatus() const Returns a copy of the current status (RECL-04). |
Public Attributes¶
| Name | |
|---|---|
| constexpr int | kInterruptAfterEvaluation Interrupt seam step: after Evaluate(), before grouping. |
| constexpr int | kInterruptBeforeErase |
| constexpr int | kInterruptBeforeStatus Interrupt seam step: after the erase loop, before the status update. |
| constexpr int | kInterruptAfterStatus |
Detailed Description¶
The real prune-cycle service (PRUNE-04).
Timer-driven ONLY (D-C6): never invoked from CRDT element callbacks (they fire pre-batch-commit). Construction fails closed unless the node role is Light (GATE-01 — the PruneEligibility::New role-gate mirror; full/archive never erase history); the PruningConfig default-disabled consent gate is the wiring's duty (SC-5) and is not re-checked here.
Public Functions Documentation¶
function New¶
static outcome::result< std::shared_ptr< TxPruner > > New(
NodeType node_type,
const PruningConfig & config
)
Fail-closed factory (the construction gate).
Parameters:
- node_type Deployment role of the constructing node.
- config Validated pruning policy (the caller — GeniusNode — owns the consent gate).
Return: The service, or outcome::failure for a non-Light role.
Mirrors PruneEligibility::New: rejects any role other than NodeType::Light with std::errc::operation_not_permitted before any state exists (GATE-01).
function IsPermanentStop¶
Whether a RunCycle error is a permanent-stop class.
Parameters:
- error A RunCycle failure code.
Return: true when the caller must stop instead of reschedule.
The 17-06 fail-closed error split re-hosted as ONE classification home: std::errc::invalid_argument (Evaluate's fail-closed no-window contract) and std::errc::operation_not_permitted (a non-Light role at either factory) are broken policy states no retry can fix — the caller stops the cycle instead of spinning on it every 10 minutes. Every other error is transient (skip this tick, keep the cadence).
function SetCycleInterruptHookForTest¶
Test-only interruption seam for the cycle.
Parameters:
- hook invoked at the steps above; a
truereturn aborts the cycle AT that point. An aborted cycle is NOT a completed cycle: the status (including the watermark) is left untouched for steps 1-3 — the crash-matrix positions 18-06 asserts against. Pass nullptr to clear.
Note: No production caller may invoke this method. Fixture discipline: a hook armed by a failing case must never leak further — clear it in the fixture destructor (the GlobalDB::SetEraseInterruptHookForTest shape).
function RunCycle¶
outcome::result< PruneCycleStats > RunCycle(
crdt::GlobalDB & globaldb,
TransactionManager & transaction_manager,
UTXOManager & utxo_manager,
uint64_t generation
)
Runs ONE erase cycle over the passed dependencies.
Parameters:
- globaldb Committed-state reader (watermark height).
- transaction_manager Tick-gate inputs, re-verify fetch, and the pruned-erase driver.
- utxo_manager Fresh spent-ness re-verify.
- generation The caller's account-generation tag.
Return: The cycle counters, or outcome::failure: an invalid_argument-class Evaluate failure (and a non-Light evaluator construction) is a PERMANENT-stop signal — see IsPermanentStop — while any other error is transient (retry next cycle). Failures leave the status untouched.
Cycle order (research Pattern 1): (1) tick gate — TransactionManager::GetState() == State::READY, !HasMissingTxHashes(), and the settle window elapsed (the clock starts when the gate FIRST fully holds, skips until settle_seconds after it, and restarts whenever the gate re-opens — a cycle cannot fire during initial sync, D-C2); a gate-skipped tick returns zeroed stats and touches no status. (2) A per-cycle PruneEligibility is constructed from the PASSED deps and Evaluate()d VERBATIM — never under any lock, and never re-implemented (the window arithmetic's one home). (3) Eligible candidates are grouped by delta-block CID; a group whose block report is erasable is taken WHOLE when it fits the remaining K budget, else DEFERRED whole (held_blocks) — never a partial group (Pitfall 1). (4) Per tx inside a taken group: a FRESH spent-ness re-verify (IsOutPointGenuinelyConsumed per outpoint) runs immediately before the erase; a reverted spend (or an unreadable value) skips the tx — never aborts the cycle; then the atomic EraseTransactionEntryPruned commits value + marker in one batch (18-03), with a per-tx failure recorded and skipped past (log-and-continue is sanctioned ONLY for this per-tx scan contract). (5) The status is updated and ONE INFO summary emitted (RECL-03).
GENERATION CONTRACT (D-C4): the supersession check is the CALLER's pre-erase duty — the wiring arm checks the generation is still current BEFORE invoking this cycle (this function is the only erase path, so the check precedes every erase). generation is carried onto the returned stats and the INFO line as the tag. Dependencies are never cached: the caller passes a consistent per-tick snapshot and holds it for the whole cycle.
function GetPruneStatus¶
Returns a copy of the current status (RECL-04).
Return: The watermark + last-cycle counters.
Thread-safe: taken under the status mutex, so a concurrent reader never observes a half-updated cycle.
Public Attributes Documentation¶
variable kInterruptAfterEvaluation¶
Interrupt seam step: after Evaluate(), before grouping.
variable kInterruptBeforeErase¶
Interrupt seam step: immediately before EACH per-tx erase call (the first erase included — "between erases" plus the pre-first position; mid-compose steps are covered by GlobalDB's own seam).
variable kInterruptBeforeStatus¶
Interrupt seam step: after the erase loop, before the status update.
variable kInterruptAfterStatus¶
Interrupt seam step: after the status update, before the INFO summary (the status IS updated at this point).
Updated on 2026-10-22 at 19:28:22 +0000