Skip to content

pm-stack(drills): kill-collector chaos drill, first slice of #1283 - #1823

Merged
dezren39 merged 2 commits into
mainfrom
queue/2667-1283-kill-collector-drill
Oct 30, 2026
Merged

dezren39 merged 2 commits into
mainfrom
queue/2667-1283-kill-collector-drill

Conversation

@dezren39

@dezren39 dezren39 commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

First slice of #1283 (epic #1184), queue task 2667: the kill-collector chaos drill.

What

Live verification (2026-10-28, from this branch's script)

Refs #1283.

scripts/kill-collector-drill.sh stops the sandbox fleet-feed
collector, polls the aggregator /api/health until the feed age
crosses FEED_STALE_MS (15 min, the #1148 watchdog threshold), then
always restores (trap + explicit restore + immediate collection
run) and confirms the feed is fresh again. Interlocks: flock
against overlap, incident-flag refusal, and refusal to start on
an already-stale feed (a real incident is not a drill canvas).
A passed drill comments on #1283; a drill whose signal does not
fire files a finding issue under epic #1184 with its evidence.
systemd service/timer units ship in pm-stack/aggregator/systemd
in the collector units' style (weekly, flock prevents overlap).
@dezren39
dezren39 requested a review from a team as a code owner October 28, 2026 20:56
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 28 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a2e4f1ba-f4cc-49e6-8e52-d1802880a83d
Commits

Reviewing files that changed from the base of the PR and between 528886e and f73e1eb.

Files selected for processing: 3
  • pm-stack/aggregator/scripts/kill-collector-drill.sh
  • pm-stack/aggregator/systemd/kill-collector-drill.service
  • pm-stack/aggregator/systemd/kill-collector-drill.timer
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T21:15:28.571405Z f73e1eb New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b339aef3c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

sudo -n systemctl start "$COLLECTOR_TIMER" 2>/dev/null || log "WARN: could not start $COLLECTOR_TIMER"
sudo -n systemctl start "$COLLECTOR_SERVICE" 2>/dev/null || log "WARN: could not start $COLLECTOR_SERVICE"
}
trap restore EXIT INT TERM

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exit after restoring on termination signals

If SIGTERM or SIGINT arrives during the preconditions, the handler restores the collector and sets RESTORED=1, but then returns instead of terminating the script. Execution subsequently stops the timer and service, while both the explicit restore and EXIT handler skip restoration because that flag is already set. An isolated mock reproduction confirmed the sequence of starts followed by stops with no later restart, leaving the collector disabled. Use termination handlers that exit after cleanup rather than resuming the drill.

Useful? React with 👍 / 👎.

Comment on lines +133 to +134
if [ "$AGE" -gt "$STALE_MS" ]; then
SIGNAL=1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the aggregator's stale signal before declaring success

When the feed timestamp becomes old but the aggregator incorrectly continues reporting healthy services and degraded=false, this condition still sets SIGNAL=1: it checks only the age calculated locally by feed_facts, not the aggregator's response to staleness. A mocked run with exactly that payload completed with outcome=passed. This means the drill passes for the silent-health regression it is intended to detect. Require the relevant feed-backed health states and degradation signal to reflect staleness in the captured response before declaring success.

Useful? React with 👍 / 👎.

sudo -n systemctl start "$COLLECTOR_TIMER" 2>/dev/null || log "WARN: could not start $COLLECTOR_TIMER"
sudo -n systemctl start "$COLLECTOR_SERVICE" 2>/dev/null || log "WARN: could not start $COLLECTOR_SERVICE"
}
trap restore EXIT INT TERM

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Arm restoration only when the drill starts changing collector state

If the timer is inactive, the health endpoint is unreadable, or the feed is already stale, the precondition exits through die, but this already-installed EXIT trap starts both the timer and collector anyway. A mocked inactive-timer run confirmed both start commands despite reporting refusal. This violates the stated no-touch precondition behavior and can restart a deliberately stopped collector or alter a real incident before any drill action occurred. Gate cleanup on whether this run has begun stopping the collector, or arm it immediately before that operation after all preconditions pass.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f73e1eb951

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +157 to +158
if [ "$AGE" -ge 0 ] && [ "$AGE" -le "$STALE_MS" ]; then
CONFIRMED=1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify the collector timer before confirming restoration

If restarting the collector timer fails but the immediate service run succeeds, this freshness check declares restoration successful even though recurring collection remains stopped. An isolated mock reproduced the timer-start warning followed by outcome=passed and exit status 0. The one-off refresh only temporarily masks the outage because fleet-feed-collector.timer supplies the recurring collection cadence. Require successful timer restoration before setting CONFIRMED=1, and retry failed restoration; systemctl --help documents is-active as “Check whether units are active.”

Useful? React with 👍 / 👎.

Comment on lines +135 to +137
sleep 60
WAITED=$((WAITED + 60))
FACTS="$(health_json | feed_facts)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include health-request time in the drill's wait limit

If /api/health starts timing out after the collector is stopped, WAITED excludes the time spent fetching health. Each health_json call can consume 90 seconds across three 25-second transfers and retry sleeps (curl --help all describes --max-time as “Maximum time allowed for transfer”). Consequently, the default 25-minute limit permits roughly 62.5 minutes before restoration, exceeding the 45-minute TimeoutStartSec in systemd/kill-collector-drill.service and reaching service termination before the normal failure report. An accelerated mock confirmed that a one-minute limit waits 150 seconds before restoration. Use an elapsed-time deadline that includes requests and retries.

Useful? React with 👍 / 👎.

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