Repository navigation
feat(store): billing rows are soft deleted when an org is deleted - #1983
rohilsurana wants to merge 10 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 43 minutes. View limit details
📝 Summary
Merge Risk: 🔵 Low · up to
|
Coverage Report for CI Build 38886573055Coverage increased (+0.2%) to 55.463%Details
Uncovered Changes
Coverage Regressions1 previously-covered line in 1 file lost coverage.
Coverage Stats
💛 - Coveralls |
569b820 to
a7af83d
Compare
7d949a4 to
68311b4
Compare
a7af83d to
ebe1dc5
Compare
68311b4 to
be61aad
Compare
ebe1dc5 to
0031cdd
Compare
be61aad to
49f5fe5
Compare
0031cdd to
8d97dcd
Compare
49f5fe5 to
170adbe
Compare
There was a problem hiding this comment.
🧹 Nitpick comments: 2
internal/store/postgres/billing_transactions_repository.go: 1
146-151: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueCredit-customer check runs outside the transaction.
GetByIDruns beforeWithTxn. A customer deleted between the check and the insert still receives the credit entry. The window is small. The deleter removes transactions before the customer, and the customer delete now takes a row lock. An in-transactionSELECT ... FOR SHAREon the credit customer would close the gap.internal/store/postgres/billing_customer_repository_pg_test.go: 1
196-199: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThe lock-wait probe can match other sessions.
The query counts any session with
wait_event_type = 'Lock'andFOR UPDATEin its text. It spans the whole server. Each test uses its own database, but parallel packages share the instance, so the count can differ from"1". Filter ondatname = current_database()to avoid flaky runs.Proposed fix
- `SELECT count(*)::text FROM pg_stat_activity WHERE wait_event_type = 'Lock' AND query ILIKE '%FOR UPDATE%'`) == "1" + `SELECT count(*)::text FROM pg_stat_activity WHERE datname = current_database() AND wait_event_type = 'Lock' AND query ILIKE '%FOR UPDATE%'`) == "1"
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: raystack/frontier/.coderabbit.yaml
- Review profile: CHILL
- Plan: Advanced
- Run ID:
5919f5a2-0a4b-4974-987c-9088c541f7e5
📒 Files selected for processing: 18
billing/checkout/service.gobilling/credit/service.gobilling/customer/errors.gobilling/subscription/service.gocore/deleter/service.gointernal/api/v1beta1connect/billing_errors.gointernal/api/v1beta1connect/billing_errors_test.gointernal/store/postgres/billing_checkout_repository.gointernal/store/postgres/billing_checkout_repository_pg_test.gointernal/store/postgres/billing_customer_repository.gointernal/store/postgres/billing_customer_repository_pg_test.gointernal/store/postgres/billing_invoice_repository.gointernal/store/postgres/billing_invoice_repository_pg_test.gointernal/store/postgres/billing_subscription_repository.gointernal/store/postgres/billing_subscription_repository_pg_test.gointernal/store/postgres/billing_teardown_pg_test.gointernal/store/postgres/billing_transactions_repository.gointernal/store/postgres/billing_transactions_repository_pg_test.go
Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review.
170adbe to
c2b82b8
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: raystack/frontier/.coderabbit.yaml
- Review profile: CHILL
- Plan: Advanced
- Run ID:
73087e52-9403-4f6b-87c9-078206ff9536
📒 Files selected for processing: 1
internal/store/postgres/billing_customer_repository_pg_test.go
Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.
…live records point at it
…ailed precondition
c2b82b8 to
e625872
Compare
What changes
The org delete now keeps the billing rows. These five deletes set
deleted_atinstead of removing rows:The order is the same as before: children first, the account last, the org row after everything else.
The account delete now refuses while a live subscription, invoice or checkout points at it. The
DeleteBillingAccountAPI answersfailed_preconditionin that case. Before, it was an internal error from the foreign key.A credit entry now also checks that the billing account is live. Before, only the debit side checked it. A credit to a deleted account now answers not found, like a debit does.
Stripe behavior is unchanged. Provider ids stay on the rows. Clearing them is a separate ticket.
Comments that said rows are removed are reworded.
Release note: deploy order
Do not ship this before #1973. A hard org row would make every org delete fail on the
billing_customers.org_idforeign key.Do not ship it before #1982. If a delete stops half way, an overdraft customer could be billed twice.
This PR stays a draft until #1981, #1982 and #1973 are merged.
How it was tested
One thing to know: the onboarding credit is a double entry. Its debit side sits on the system account, so the delete does not hide that row. It only hides rows owned by the deleted account.