fix(eventsourcing): SQL concurrency, upcaster wiring, exports (v26.06.10)#36
Merged
Merged
Conversation
…t EventHandlerException + bump v26.06.10 Surfaced validating implement-event-sourcing (skill faithful; these are framework bugs): - SqlAlchemyEventStore.append read latest_version() on a separate connection BEFORE the write txn (TOCTOU) and never translated the UNIQUE violation, so concurrent writers leaked a raw IntegrityError instead of ConcurrencyError. Version check now runs inside the txn + IntegrityError -> ConcurrencyError backstop. - EventUpcaster/NoOpUpcaster were exported+documented but never invoked (dead code). Both stores now accept upcasters= and apply them in load()/stream_all(). - EventHandlerException now exported from pyfly.eventsourcing (was submodule-only, unlike its sibling ConcurrencyError). - TransactionalOutbox.dead_letters() surfaces exhausted records. Tests: tests/eventsourcing/test_eventsourcing_fixes.py (concurrency, upcaster-on-read, dead-letters, export). Gates: mypy --strict (607), ruff, full suite 3635 passed.
628541c to
6854b87
Compare
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.
Summary
Validating
implement-event-sourcing(skill itself faithful — all 5 behaviours verified, zero demo fixes) surfaced framework issues inpyfly.eventsourcing:SqlAlchemyEventStoreoptimistic-concurrency TOCTOU + un-translated error (correctness bug).append()readlatest_version()on a separate connection beforeasync with self._engine.begin(), so two concurrent writers could both pass theexpected_versioncheck; the loser hitUNIQUE(aggregate_id, sequence)and surfaced a rawIntegrityErrorrather than the documentedConcurrencyError, so retry-on-ConcurrencyErrorcallers silently missed the collision. Fix: the version check now runs inside the write transaction, and aUNIQUEviolation is caught and re-raised asConcurrencyError. (InMemoryEventStorewas already correct.)EventUpcasterwas dead code (noop-wiring).EventUpcaster/NoOpUpcasterwere exported + documented but never invoked by any read path. Fix: both stores acceptupcasters=...and apply them inload()/stream_all()(default identity).EventHandlerExceptionnot exported — reachable only via the privatepyfly.eventsourcing.aggregatesubmodule, unlike its siblingConcurrencyError. Fix: exported frompyfly.eventsourcing(+__all__).max_attemptswere retained but had no accessor. Fix:TransactionalOutbox.dead_letters().Tests
tests/eventsourcing/test_eventsourcing_fixes.py: concurrent SQL append → exactly oneConcurrencyError(not a raw DB error) + consistent final version; upcasters applied onloadandstream_all; outboxdead_letters()surfaces exhausted records;EventHandlerExceptionimportable from the package.Gates
mypy --strict(607 files) ✓ ·ruff✓ · full suite 3635 passed, 1 skipped.Bumps
v26.06.09 → v26.06.10, CHANGELOG,uv.locksynced.