Commit 55c7b9f
feat(worker): cohort skip-guards — no-op every team-iterating job for is_test_cohort teams (PR-1 follow-up) (#90)
* feat(worker): cohort skip-guards — no-op every team-iterating job for is_test_cohort teams (PR-1 follow-up)
Worker-side follow-up to api #246 (W0): teams.is_test_cohort (migration 067,
already on master) tags durable synthetic test-cohort teams. This makes every
background job that charges / churns / emails / quota-nudges a team SKIP an
is_test_cohort team, so continuous synthetic monitoring never pollutes the real
funnel / billing / email surface.
Plan: docs/sessions/2026-06-04/TEST-ACCOUNTS-AND-NR-SYNTHETICS-PLAN.md §1.6.
Mechanism — two skip surfaces, both UNCONDITIONAL + inert (no real team is
is_test_cohort=true today, so behaviour is unchanged for all real teams; this
is a safety guard, not a feature, and does NOT depend on FLOW_SYNTHETIC_ENABLED):
- SQL scans add `AND NOT [t.]is_test_cohort` (teams-joined) or a NULL-safe
NOT EXISTS subselect (testCohortNotExistsClause, for team_id-carrying scans).
- Per-team Go loops can call isTestCohort/skipIfTestCohort (shared helper).
Guarded (§1.6): quota.go (suspend/unsuspend/redis-eviction scans),
quota_wall_nudge.go, churn_predictor.go, expire_imminent.go, expiry_reminder.go,
billing_reconciler.go (primary + orphan sweep), checkout_reconcile.go,
payment_grace_reminder.go, payment_grace_terminator.go, email.go (weekly_digest).
Deliberately NOT guarded (documented in test_cohort_registry_test.go): expire.go
+ expire_stacks.go (TTL REAPERS — must reap synthetic resources/stacks so they
never leak; no customer email), lifecycle_emails.go (pure render layer, gated by
the guarded trigger jobs upstream).
Tests:
- test_cohort_test.go: sqlmock unit coverage of the helper (flagged /
not-flagged / row-vanished / DB-error fail-safe-for-real-teams). 100% of
test_cohort.go.
- test_cohort_registry_test.go: rule-18 enumeration net —
TestAllTeamIteratingJobs_FilterTestCohort fails if any enumerated job loses
its guard, plus TestNotGuardedJobs_AreStillPresent pins the scope boundary.
- test_cohort_integration_test.go: real-Postgres round-trips proving each
SQL-driven job skips a cohort team while processing a normal team
(quota_wall_nudge, churn_predictor, expiry_reminder, expire_imminent,
weekly_digest, checkout_reconcile, payment_grace_reminder,
billing_reconciler). Gated by SetupTestDB (skips no-DB lanes).
testhelpers: add is_test_cohort + the users/pending_checkouts/
payment_grace_periods subset tables + cohort seed/read helpers. The two-gate
note (ci.yml + deploy.yml) holds: the harness change is idempotent and DB-gated
so both -short, no-DB workflows stay green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(testhelpers): in-package smoke test for cohort.go → 100% (unblock #90 coverage)
cohort.go is exercised only cross-package by internal/jobs integration tests, so
the per-package coverage job reported it 0% (94 missing lines) → 100%-patch gate
red. Add an in-package smoke test (DB-gated via SetupTestDB, runs in coverage.yml)
bringing all 8 seed/query helpers to 100%, mirroring billing_deletion_smoke_test.go.
Recurring testhelpers gotcha (3rd: #87/#89/#90) — see memory.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent baa1aba commit 55c7b9f
17 files changed
Lines changed: 1209 additions & 31 deletions
File tree
- internal
- jobs
- testhelpers
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
822 | 822 | | |
823 | 823 | | |
824 | 824 | | |
| 825 | + | |
825 | 826 | | |
826 | 827 | | |
827 | 828 | | |
| |||
1204 | 1205 | | |
1205 | 1206 | | |
1206 | 1207 | | |
| 1208 | + | |
1207 | 1209 | | |
1208 | 1210 | | |
1209 | 1211 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
148 | 148 | | |
149 | 149 | | |
150 | 150 | | |
151 | | - | |
| 151 | + | |
152 | 152 | | |
153 | 153 | | |
| 154 | + | |
154 | 155 | | |
155 | 156 | | |
156 | 157 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
90 | | - | |
| 90 | + | |
91 | 91 | | |
92 | 92 | | |
93 | | - | |
| 93 | + | |
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
| 97 | + | |
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| |||
210 | 210 | | |
211 | 211 | | |
212 | 212 | | |
| 213 | + | |
213 | 214 | | |
214 | 215 | | |
215 | 216 | | |
| |||
300 | 301 | | |
301 | 302 | | |
302 | 303 | | |
303 | | - | |
304 | | - | |
305 | | - | |
306 | | - | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
307 | 308 | | |
308 | 309 | | |
309 | 310 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
| 123 | + | |
123 | 124 | | |
124 | 125 | | |
125 | 126 | | |
| |||
228 | 229 | | |
229 | 230 | | |
230 | 231 | | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
236 | 238 | | |
237 | 239 | | |
238 | 240 | | |
| |||
268 | 270 | | |
269 | 271 | | |
270 | 272 | | |
271 | | - | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
| 170 | + | |
170 | 171 | | |
171 | 172 | | |
172 | 173 | | |
| |||
303 | 304 | | |
304 | 305 | | |
305 | 306 | | |
306 | | - | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
181 | 181 | | |
182 | 182 | | |
183 | 183 | | |
| 184 | + | |
184 | 185 | | |
185 | 186 | | |
186 | 187 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | | - | |
| 116 | + | |
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
| 120 | + | |
120 | 121 | | |
121 | 122 | | |
122 | 123 | | |
| |||
186 | 187 | | |
187 | 188 | | |
188 | 189 | | |
189 | | - | |
190 | | - | |
191 | | - | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
192 | 193 | | |
193 | 194 | | |
194 | 195 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
152 | | - | |
| 152 | + | |
153 | 153 | | |
154 | 154 | | |
| 155 | + | |
155 | 156 | | |
156 | 157 | | |
157 | 158 | | |
| |||
308 | 309 | | |
309 | 310 | | |
310 | 311 | | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
319 | 321 | | |
320 | 322 | | |
321 | 323 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
241 | 241 | | |
242 | 242 | | |
243 | 243 | | |
244 | | - | |
| 244 | + | |
245 | 245 | | |
246 | 246 | | |
| 247 | + | |
247 | 248 | | |
248 | 249 | | |
249 | 250 | | |
| |||
362 | 363 | | |
363 | 364 | | |
364 | 365 | | |
365 | | - | |
| 366 | + | |
366 | 367 | | |
367 | 368 | | |
| 369 | + | |
368 | 370 | | |
369 | 371 | | |
370 | 372 | | |
| |||
528 | 530 | | |
529 | 531 | | |
530 | 532 | | |
531 | | - | |
| 533 | + | |
532 | 534 | | |
533 | 535 | | |
| 536 | + | |
534 | 537 | | |
535 | 538 | | |
536 | 539 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
| 148 | + | |
148 | 149 | | |
149 | 150 | | |
150 | 151 | | |
| |||
0 commit comments