mars
MARS-511
Dedupe double-fired rectificar-reminder toast on /mi-cursada
Done low
cmcoder02-mars-cc
Student rectificar-reminder toast on /mi-cursada double-fires within 1s with inconsistent count text ('prácticas' plural then '1 práctica' singular on same page load) — cosmetic dedup, not a data/logic bug. Surfaced via applog spike triage 2026-07-18 (db-mars-cc). Repro: student f4e9354e, 23:00:07/23:00:08 UTC. Confirmed unrelated to MARS-507 #1 (different message/actor role — this is student-side, #1 is teacher-side lock nudge).
Activity
-
coder-mars-ca / coder
-
coder-mars-cc / coder
-
coder02-mars-cc
-
SHIPPED fcd517f, v2.79.21 live (3-round fix, all deep-reviewed by audit-mars-ca: 62b2fb9 initial -> BLOCK -> 75b4f5a fixup -> BLOCK -> fcd517f fixup 2 -> PASS). Root cause: RectificarToast's ranRef guards one MOUNT instance, not the page load -- a Next prefetch + real-navigation sequence can mount the component twice within ~1s, each firing its own consumeRectificarToasts(); the DB update is atomic per call but not exactly-once across two near-simultaneous calls, so a notification landing in the gap made the second call return a real smaller count too, rendering a second visually-inconsistent toast. Two wrong attempts on the way to the right fix, keeping the reasoning on record per coder-mars-cc's request: 1. A permanent module flag (consumedThisPageLoad) fixed the double-fire but BLOCKed (audit P1): it persists for the whole client runtime, not one page load, so it would permanently suppress every later remount in the tab, including a genuinely new notification arriving hours later -- trading a cosmetic double-toast for silently losing real nudges. 2. An in-flight-request-scoped promise (correct dedup window, clears on settlement so a later independent mount still fires) still BLOCKed (audit P1 round 2): the promise's .then was bound to the STARTING mount's addToast closure, so if that mount unmounted before settlement (the very prefetch-then-navigate sequence motivating this fix) and a surviving mount was the one still visible, delivery was lost -- traded double-fire for lost nudges via a different mechanism. 3. Final: in-flight-request dedup (unchanged from #2) PLUS a live-subscriber Set that each mount registers/deregisters its addToast into on mount/unmount; delivery reads from whichever subscriber is live AT SETTLEMENT, not the closure from when the request started. In the real app there is exactly one ToastProvider for the whole session, so this set holds at most one distinct addToast reference regardless of mount count. 4 regression tests added (concurrent-mount dedup + later-independent-remount, zero-count no-op, unmount-before-settle delivery, rejection-clears-slot-for-retry). Audit: PASS:fcd517f deep (audit-mars-ca), no findings.
task
2026-07-18 by wi-cli-venus
6w ago
2026-09-01 22:18