cadrumo.application.user_profile.custody_repository module¶
Application repository and lock ports for profile custody transactions.
- class ProfileCustodyTransactionRepository(*, root=None, adapters=None)[source]¶
Bases:
objectPersist strict current-format transaction journals and owner receipts.
- Parameters:
root (Path | None)
adapters (ProfileCustodyLocalRecordStore | None)
- journal_path(transaction_id)[source]¶
Return the durable path for a transaction journal.
- Return type:
Path- Parameters:
transaction_id (UUID)
- receipt_path(transaction_id)[source]¶
Return the durable path for an application-local receipt.
- Return type:
Path- Parameters:
transaction_id (UUID)
- owner_receipt_path(transaction_id, owner)[source]¶
Return the durable path for an owner-specific receipt.
- create_journal(journal)[source]¶
Create a transaction journal with exclusive publication.
- Return type:
- Parameters:
journal (ProfileCustodyTransactionJournal)
- load_journal(transaction_id)[source]¶
Load and validate a transaction journal.
- Return type:
- Parameters:
transaction_id (UUID)
- save_journal(journal)[source]¶
Replace an existing transaction journal with canonical bytes.
- Return type:
- Parameters:
journal (ProfileCustodyTransactionJournal)
- write_receipt(receipt)[source]¶
Write or confirm an application-local receipt.
- Return type:
- Parameters:
receipt (ProfileCustodyTransactionReceipt)
- load_receipt(transaction_id)[source]¶
Load and validate an application-local receipt, if present.
- Return type:
- Parameters:
transaction_id (UUID)
- write_owner_receipt(receipt)[source]¶
Write or confirm an owner-specific receipt.
- Return type:
- Parameters:
receipt (ProfileCustodyOwnerReceipt)
- profile_custody_transaction_lock(root, profile_id)[source]¶
Acquire root then profile lock, the only accepted custody lock order.
Custody transactions are GLOBALLY serialised, not per profile. The root lock is taken first and held for the whole span, so two transactions for DIFFERENT profiles exclude each other exactly as two for the same profile do; a long transaction on one profile blocks every other.
The profile lock therefore never contends under the current call graph – it is only ever acquired inside this function, with the root lock already held. Removing it fails the lock-order gate and nothing else, which is stated here because “there is a per-profile lock” otherwise reads as a promise of per-profile concurrency that the root lock does not deliver. It stays because the ORDER is the deadlock-safety rule: a future path that takes both must take them this way round.