Repository navigation
Add capacity limits for Huddlz - #124
Merged
Merged
Conversation
- Replace raw SQL FOR UPDATE / count with Ash.Query.lock and Ash.count! - Drop Ecto.UUID.dump!, Repo, and Ecto.Adapters.SQL aliases - Restructure existing-rsvp check so the predicate has no side effects; the action transaction handles rollback via changeset errors
Convert the CapacityNotBelowRsvps validation into a Change attached to the :update action. The change locks the huddl row with FOR UPDATE before counting attendees, eliminating the TOCTOU race where an organizer could shrink capacity while a member RSVP was in flight. - Add Huddlz.Communities.Huddl.Changes.EnforceCapacityFloor - Wire it into the :update action only (was previously a global validation gated in code on action.name) - Delete the now-unused validation module
The five capacity helpers (event_full?, capacity_label, capacity_percent, capacity_status, capacity_status_class) were duplicated verbatim in HuddlLive.Show and CommunityComponents. Promote the helpers in CommunityComponents from defp to def — they're auto-imported into every LiveView via HuddlzWeb html_helpers — and drop the duplicates from Show.
- Unlimited huddl (max_attendees nil) accepts arbitrary RSVPs - :create accepts and enforces max_attendees end to end - Edit form renders inline error when reducing capacity below current RSVPs - New form sets max_attendees and the show page renders "0/N spots filled" - Card empty-state shows the capacity label, status, and 0% progress bar
Both Changes locked the huddl row and then issued a separate COUNT(*) query against HuddlAttendee. The Huddl resource already exposes an :rsvp_count aggregate, which composes with FOR UPDATE. Loading it on the locked read replaces the second query with the same one — and lets at_capacity? read the count off the struct instead of taking a redundant huddl_id arg through the call chain.
The card duplicated the "<icon> <capacity_label>" span across two branches of an outer if. Collapse to a single span guarded by max_attendees || rsvp_count > 0; the inner if/else still picks between capacity_label and the legacy "X attending" copy.
capacity_status and capacity_status_class were mirrored cond chains that each recomputed event_full? and capacity_percent. Extract a private capacity_tier/1 returning an atom; both helpers now match on the tier instead of evaluating the thresholds twice per render.
- "Almost full" tier (4/5 = 80%) was untested; only :full, :filling_up, and :plenty had coverage. - Clearing max_attendees to nil with existing RSVPs was untested; EnforceCapacityFloor's nil short-circuit had no guard against regression. - The card-with-RSVPs path of the flattened capacity row was untested; only the rsvp_count = 0 case had a search test.
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.
Summary
Closes #15
Follow-up
Tests
Note: full mix test currently has one unrelated existing failure in test/huddlz_web/live/huddl_live/new_image_upload_test.exs around Unicode slug redirect encoding.