Replies: 2 comments 2 replies
-
|
In upstream Fizzy, cards_count is not a Rails counter cache — there's no There is no code anywhere in the codebase that decrements cards_count when cards are deleted. So in upstream Fizzy, deleting cards should not affect the sequence. When reporting issues that generate a 500 response, in the future please provide the exception stack trace so we can diagose the issue. |
Beta Was this translation helpful? Give feedback.
-
|
If you imported cards, that might have been the cause -- recently fixed by @monorkin in #2597 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
When cards are deleted, fizzy decrements cards_count on the account. Since assign_number uses cards_count as a sequence (account.increment!(:cards_count).cards_count), subsequent card creation attempts collide with existing card numbers, producing a UNIQUE constraint failed: cards.account_id, cards.number error and a 500 for all users on that account.
Steps to reproduce
Create ~150 cards on an account
Delete several cards (we deleted enough to bring cards_count back to 11)
Attempt to create a new card via the UI
500 Internal Server Error
Root cause
In app/models/card.rb:
rubydef assign_number
self.number ||= account.increment!(:cards_count).cards_count
end
cards_count is a standard Rails counter cache, which decrements on deletion. But here it's being used as a monotonically increasing sequence. These two roles are incompatible — a counter cache reflects the current count, not the highest number ever assigned.
Fix applied in production
rubyaccount.update_columns(cards_count: account.cards.maximum(:number))
Suggested fix
Either use a separate cards_sequence column that only ever increments and is never decremented on deletion, or use MAX(number) + 1 at assignment time:
rubydef assign_number
self.number ||= (account.cards.maximum(:number) || 0) + 1
end
The MAX approach is slightly less efficient but correct. A dedicated sequence column would be both correct and performant.
Environment
Self-hosted via Docker on Hetzner
SQLite backend
fizzy version: fork "sha256:90f1a0a1fe73200fe7c90ea94f49596759d2031eadbcc58e2760ee3f7e6ecda9
Beta Was this translation helpful? Give feedback.
All reactions