Skip to content

fix(drivers): restart a driver that stays offline - #1628

Open
frahlg wants to merge 2 commits into
masterfrom
cursor/driver-restart-watchdog-2017
Open

frahlg wants to merge 2 commits into
masterfrom
cursor/driver-restart-watchdog-2017

Conversation

@frahlg

@frahlg frahlg commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Problem and result

A Pixii stayed offline after a power outage until someone restarted the driver by hand. Core only restarted a driver on a config change or a manual RestartByName, and a driver that failed to start at boot was logged once and never retried.

The registry now restarts a driver that has been offline or stale, or that failed to start, with backoff 30s, 1 min, 2 min, 5 min, then every 5 min. A fresh reading resets the backoff. Each automatic restart is logged, and /api/status reports auto_restarts, auto_restart_reason, auto_restart_error, and next_auto_restart_ms.

Related to #522. That GoodWe case is a dead Modbus TCP session after the controller reboots. TCP keepalive already landed; this does not change the dialer. It does replace a Modbus driver, including a Pixii or a GoodWe, whose session has gone stale, by stopping it (which runs driver_default_mode) and starting it again.

Scope and safety

Disabled drivers and observe-only drivers are left alone. A disabled entry does not stop a driver that is still running; reload owns that.

A running cloud or OAuth driver is not torn down when it goes quiet. driver_init is where a rotated refresh token is applied, and restarting a live login would repeat the re-auth loop Registry.Add warns about. A cloud driver that failed to start is retried on the same backoff.

MQTT, WebSocket, and TCP drivers that are polling and have never delivered a reading are waiting, not dead. A push driver that has delivered data and then goes stale is restarted. That memory survives the health record being wiped on remove.

The watchdog takes the same per-driver lifecycle lock as Reload and Restart, then uses the same remove-and-add path, including driver_default_mode on the way out and again at startup. It does not run inside the control tick. On process exit it is cancelled and waited for before ShutdownAll, so it cannot start a driver shutdown has already removed.

The existing control-loop watchdog still marks a driver offline and sends its default mode. This one replaces the process when that is not enough. Stale site-meter data still stops dispatch; planner output is still not sent to hardware.

Open PRs #1003, #1364, #1337, and #1546 also touch main.go or api.go, in other regions. This branch is based on master and does not include those changes.

Verification

cd go && make -C .. drivers
cd go && go vet ./...
cd go && go test -count=1 -timeout 300s ./...
cd go/protocol && go vet ./... && go test -count=1 ./...

All passed. The watchdog tests cover offline then restart then recovered (including driver_default_mode), backoff growth through 30s/1m/2m/5m/5m and reset to 30s, disabled and observe-only left alone, start failure retried, a running cloud driver left alone with start failures still retried, MQTT waiting left alone, the lifecycle lock, and a cancelled context.

/api/status covers auto_restarts, the reason, the error, and the next attempt. GitHub CI on this PR is green, including test / go test + vet.

No hardware run. A Pixii or GoodWe that stays offline after a power loss or a controller reboot still needs a site check.

Checklist

  • The change follows VISION.md and one selected scope.
  • I checked overlapping PRs and coordinated shared files/contracts.
  • Relevant checks cover the changed behaviour and failure paths.
  • A human reviewed changed UI in a browser, or no UI changed.
  • A Changeset is included, or the change is exempt.
  • Every commit has a DCO sign-off.
Open in Web Open in Cursor 

A driver that went offline or failed to start stayed down until a config
reload or a manual restart. The watchdog retries with backoff, and leaves
disabled, observe-only, waiting push, and running cloud drivers alone.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@frahlg
frahlg marked this pull request as ready for review October 14, 2026 15:49
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 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 ⚠️ Failed 2026-10-15T05:26:30.757785Z a9dd434 Manual request
ℹ️ 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: ce8fffd49e

ℹ️ 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 thread go/cmd/ftw/main.go
The watchdog copied the driver list, dropped the config lock, and could
then start that copy after a reload had already disabled or edited the
driver. It now re-reads the installed config after the lifecycle gate
and leaves a disabled, observe-only, or changed driver to reload.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@cursor

cursor Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@frahlg

frahlg commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Provided git ref a9dd4345eb98e0c80e734d3590cde25e76941a45 does not exist
ℹ️ 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".

frahlg commented Oct 18, 2026

Copy link
Copy Markdown
Member Author

The configuration-recheck finding is addressed in a9dd4345: the watchdog rereads the current configuration after acquiring the lifecycle gate and rejects a removed, disabled, observe-only or changed snapshot. TestRestartWatchdogRechecksConfigAfterLifecycleGate passed three times with the race detector on that exact head during this triage. Resolving the addressed review point; this does not merge or deploy the PR.

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.

2 participants