fix(dean): scope timeout retry cap to this-wait timeout events (VIR-8 hotfix)#138
Merged
Conversation
Dean's timeout-selection gate used jsonb_array_length(externalEvents) as a proxy for "timeout attempts made". But externalEvents is a shared, never-drained log that also holds unrelated events (e.g. moviehouse:* video events). A respondent who watched a video clip earlier in the survey arrived at a later 1-week timeout wait already showing >= 5 events, so the `< DEAN_TIMEOUT_MAX_ATTEMPTS` (5) gate silently excluded them: Dean never emitted the synthetic timeout, the wait never resolved, and they stayed parked in the form forever, never stitching to the next form. (Linear VIR-8: MENtality incentive users stuck, not stitching to endline. ~21 matured users were blocked, 19 of them by moviehouse events.) Count only the timeout events Dean emitted for the CURRENT wait (event.type='timeout' AND value == waitStart) instead of the whole log. The retry cap still works; unrelated events no longer consume it. Unbounded state growth remains independently bounded by the spammer gate (externalEvents > 100 -> BLOCK_USER), so narrowing this counter is safe. Dean-query-only change: no state-shape change, no migration. Adds a regression test (matured timeout fires despite prior video events) and a retry-cap test, and updates the existing cap test to model attempts as real timeout events rather than opaque array length. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for virtuallab-videos canceled.
|
✅ Deploy Preview for vlab-research canceled.
|
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.
Production hotfix — Linear VIR-8 (MENtality incentive users stuck, not stitching to endline)
Root cause
Dean's timeout-selection gate used
jsonb_array_length(externalEvents) < DEAN_TIMEOUT_MAX_ATTEMPTS (5)as a proxy for "timeout retry attempts". ButexternalEventsis a shared, never-drained log that also holds unrelated events — notablymoviehouse:*video-player events from earlier in the survey. Respondents who watched a video clip arrived at their later 1-week timeout wait already showing ≥5 events, so Dean silently excluded them, never emitted the synthetic timeout, and they stayed parked forever.Verified read-only against prod: Dean's timeout query returned 0 actionable users; all ~21 matured/in-window users failed the
<5gate, 19 of 21 specifically due to moviehouse events.Fix
Count only the timeout events Dean emitted for the current wait (
event.type='timeout' AND value == waitStart) instead of the whole log. Retry cap preserved; unrelated events no longer consume it. Unbounded growth stays independently bounded by the spammer gate (externalEvents > 100 → BLOCK_USER).Dean-query-only: no state-shape change, no migration.
Tests
TestGetTimeouts_MaturedTimeoutFiresDespitePriorVideoEvents— matured timeout now fires despite 5 prior moviehouse events (control + stuck both fire).TestGetTimeouts_RetryCapStillStopsAfterMaxTimeoutAttempts— cap still stops after 5 timeout attempts for the wait.TestGetTimeoutsIgnoresThoseAtOrAboveCapto model attempts as real timeout events.All 11 timeout tests pass. (Pre-existing, unrelated
TestGetPaymentsGetsOnlyThoseWhovePassedGraceButNotIntervalfailure reproduces on untouchedmain— not part of this change.)Deploy
Dean is not part of the
-waplatform rebuild; identical onmainand prod tagdean-v0.0.41. After merge: tagdean-v0.0.43→ build → bumpproduction.yamlversionDean→helm upgrade -n vprod. Staging follows after.🤖 Generated with Claude Code