Skip to content

feat(data): unified @transactional for relational + document (v26.06.75)#102

Merged
ancongui merged 1 commit into
mainfrom
feat/unified-transactional-rel
Jun 7, 2026
Merged

feat(data): unified @transactional for relational + document (v26.06.75)#102
ancongui merged 1 commit into
mainfrom
feat/unified-transactional-rel

Conversation

@ancongui
Copy link
Copy Markdown
Contributor

@ancongui ancongui commented Jun 7, 2026

One @transactional annotation for every backend (Spring's uniform-annotation model), addressing the request to "just use @transactional, no adapter-specific annotations."

  • Backend-neutral @transactional in pyfly.data (imports neither SQLAlchemy nor Motor at module scope). At call time it dispatches to the transaction manager the service exposes: self._session_factory (relational) → SQLAlchemy txn with propagation/isolation/read-only/rollback_for; self._motor_client (document) → Mongo session+txn, session injected as the session kwarg, with rollback_for/no_rollback_for parity.
  • Each backend supplies a lazily-imported runner (run_relational_transaction / run_mongo_transaction) — hexagonal.
  • Back-compat: from pyfly.data.relational.sqlalchemy import transactional is the same object; mongo_transactional is a deprecated alias.

Proper tests + no stubs (the other half of the ask): the MongoDB transaction path was completely untested — now covered (commit / abort on rollback_for / commit-and-re-raise on no_rollback_for / session injection / missing-client error). Relational isolation is now verified (asserts isolation_level reaches the session). No stubs found in the transactional/repository code (verified). Docs + the implement-data-repository skill updated to teach the single annotation; the doc's broken @mongo_transactional(client) example fixed.

Gates: mypy --strict (639), ruff+format, full suite 3993.

…s + bump v26.06.75

ONE @transactional annotation (pyfly.data) for both backends — Spring's uniform-annotation model.
Backend-neutral core (pyfly/data/transactional.py, no sqlalchemy/motor at module scope) dispatches
at call time by what the service exposes:
- self._session_factory -> run_relational_transaction (propagation/isolation/read-only/rollback_for,
  repo session-patching);
- self._motor_client -> run_mongo_transaction (session injected as 'session' kwarg, commit/abort
  with rollback_for/no_rollback_for parity).
Each backend supplies a lazily-imported runner (hexagonal). 'from pyfly.data.relational.sqlalchemy
import transactional' still works (same object); mongo_transactional is now a deprecated alias.

Tested: tests/data/test_unified_transactional.py (8) — relational commit/rollback/isolation-applied
+ document commit/abort/no_rollback_for-commit/session-injection/missing-client (the Mongo path was
previously UNTESTED). Updated test_transactional.py's no-manager error match. Docs (data.md,
data-document.md) + implement-data-repository skill teach the single annotation; fixed the doc's
broken @mongo_transactional(client) example.

Gates: mypy --strict (639), ruff + format, full suite 3993 passed.
@ancongui ancongui merged commit b45381a into main Jun 7, 2026
5 checks passed
@ancongui ancongui deleted the feat/unified-transactional-rel branch June 7, 2026 21:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant