fix: drive background refresh and phishing update from alarms (closes #158)
All checks were successful
check / check (push) Successful in 29s
All checks were successful
check / check (push) Successful in 29s
The Chrome MV3 service worker is terminated after roughly 30 seconds idle, which destroyed both recurring jobs: the 60-second balance refresh and the 24-hour phishing blocklist refresh were setInterval schedules, so in practice each ran only while the worker happened to be alive. The phishing delta was persisted to localStorage, which does not exist in a service worker, so on Chrome it was never persisted at all. Both jobs now run off the extension alarms API in the new src/shared/alarms.js: the browser holds the schedule and wakes the worker to deliver it. The balance refresh is one minute and the phishing refresh is 1440 minutes, both whole minutes at or above the one-minute minimum, so neither is silently clamped. Alarms are created only when missing or when the existing one carries a different period, because creating one restarts its period and the startup path runs on every wake — while an alarm left at an older release's period would otherwise never be reconciled. Each job's freshness guard is decoupled from its alarm period, or the period would not be the cadence. A guard is measured from when the last run finished, which is one run-duration after the alarm that started it, so a guard timed to the period vetoes the very next tick and the real rate halves. The two are handled differently because the guards differ in purpose: the phishing cache TTL exists to keep the worker off the network on the wakes between refreshes, so the scheduled tick bypasses it and fetches unconditionally; the balance guard exists to skip work an open popup has already done, so it must keep applying on the tick and is instead shortened to half the alarm period — above the popup's 10-second refresh, below the 60-second period. The phishing delta and the timestamps of the fetch that produced it now live in extension storage, and updatePhishingList() reloads that record before deciding whether a fetch is due. A revived worker therefore neither re-fetches on every wake nor sleeps through an overdue update. A timestamp read back from storage is discarded if it lies in the future: clock skew or a restored profile backup would otherwise suppress updates until that time arrived, permanently, now that the value outlives the worker. Two timestamps are kept, not one. The 256 KiB cap still drops an oversized delta together with its freshness claim, but the record of having contacted the network at all is written regardless — as it is after a failed fetch — and floors unscheduled retries at one hour. Without it, a list that is persistently oversized or a fetch that persistently fails means a full blocklist download on every worker wake, indefinitely. The startup path (ensureRecurringAlarms plus the phishing list init) is registered on onInstalled and onStartup as well as running at the top level of the worker, and is idempotent. The concurrent callers on a fresh install share one in-flight run rather than racing to create the same alarm, and a failure is logged instead of becoming an unhandled rejection. Firefox MV2 has a persistent background page where timers would have survived, but both browsers are built from one bundle and both take the alarm path, so there is a single code path; "alarms" is declared in both manifests. src/shared/ens.js keeps its localStorage cache and gains a comment recording that it is popup-only, so it does not get pulled into the worker later.
This commit is contained in:
7
TODO.md
7
TODO.md
@@ -64,6 +64,13 @@ undefined identifiers, which is how
|
||||
on every xprv and xpub, and a non-master key is refused with an explanation
|
||||
instead of being derived beneath
|
||||
([#210](https://git.eeqj.de/sneak/AutistMask/issues/210)).
|
||||
- 2026-08-11: the balance refresh and the 24-hour phishing list refresh moved
|
||||
from `setInterval` to the extension alarms API, with the phishing delta and
|
||||
its fetch timestamps persisted to extension storage, so neither job dies with
|
||||
the MV3 service worker. Each job's freshness guard was decoupled from its
|
||||
alarm period at the same time — timed to the period, a guard vetoes its own
|
||||
scheduled tick and halves the real refresh rate
|
||||
([#158](https://git.eeqj.de/sneak/AutistMask/issues/158)).
|
||||
- 2026-08-11: Policy compliance sweep — conditional verbose test rerun, local
|
||||
Tailwind binary instead of `npx`, `--frozen-lockfile` on `make install`, and
|
||||
the Makefile-only targets documented in the README
|
||||
|
||||
Reference in New Issue
Block a user