cadrumo.application.operations.financial_operand_custody module¶
Non-sensitive custody checkpoints for one transient financial operand.
Custody of an operand moves through a fixed order: a wait is opened, an amount is bound to it, delivery to the executor starts, the executor acknowledges, and custody is released. Every step is journalled, and what is journalled is only ever the shape of the wait - which requirement, which state, when - never the amount. The operand contracts keep the value out of every record; this module keeps it out of the durable record too.
The order matters because the interesting failures live between the steps. A process that dies after delivery started but before acknowledgement cannot know whether the executor saw the amount, so restart must classify that as uncertain rather than guess. A wait that lapses must settle as expired even though no one was watching. And release must happen exactly once however many supervisor paths race for it, because a second release would clear a buffer another path believes it still owns.
See also
OperationTransientFinancialOperandRequirementThe durable, amount-free identity every checkpoint is written against.
- class OperationFinancialOperandCustodyState(*values)[source]¶
Bases:
StrEnumThe fixed custody order one operand wait advances through.
- AWAITING_SUBMISSION¶
- BOUND¶
- DELIVERY_STARTED¶
- DELIVERY_ACKNOWLEDGED¶
- RELEASED¶
- EXPIRED¶
- CANCELLED¶
- class OperationFinancialOperandCrashClassification(*values)[source]¶
Bases:
StrEnumWhat a restart may conclude about a wait interrupted mid-flight.
- NOT_DELIVERED¶
- DELIVERY_UNCERTAIN¶
- DELIVERED¶
- exception OperationFinancialOperandCustodyError(message=None, *, context=None, translated_message=None)[source]¶
Bases:
CadrumoErrorRaised when a custody advance would break the fixed transition order.
- Parameters:
- Return type:
None
- code¶
- class OperationFinancialOperandCustodyCheckpoint(**data)[source]¶
Bases:
BaseModelOne journalled custody position, carrying no operand material.
The checkpoint names the wait and its state. It deliberately has no field for an amount, a digest, or any other derivative, so a journal replay can reconstruct what happened without reconstructing what was supplied.
- Parameters:
data (Any)
- operand_kind: OperationFinancialOperandKind¶
- interaction_id: Annotated[str, Field(min_length=1, max_length=128)]¶
- sequence: Annotated[int, Field(ge=1)]¶
- state: OperationFinancialOperandCustodyState¶
- recorded_at: datetime¶
- refusal_reason: OperationFinancialOperandRefusalReason | None¶
- crash_classification: OperationFinancialOperandCrashClassification | None¶
- open_custody(requirement, *, now)[source]¶
Journal the opening of one bounded wait, before any amount exists.
- Return type:
- Parameters:
requirement (OperationTransientFinancialOperandRequirement)
now (datetime)
- advance_custody(current, target, *, now, refusal_reason=None)[source]¶
Advance one wait along the fixed order, refusing every other move.
A terminal checkpoint refuses every advance, which is what makes release exactly-once: the second racing path to arrive finds a released checkpoint and is refused rather than clearing a buffer twice.
- Return type:
- Parameters:
now (datetime)
refusal_reason (OperationFinancialOperandRefusalReason | None)
- classify_interrupted_custody(checkpoint)[source]¶
Say what a restart may conclude about a wait that was cut off.
Nonemeans the wait was already settled and needs no conclusion. A wait cut off between delivery starting and its acknowledgement is reported as uncertain, never as delivered or as not delivered, because the record genuinely does not say.- Return type:
- Parameters:
checkpoint (OperationFinancialOperandCustodyCheckpoint)
- reconcile_on_restart(checkpoint, *, now)[source]¶
Settle one interrupted wait so no custody position survives a restart.
An unsettled wait cannot be resumed: the amount lived only in the memory of a process that is gone, so custody has in fact ended either way. What reconciliation must not do is decide what it cannot know. A wait cut off between delivery starting and its acknowledgement settles as released because the buffer is gone, and carries
DELIVERY_UNCERTAINforever after. Recording it as acknowledged would manufacture evidence that the executor saw the amount; recording it as not delivered would manufacture the opposite.This is deliberately not an
advance_custody()call. The fixed order governs a live wait; a restart settles a wait whose owner no longer exists, and forcing it through the live transitions is what would tempt a caller to invent the missing acknowledgement.- Return type:
- Parameters:
checkpoint (OperationFinancialOperandCustodyCheckpoint)
now (datetime)