Skip to content

fix(incidents): fail over to ICNF when the ANEPC feed is frozen (#42) - #43

Merged
tomahock merged 2 commits into
mainfrom
fix/anepc-icnf-failover
Oct 26, 2026
Merged

tomahock merged 2 commits into
mainfrom
fix/anepc-icnf-failover

Conversation

@tomahock

@tomahock tomahock commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Closes #42
Closes #44

Problem

ProcessOcorrenciasSite (ArcGIS OcorrenciasSite) answers 200 but its data has been frozen since 2026-10-25 00:58 UTC (DataDosDados). Every 5 min it re-wrote the same 32 records and dispatched CheckIsActive with that list, which deactivated every fire created by ProcessICNFNewFireData. The ICNF job never touched active, so those fires never came back. The history.json freshness tracker was dead (file never written).

Change

  • App\Support\AnepcFeedHealth — tracks newest DataDosDados (hash fallback) in Redis. Stale after ANEPC_STALE_MINUTES (default 30). Posts to Discord on stale/recovered transitions.
  • ProcessOcorrenciasSite — while stale, does not write the frozen snapshot nor dispatch CheckIsActive. Sets source=anepc + anepcUpdatedAt.
  • CheckIsActive — skips if the feed is stale (defensive, it is queued).
  • ProcessICNFNewFireData — ICNF is primary for ICNF-only incidents, and for all incidents while ANEPC is stale:
    • ICNF-only: active follows ICNF (Em Curso → active, Dominado → active only if started < 24h ago, Extinto → inactive). Re-activates fires wrongly dropped.
    • ANEPC incidents: closed on Extinto, never re-opened.
    • status only moves forward (as before). New incidents get source=icnf.
  • Scheduler — ProcessOcorrenciasSite now runs every 2 minutes (was 5).
  • App\Tools\ICNFTool — shared fetch/parse of faztable.asp (was duplicated).
  • When ANEPC data is fresh again, it overwrites the incidents (source=anepc) and CheckIsActive deactivates anything not in its list → ANEPC is primary again.

Tests

  • New: tests/Unit/Support/AnepcFeedHealthTest.php, tests/Unit/Tools/ICNFToolTest.php (9 tests, pass).
  • Full suite: same 12 pre-existing errors as main (missing mongodb extension in the local container).
  • Parsed the live faztable.asp: 8892 Extinto / 37 Dominado / 8 Em Curso → 12 considered active (old Dominados excluded).

Deploy

  1. Deploy as usual.
  2. php artisan queue:restart (jobs changed).
  3. Optional: set ANEPC_STALE_MINUTES in .env (default 30). No migrations.
  4. On the first ProcessOcorrenciasSite run the feed is flagged stale (Discord message); on the next ProcessICNFNewFireData run (≤5 min) the ICNF fires reappear. To force: php artisan ocorrencias:sync then run ProcessICNFNewFireData.

🤖 Generated with Claude Code

The OcorrenciasSite feed can keep answering 200 with a frozen snapshot.
Every run re-wrote the stale records and CheckIsActive deactivated every
fire only ICNF knew about, so new fires disappeared from the endpoints.

- AnepcFeedHealth tracks the newest DataDosDados in Redis; stale after
  ANEPC_STALE_MINUTES (default 30). Transitions go to Discord, replacing
  the dead history.json tracker.
- While stale, ProcessOcorrenciasSite skips writes and CheckIsActive, and
  ProcessICNFNewFireData owns the active flag: ICNF-only fires follow ICNF
  (Dominado only within 24h), ANEPC fires close on Extinto.
- Incidents carry source=anepc|icnf; when ANEPC returns it overwrites them
  and CheckIsActive resumes as before.
- ICNFTool shares the faztable.asp fetch/parse between both jobs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 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-26T14:59:20.794904Z 72787d4 PR opened
ℹ️ 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.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@tomahock
tomahock merged commit 078d6ba into main Oct 26, 2026
1 check passed

@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: 72787d48b6

ℹ️ 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 +151 to +155
if ($icnfOnly) {
// ICNF owns the lifecycle: brings back fires that were dropped
// because a frozen ANEPC list did not include them.
if ((bool) $incident->active !== $icnfActive) {
$incident->active = $icnfActive;

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 Reconcile ICNF reactivation with fresh ANEPC cleanup

When ANEPC is fresh or has recovered, CheckIsActive::handle() still deactivates every incident absent from its ANEPC list, including ICNF-only incidents. This branch then reactivates those same incidents on the next ICNF run even though $anepcStale is false. Both ingestion jobs run every five minutes in bootstrap/app.php, so existing ICNF-only fires now repeatedly disappear and reappear depending on job execution order, rather than settling under one source's authority. Make the two jobs agree on lifecycle ownership while ANEPC is fresh.

Useful? React with 👍 / 👎.

Comment on lines +42 to +45
if (AnepcFeedHealth::isStale()) {
Log::info('CheckIsActive: ANEPC feed is stale, skipping');

return;

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 Scope the stale-feed guard to the snapshot's actual source

When the ArcGIS feed is stale or its health cache has not been initialized, this guard also disables cleanup for the separate ANEPC_API_URL ingestion path. The registered SyncANEPCIncidents command runs ProcessANPCAllDataV2, which dispatches CheckIsActive with its successfully fetched list but never records anything in AnepcFeedHealth. Consequently, running anepc:sync can update current incidents while leaving absent incidents active indefinitely, even when that alternative feed is healthy. Pass the snapshot source or freshness into the cleanup job instead of unconditionally applying ArcGIS health to both callers.

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.

Run ProcessOcorrenciasSite every 2 minutes ICNF fires disappear when the ANEPC feed stops updating

1 participant