fix: keep history responsive during archive work - #1271
Conversation
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d51a710129
ℹ️ 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".
| if !historyWriteBusy(err) { | ||
| return err |
There was a problem hiding this comment.
Retry archive work after the per-attempt deadline
When mergeArchivedHour legitimately takes more than one second—for example, while scanning a dense hour on a slow target disk—tryArchiveBatch returns context.DeadlineExceeded, but this branch treats every non-SQLite-busy error as terminal. Unlike pruning, the hourly merge does not reduce or otherwise resume its work, and its Parquet receipt is written only after the entire file completes, so runSeriesHourBackfill repeatedly restages and restarts the same file without ever becoming ready. Retry this inner deadline after releasing the locks while the parent work budget remains valid, or make the merge resumable.
Useful? React with 👍 / 👎.
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Problem and result
A completed hourly chart can time out when its partial boundary hours wait behind archive staging and compression (#1270). Reads now share a separate lock with file publication and raw pruning. Building and checking an archive no longer excludes those reads. The SQLite-to-Parquet handover stays consistent, and raw values still win when a correction arrives after the archive copy.
Archive writes use short transactions on a reserved SQLite connection with immediate busy errors. They release both locks before retrying, yield to the live queue, and prune at most 64 copied keys per transaction, with smaller retries after a deadline. Dense-hour preparation reads a SQLite snapshot outside the writer locks and the short write budget. If live data changes, the snapshot upgrade fails and the whole preparation retries before the summary can commit. The connection's previous busy timeout is restored before reuse. Live commits honor cancellation while waiting for their mutex and retry temporary SQLite contention promptly without discarding accepted ticks.
Scope and safety
Storage code and synthetic tests only; no schema, API, driver or UI changes. File readback, hashes, sync, atomic rename and copied-key/value checks remain in place. PR #1261 also touches
store.go; this PR changes only its archive mutex fields and leaves that PR's backup work alone.The existing finite queue still rejects overflow explicitly during a prolonged storage outage. The tests establish progress under bounded contention; they do not promise unlimited buffering or prove Raspberry Pi disk latency. Keep #1270 open as a release-blocker until the published beta passes the large-backlog chart checks on hardware.
Verification
make verifypassed locally, including Go tests, vet, builds, Compose checks, release checks and the bundled Energyplan worker.go test -race.Reproduce the focused suite from
go/:No release or hardware installation is part of these test results. Physical EV charging remains untested in this change.
Checklist