Skip to content

refactor(organization): drop refunds_blocked column (Phase B)#11187

Merged
psincraian merged 1 commit intomainfrom
psincraian/drop-refunds-blocked
Apr 24, 2026
Merged

refactor(organization): drop refunds_blocked column (Phase B)#11187
psincraian merged 1 commit intomainfrom
psincraian/drop-refunds-blocked

Conversation

@psincraian
Copy link
Copy Markdown
Contributor

Summary

Phase B of the refunds_blockedcapabilities["refunds"] migration. Drops the deferred column now that all app code reads from capabilities, and makes capabilities NOT NULL.

Follow-up to #11163 (Phase A, which deferred the column and removed all reads/writes).

What

  • New migration d3f5e1a7b2c4SET NOT NULL on capabilities, DROP COLUMN refunds_blocked. Uses SET lock_timeout = '2s' to fail fast on contention.
  • Model: drop refunds_blocked column, capabilities becomes non-nullable, remove get_effective_capabilities() fallback.
  • Callers switched to direct .capabilities access:
    • organization/service.py (set_capability)
    • backoffice/organizations_v2/endpoints.py (set_capability endpoint)
    • backoffice/organizations_v2/views/sections/settings_section.py
    • backoffice/organizations_v2/views/modals/set_capability_modal.py
    • tests/refund/test_service.py

Why

Phase A made capabilities["refunds"] the sole source of truth but left the column in place to avoid a CD race. That has now shipped and soaked — this PR cleans up the deprecated column and eliminates the nullable-capabilities fallback.

How

Migration safety on the hot organizations table (77k rows / 177MB in prod):

  • SET lock_timeout = '2s' prevents pileup behind long-running DDL on a table heavily joined from checkouts/orders/subscriptions.
  • No defensive inline backfill — ALTER COLUMN SET NOT NULL will fail loudly if any NULL rows remain, which is a better signal than silent heal.
  • Reversible downgrade: recreates refunds_blocked from NOT (capabilities->>'refunds')::boolean and reverts capabilities to nullable.

Deploy order:

  1. uv run python -m scripts.backfill_org_capabilities --execute against prod (confirm zero NULLs with --verify).
  2. Apply this migration.

How to verify

  • Local cycle: uv run alembic upgrade head && uv run alembic downgrade -1 && uv run alembic upgrade head — clean
  • Targeted tests: uv run pytest tests/organization tests/refund tests/backoffice — 327 passed
  • Broader capability-adjacent flows: uv run pytest tests/checkout tests/order tests/subscription tests/payment tests/customer — 883 passed

Checklist

  • This PR addresses a single concern
  • The diff is reasonably sized and easy to review
  • New functionality is covered by tests
  • Linting and type checking pass (uv run task lint && uv run task lint_types)
  • No unrelated changes or drive-by fixes are included

Removes the deferred `refunds_blocked` column now that all code paths
read from `capabilities["refunds"]` (Phase A, #11163). Makes
`capabilities` NOT NULL and removes the `get_effective_capabilities`
fallback.

Migration uses `SET lock_timeout = '2s'` to fail fast on contention.
Requires `backfill_org_capabilities.py --execute` to have run first.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@psincraian psincraian requested a review from frankie567 as a code owner April 23, 2026 11:01
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
polar Ready Ready Preview, Comment Apr 23, 2026 11:04am
polar-sandbox Ready Ready Preview, Comment Apr 23, 2026 11:04am

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Migration Isolation Check Failed

This PR contains database migrations along with other code changes. To ensure safe deployments, please split this into separate PRs,
or verify that your changes will not break. Keep in mind that the API is deployed before the workers.

  1. Migration PR: Only model changes and the migration file
  2. Code PR: All other changes (can be merged after migration PR)

Files that should be in a separate PR:

  • server/polar/backoffice/organizations_v2/endpoints.py
  • server/polar/backoffice/organizations_v2/views/modals/set_capability_modal.py
  • server/polar/backoffice/organizations_v2/views/sections/settings_section.py
  • server/polar/organization/service.py
  • server/tests/refund/test_service.py

Why?

Migrations are deployed separately and run before code changes. Mixing them can cause deployment issues if the new code depends on the migration.

@github-actions
Copy link
Copy Markdown
Contributor

OpenAPI Changes

No changes detected in the OpenAPI schema.

@psincraian psincraian added this pull request to the merge queue Apr 24, 2026
Merged via the queue into main with commit 61b4da0 Apr 24, 2026
23 of 24 checks passed
@psincraian psincraian deleted the psincraian/drop-refunds-blocked branch April 24, 2026 06:47
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.

2 participants