Skip to content

Fix: Schedule scanner false-positives for inactive NS - #11703

Open
davidporter-id-au wants to merge 2 commits into
temporalio:mainfrom
davidporter-id-au:scanner-active-cluster-and-invariant-recheck
Open

Fix: Schedule scanner false-positives for inactive NS #11703
davidporter-id-au wants to merge 2 commits into
temporalio:mainfrom
davidporter-id-au:scanner-active-cluster-and-invariant-recheck

Conversation

@davidporter-id-au

@davidporter-id-au davidporter-id-au commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

What

This fixes the Schedule invariant scanner's false-positives coming from replication. Due to carelessness it was firing on the passive side because I forgot to filter this out, and for a while during post-replication disconnection, the task processing will cease. Also adds a small check for Described schedules to filter out visibility drift.

How

  • Adds a guard for only checking active NS
  • Adds a describe check for the next fire time, so that visibility-delayed schedules are excluded

Risks:

  • That I make a mistake and break the scanner

…e invariant

Two independent sources of false positives in the schedule-invariants scanner,
both found while chasing a "stuck" V2 schedule that turned out to be healthy -
the dump under investigation was a standby replica 3h24m behind its active
cluster.

1. No active-cluster gate. ListAllNamespaces filtered only on
   NAMESPACE_STATE_DELETED, so every cluster scanned every namespace. Each
   invariant here is evaluated from visibility records, and a standby's records
   track its replica: a schedule ticking normally on the active side looks
   arbitrarily overdue on a standby, whose ScheduleNextActionTime is frozen at
   whatever it was when replication last landed. Every passive cluster
   re-reported the whole namespace as anomalous.

   The ingredient was already wired in and dropped on the floor -
   Activities.currentClusterName was declared, passed to the constructor,
   assigned, and never read. The sibling build-ids scavenger does this correctly
   (scavenger.go:172), as does pernamespaceworker.go:383. The function's own doc
   comment already claimed it returned "every namespace active in the current
   cluster"; now it does.

   TestListAllNamespaces_FiltersInactiveAndDeleted was pinning the bug: it built
   a globalNS explicitly commented "inactive in this cluster" and then asserted
   that it WAS returned. The assertion now matches the test's name.

2. The confirmation step never re-checked the invariant. scheduleIsExpectedNotToFire
   called DescribeSchedule and then looked only at two unrelated exemptions
   (paused; BUFFER_ONE/BUFFER_ALL with a running workflow) - never at whether the
   next action time was still overdue in authoritative state. A candidate is now
   cleared when Info.FutureActionTimes shows no overdue action, which makes the
   check self-correcting against any stale index entry - replication lag,
   visibility indexing lag, or a failover - instead of depending on enumerating
   every benign explanation.

   Deliberately not added as an exemption: SKIP with a running workflow. A SKIP
   schedule whose action overruns the interval does drop that action, but the
   Generator still ticks and advances FutureActionTimes, so the re-check clears
   it without an exemption that would also mask a genuinely stalled SKIP
   schedule.

The re-check suppresses candidates, so it emits
schedule_invariants_scanner_overdue_next_action_time_stale_candidate rather than
going silently blind: a sustained nonzero rate means visibility is lagging, and a
rate that swallows every candidate means the re-check itself has broken.

Note the count-only scanners (stuck_open, unknown_state) have no confirmation
step at all, so fix 1 is their only protection.

All new and changed tests were verified to fail with the fixes reverted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@davidporter-id-au
davidporter-id-au force-pushed the scanner-active-cluster-and-invariant-recheck branch from 11c8c67 to 47da2a6 Compare August 21, 2026 05:32
@davidporter-id-au davidporter-id-au changed the title Scope schedule-invariants scans to the active cluster and re-check the invariant Fix: Schedule scanner false-positives for inactive NS Aug 21, 2026
@davidporter-id-au
davidporter-id-au marked this pull request as ready for review August 21, 2026 05:46
@davidporter-id-au
davidporter-id-au requested a review from a team August 21, 2026 05:46
@davidporter-id-au
davidporter-id-au requested review from a team as code owners August 21, 2026 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant