fix: release SAVEPOINT via context manager in remaining begin_nested() call sites - #14032
Open
stilla[bot] wants to merge 1 commit into
Open
fix: release SAVEPOINT via context manager in remaining begin_nested() call sites#14032stilla[bot] wants to merge 1 commit into
stilla[bot] wants to merge 1 commit into
Conversation
Follow-up to #14030. Several call sites opened a SAVEPOINT with a manual `session.begin_nested()` and only rolled it back on the error path, leaving the SAVEPOINT un-released on success. Over many iterations these stack up on a session and cause a RecursionError when the session is eventually rolled back. Convert each remaining occurrence to the `async with session.begin_nested():` context-manager form, which releases the SAVEPOINT on success and rolls it back automatically on exception, while preserving each call site's exact control flow, exceptions, return values, and logging. For the product update paths that accumulate validation errors across blocks (medias, attached custom fields), a small local `_SavepointRollback` sentinel triggers the context manager's automatic rollback-and-continue without changing observable behavior. Intentional dry-run/preview SAVEPOINTs (subscription charge/change previews) and already-fixed/already-converted sites are left untouched. Co-Authored-By: Stilla <stilla@stilla.ai>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
OpenAPI ChangesNo changes detected in the OpenAPI schema. |
frankie567
approved these changes
Aug 31, 2026
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.
Problem
#14030 fixed
CustomerMeterRepository.get_or_createwhereself.session.begin_nested()was opened manually and only rolled back on theIntegrityErrorpath, leaving the SAVEPOINT un-released on success. Looped over many meters this stacked hundreds of un-released SAVEPOINTs, and a later session rollback recursed once per stacked SAVEPOINT, causing a productionRecursionError(Sentry SERVER-4ZT).That PR's description flagged the same pattern elsewhere as worth auditing separately. This PR is that follow-up.
Fix
Converted every remaining manual
begin_nested()leak site toasync with session.begin_nested():, which releases the SAVEPOINT automatically on success and rolls it back automatically on exception:discount/service.py:create(), and theupdate()products blockevent_type/repository.py:get_or_create()(same shape as the fix(customer_meter): release SAVEPOINT on success in get_or_create #14030 fix)integrations/github_repository_benefit/service.py:create_oauth_account()(was manually callingnested.commit()/nested.rollback())organization/service.py:create(), andadd_user()product/service.py:update()'smediasandattached_custom_fieldsblocks. These accumulate validation errors instead of raising immediately, so a small local sentinel exception is used to trigger the context manager's rollback while preserving the exact existing control flow (both blocks always run, a combinedPolarRequestValidationErroris still raised at the end with identical content)user/service.py:get_by_email_or_create()Left untouched
customer_meter/repository.py::get_or_create— already fixed in fix(customer_meter): release SAVEPOINT on success in get_or_create #14030member/service.py,customer_seat/service.py,transaction/service/dispute.py— already use the context manager patternsubscription/service.py's charge-preview and change-preview methods — these intentionally always roll back the SAVEPOINT (try/finally: rollback) to compute-then-discard a preview. Converting them would incorrectly persist the preview changes instead of discarding themserver/tests/Testing
ruff check/formatandmypyclean on touched files. Full test suites fordiscount,event_type,organization,product,user, andintegrations/github_repository_benefit: 1124 passed, 16 skipped, no failures.Follow-up to #14030, requested by @frankie567 from @Stilla investigation.
Sent by @frankie567 from PR 14030 savepoint context manager fix.