Adds ability to have consequences to Events#75
Merged
Conversation
Detect oversize submissions at file-upload time and persist the flag to the classic arXiv_submissions.is_oversize column. The flag is a soft gate: the submitter is warned but can still proceed. The auto-hold effect at finalize is a later phase. Adds policy module: - submit_ce/domain/size_limits.py: SizeLimits (three per-archive limits, default 50 MB) and a pure check_sizes() decision function. Enforces the total and per-file uncompressed limits, matching legacy check_sizes; compressed limit defined but not enforced. OVERRIDE/MAXSIZE env escapes. - ui/config.py: MAX_UNCOMPRESSED_TOTAL_KB / _PER_FILE_KB / _COMPRESSED_KB. Adds detection in the file `Event`: - Submission.is_oversize: flag set when files change. - UploadArchive/UploadFiles/RemoveFiles evaluate the authoritative workspace against the limits in execute(), persist the result, and apply it in project() (deterministic on replay); RemoveAllFiles clears it. - SubmitApi.get_size_limits() (defaults) + Flask override reading config, so the domain event reaches limits through the api boundary. - upload controller flashes an oversize warning. Adds submit 1.5 backward-compatible DB projection: - update_from_submission writes arXiv_submissions.is_oversize; to_submission reads it back so rows round-trip. Tests: size_limits unit tests, event detection tests, and UI/DB persistence tests (column write + domain round-trip). Co-Authored-By: Claude Opus 4.8 (1M context)
Adds auto-hold oversize on `FinalizeSubmission`
Event base class (domain/event/base.py):
- consequences(submission) -> List[Event]: follow-on events an event implies,
given the post-projection state. Default returns none.
- get_consequences(): wraps consequences() and enforces that every emitted
type is declared in the new CONSEQUENCE_TYPES class attribute, so the static
graph cannot silently rot.
- CONSEQUENCE_TYPES: frozenset of event types an event may emit, declared
statically so the type graph can be checked for cycles.
Save loop (implementations/legacy_implementation/__init__.py):
- `_save()` now drives a work-queue instead of a flat loop. Consequences are
applied and persisted in the same locked session/transaction, inserted at
the front of the queue so a consequence applies to the state immediately
after its parent.
First use case (domain/event/__init__.py):
- FinalizeSubmission declares CONSEQUENCE_TYPES = {AddHold} and emits a
SOURCE_OVERSIZE AddHold when the submission is oversize and unwaived.
Status stays SUBMITTED; the derived is_on_hold property reports the hold
(this model has no ON_HOLD status).
Tests:
- test_consequences_graph.py: asserts the production consequence type-graph is
acyclic therefore chains always terminate and that all declared types are Events.
Includes a detector test with a self-referencing throwaway Event to prove
find_cycle fires.
- test_finalize_oversize_hold.py (domain): unit-tests the oversize/normal/
waiver branches of FinalizeSubmission.consequences().
- test_finalize_oversize_hold.py (ui): end-to-end finalize of an oversize
submission applies the hold and persists the AddHold in event history.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
norbusan
reviewed
Jun 11, 2026
| limits: Optional[SizeLimits] = None) -> bool: | ||
| """Return ``True`` if the submission exceeds any enforced limit.""" | ||
| return bool(check_sizes(total_uncompressed, per_file_sizes, | ||
| primary_category, limits)) |
Contributor
There was a problem hiding this comment.
This throws away all the well computed reasons.
Is there a way to incorporate the reasons in the message "flashed"?
norbusan
approved these changes
Jun 11, 2026
norbusan
left a comment
Contributor
There was a problem hiding this comment.
Looks very good to me!!!
- Moved default size limits to SIZE_LIMIT_POLICY for more visibility - Changed to all bytes instead of kb - Initial change to oversize message - Saved `OversizeReason` instances on upload `Event` - Changes check_sizes to not have a default `limits` to avoid incorrect use - Changed UploadFiles and UploadArchive to only handle added files for size limit check. - Updated tests. Claude assisted
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add Event.consequences() for explicit follow-on events; auto-hold oversize on finalize
Replace the removed @bind/Rule/Callback choreography with an explicit,
traceable mechanism for events that imply other events.
Event base class (domain/event/base.py):
given the post-projection state. Default returns none.
type is declared in the new CONSEQUENCE_TYPES class attribute, so the static
graph cannot silently rot.
statically so the type graph can be checked for cycles.
Save loop (implementations/legacy_implementation/init.py):
applied and persisted in the same locked session/transaction, inserted at
the front of the queue so a consequence applies to the state immediately
after its parent.
First use case (domain/event/init.py):
SOURCE_OVERSIZE AddHold when the submission is oversize and unwaived.
Status stays SUBMITTED; the derived is_on_hold property reports the hold
(this model has no ON_HOLD status).
Tests:
acyclic (so chains always terminate) and that all declared types are Events.
Includes a detector test with a self-referencing throwaway Event to prove
find_cycle fires. Test-defined Event subclasses are excluded from the
production enumeration since pydantic keeps them alive in subclasses().
waiver branches of FinalizeSubmission.consequences().
submission applies the hold and persists the AddHold in event history.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Update: This PR is/was stacked on #73 but that was merged to develop. So this is just a PR to merge to develop.