This change adds a SaveParticipant abstraction#82
Conversation
Goal to allow the SubmitAPI to have more options to add behavior that happens inside protected critical sections. Adds ability to have behavior in the save transaction with four phases of callbacks (`under_lock`, `before_commit`, `after_commit`, `on_rollback`), injected via constructor. `on_rollback` receives an explicit `SaveFailure` record (exception + `SavePhase` enum + current event/participant) built from a cursor the save loop maintains, so participants never reverse-engineer failure location from exception types. `SubmitApi.save()` runs a critical section (row lock → validate/execute events → persist → commit) that is currently a private detail of `LegacySubmitImplementation`. Composed implementations like `PubsubEventSubmitImplementation` can only act before/after the whole `save()` call. This is *outside* the transaction and nothing is notified of rollback. This changes provides several new places to tie in code that is run inside the transaction that makes up the protected critical section. Scope: **core machinery + tests only**. Pubsub stays a decorator; conversion in follow-up work.
Resolve two semantic conflicts between the SaveParticipant refactor and develop's SUBMISSION-169 (build source package under lock): - _FakeStore in test_oversize_detection.py: add no-op delete_source_package/delete_user_decisions/delete_directives, which _common_file_change_execute now calls. - BuildSourcePackage: rename validate -> validate_pre_lock to match the renamed base-class hook that EventWithSideEffect.apply invokes. Co-Authored-By: Claude Fable 5 <[email protected]>
norbusan
left a comment
There was a problem hiding this comment.
Sorry, no time to read through all this now, but I asked codex GPT/Sol and it gave only one issues:
- P2: Consequence failures are reported as persistence failures. legacy_implementation/__init__.py:301
(https://github.com/arXiv/submit-ce/blob/99d96702c7b007fe3326e826b734f228c9672aca/submit_ce/implementations/legacy_implementation/__init__.py#L301)
calls event.get_consequences() while ctx.phase remains EVENT_PERSIST. That method deliberately raises for undeclared consequence
types, so rollback participants receive an inaccurate SaveFailure.phase, contrary to the abstraction’s “exact failure location”
contract. Add an EVENT_CONSEQUENCES phase and set it before this call, with a regression test.
|
I added a test, showing the rollback might possibly mask a previous error. |
I'll add this. |
vent.get_consequences() is called while ctx.phase remains EVENT_PERSIST. That method deliberately raises for undeclared consequence types, so rollback participants receive an inaccurate SaveFailure.phase, contrary to the abstraction’s “exact failure location” contract. Adds an EVENT_CONSEQUENCES phase and set it before this call. Adds a test.
…to bdc34/submitapi-participants
Fixed |
Interesting case, I'm looking into it. |
Claude reports that |
This is fixed. Added a Put the rollback in a try |
Goal
To allow the SubmitAPI to have more options to add behavior that happens inside protected critical sections.
This changes provides several new places to tie in code that is run inside the transaction that makes up the protected critical section.
Justification
SubmitApi.save()runs a critical section (row lock → validate/execute events → persist → commit) that is currently a private detail ofLegacySubmitImplementation. Composed implementations likePubsubEventSubmitImplementationcan only act before/after the wholesave()call. This is outside the transaction and nothing is notified of rollback.This adds ability to have behavior in the save transaction with four phases of callbacks:
under_lockjust after locking the submission.before_commitafter the events have beenexecuted()andapplied()after_commitafter commit to the db.on_rollbackOn thrown exceptions.on_rollbackreceives an explicitSaveFailurerecord (exception +SavePhaseenum + current event/participant) built from a cursor the save loop maintains, so participants never reverse-engineer failure location from exception types.A
SaveParticipantsis injected via constructor to theSubmitApi.Scope: core machinery + tests only. Pubsub stays a decorator; conversion in follow-up work.