mirror of
https://github.com/discourse/discourse.git
synced 2026-09-05 04:40:41 -05:00
The team wants the voice badge set on by default. Reviewing the fixtures and grant hooks first turned up a handful of issues that only bite once real sites accumulate history, so this PR fixes them and flips the default in one go. ### Fixes - **Scheduled badges were auto-revocable.** Core's `Badge.auto_revoke` defaults to `true` and the fixtures never overrode it. Sessions and co-presence rows are purged after `voice_session_retention_days` (400), and a deleted user's co-presence rows are dropped, so the daily backfill would have silently revoked airtime, bonding, loyalty, exploration and hosting badges (and any titles set from them) as data aged out. All 19 query badges now set `auto_revoke = false`, same as core's cumulative badges. - **Crowd Puller / Master of Ceremonies were farmable.** The hosting query counted `COUNT(s.id)` across a creator's rooms, including the creator's own joins. At the 30/min join rate limit a Gold title took ~17 minutes. It now counts `DISTINCT` visitors excluding the creator. - **Packed House was unreachable for most rooms.** It read `room.max_participants`, which is `nil` whenever the room is capped by the site-wide setting. It now uses `effective_max_participants`, matching admission. - **Bulk toggles skipped badge maintenance.** `enable_all!`/`disable_all!` used `update_all`, bypassing the `Badge` callbacks that refresh featured ranks and distinct badge counts, leaving stale profile counts. They now run that once after the flip, and enabling also enqueues a backfill for the query badges so they show up right away instead of after the next daily job. - **Analytics dependency made explicit.** Every badge is computed from `voice_sessions`; with analytics off nothing can be earned. The hooks now check `voice_analytics_enabled` and the setting description references it. ### Default flip `voice_badges_enabled` now defaults to `true` and the fixtures seed badges as `default_enabled`. Neither reaches existing sites on its own: the settings-changed hook doesn't fire for a default change, and `default_enabled` only applies to new records. A post-migration enables the Voice-grouping badges on sites that have no explicit `voice_badges_enabled = false` row. ### Tests - New `badge_backfill_spec.rb` runs `BadgeGranter.backfill` for every SQL family at its threshold boundary, including the retention-purge case and the hosting self-join exclusion. - Migration spec covers untouched, explicitly-disabled, and non-Voice badges. - Hooks spec updated for the site-cap fallback, analytics gate, default-enabled seeding, and backfill enqueueing. ### Not changed (design notes from the review) - Weekend Warrior and Loyalty use server UTC for day boundaries while Night Owl / Early Bird use the user's timezone. Left as is; user timezones in SQL would need per-row `AT TIME ZONE` with invalid-name handling. - Icebreaker largely overlaps Mic Check since co-presence rows lag five minutes. Bronze, harmless. - Marathoner relies on `voice_afk_disconnect_threshold_minutes` (30) to keep idle tabs from earning a Gold title.