Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[async 4/7] refactor: move operation DB resolution out of __init__ into _resolve()#478

Draft
somethingnew2-0 wants to merge 1 commit into
pcollins/async-1c-model-prep from
pcollins/async-1d-op-restructure
Draft

[async 4/7] refactor: move operation DB resolution out of __init__ into _resolve() #478
somethingnew2-0 wants to merge 1 commit into
pcollins/async-1c-model-prep from
pcollins/async-1d-op-restructure

Conversation

@somethingnew2-0

@somethingnew2-0 somethingnew2-0 commented Jun 12, 2026
edited
Loading

Copy link
Copy Markdown
Collaborator

Part of the async-SQLAlchemy migration stack (stacked on #477).

Every operation class now stores raw constructor arguments and resolves them (queries, row locks, id lookups) in a _resolve() method invoked as the first statement of execute() / execute_for_group() / execute_for_role(). __init__ signatures and public attribute names are unchanged, and every call site already chains .execute() immediately, so behavior is identical — resolution just happens at execute time.

Async prep: __init__ cannot be async, so all session work must live behind execute() before the flip makes it awaitable. For the four operations whose execute() wraps asyncio.run(self._execute()), _resolve() runs before asyncio.run on the calling thread.

Side benefit: the with_for_update row locks in the approve/reject operations now begin at execute time rather than construction time, narrowing the lock window to the actual mutation.

Full suite green (515 tests), ruff + mypy clean.

PR stack

Merge bottom-up; each PR is based on the branch of the one before it (retarget to main as predecessors merge).

  1. [async 1/7] deps: prepare for async SQLAlchemy #475 — async dependency prep (SQLAlchemy[asyncio] 2.0.50, asyncpg, aiosqlite)
  2. [async 2/7] refactor: modernize the legacy Query API to 2.0-style statements #476 — legacy Query API -> 2.0-style statements (~350 sites)
  3. [async 3/7] refactor: eliminate lazy loading and commit-expiration from the ORM layer #477 — eliminate lazy loading and commit-expiration from the ORM layer
  4. [async 4/7] refactor: move operation DB resolution out of __init__ into _resolve() #478 — operation DB resolution out of __init__ into _resolve() ⬅️ this PR
  5. [async 5/7] refactor: keep db.session access out of spawned notification tasks #479 — keep db.session access out of spawned notification tasks
  6. [async 6/7] Switch to async SQLAlchemy end-to-end #480 the async flip (production + tests + docs)
  7. [async 7/7] fix: surface failed Okta/notification fan-out tasks instead of dropping them #481 — surface failed Okta/notification fan-out tasks

🤖 Generated with Claude Code

@somethingnew2-0 somethingnew2-0 changed the title (削除) refactor: move operation DB resolution out of __init__ into _resolve() (削除ここまで) (追記) [async 4/7] refactor: move operation DB resolution out of __init__ into _resolve() (追記ここまで) Jun 12, 2026
@somethingnew2-0 somethingnew2-0 changed the title (削除) [async 4/7] refactor: move operation DB resolution out of __init__ into _resolve() (削除ここまで) (追記) [async 4/8] refactor: move operation DB resolution out of __init__ into _resolve() (追記ここまで) Jun 12, 2026
@somethingnew2-0 somethingnew2-0 force-pushed the pcollins/async-1d-op-restructure branch from de54299 to 540493e Compare June 12, 2026 17:08
@somethingnew2-0 somethingnew2-0 changed the title (削除) [async 4/8] refactor: move operation DB resolution out of __init__ into _resolve() (削除ここまで) (追記) [async 4/7] refactor: move operation DB resolution out of __init__ into _resolve() (追記ここまで) Jun 12, 2026
Every operation class now stores raw constructor arguments and resolves
them (queries, row locks, id lookups) in a _resolve() method invoked as
the first statement of execute() / execute_for_group() /
execute_for_role(). __init__ signatures and public attribute names are
unchanged, and every call site already chains .execute() immediately,
so behavior is identical - resolution just happens at execute time.
Async SQLAlchemy prep: __init__ cannot be async, so all session work
must live behind execute() before the flip makes it awaitable. For the
four operations whose execute() wraps asyncio.run(self._execute()),
_resolve() runs before asyncio.run on the calling thread.
Side benefit: the with_for_update row locks in the approve/reject
operations now begin at execute time rather than construction time,
which narrows the lock window to the actual mutation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@somethingnew2-0 somethingnew2-0 force-pushed the pcollins/async-1d-op-restructure branch from 540493e to 3bf1f83 Compare June 12, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

AltStyle によって変換されたページ (->オリジナル) /