Toolbar badge: a delivery of N captures recounts every capture N times, and an unreachable Postulo is asked twice every five minutes #53

Closed
opened 2026-10-31 03:04:34 +00:00 by tiagoagueda · 0 comments
Owner

What exists today

On the forge's main (678114c):

  • Reading the whole list every five minutes (src/background.js:13-26, src/lib/waiting.js:62-89): deliberate. postulo-chromium#5 decided it ("A decided capture leaves the list, and updated_since cannot report a removal, so the list is read whole each time"; twelve reads an hour of the 600 a token gets). GET /captures lists only the captures waiting for review, so a normal inbox is one request of one page; the 200-page bound only stops a loop. Not a finding; and postulo-chromium#50 (group by posting_key) changes the counting, not the reading.
  • Recounting per storage change (the scout's N²): background.js:59-66 calls showUnsentCount on every storage.onChanged that touches a capture key. deliver (src/lib/outbox.js:44-110) writes each record at least once (store.update, lines 83 and 100-103), and showUnsentCount (src/lib/local.js:325-340) reads the index and every record (store.list()), the kept list from Postulo and the connection record, then sets badge text, colours, title and icon. So a delivery of N captures does about N to 2N full recounts, each O(N): quadratic in storage reads inside the service worker, for a value only the last one shows. store.dropPage (store.js:133-141) also reads every record once per sent capture.
  • No back-off while unreachable: with nothing to send, deliverAndRead (background.js:18-26) calls checkPostulo() and then readWaitingList() even when the check just recorded unreachable, so each alarm makes two failing requests. A five-minute alarm is already gentle; the waste is the second request, not the rhythm.

What would change

  • Coalesce showUnsentCount in the background: a call while one is pending sets a flag and the running one goes once more at the end (or a 100 ms debounce). The last state always wins, so the badge and title end where they do today.
  • In deliverAndRead, skip readWaitingList when checkPostulo has just recorded unreachable, noPermission or tokenRefused; the last list stays, as waiting.js already promises ("a Postulo that cannot be reached leaves the number where it was").
  • dropPage: check the siblings from the batch's own records (record.batch) rather than listing every capture.

No back-off schedule beyond that: the alarm interval is the grey-icon and badge refresh (#4) as well, and lengthening it while unreachable would make the icon slower to turn back.

What it saves or protects

small: a batch delivery of 40 captures stops making about 80 badge recounts, each reading all 40 records and setting badge, title and icon; an unreachable Postulo gets one request per alarm instead of two

Accessibility

must be checked: the badge text and the button's title (waitingForReview, tokenRefused and the other reasons) must still end on the right value after a delivery; the popup's spoken status (say()) is not touched. Guarded by the unit tests of showUnsentCount/toolbarFor and the badge tests in tests/.

Decisions

  • Back off the alarm while Postulo is unreachable? Recommended: no; dropping the second request is enough, and the icon's state (#4) depends on the five-minute check.

Found by the efficiency and reliability audit of 2026-10-30 (finding PR10; index postulo/postulo#1108). Checked against main at daee30b15 (2026-10-30).

## What exists today On the forge's `main` (`678114c`): - **Reading the whole list every five minutes** (`src/background.js:13-26`, `src/lib/waiting.js:62-89`): deliberate. postulo-chromium#5 decided it ("A decided capture leaves the list, and `updated_since` cannot report a removal, so the list is read whole each time"; twelve reads an hour of the 600 a token gets). `GET /captures` lists only the captures waiting for review, so a normal inbox is one request of one page; the 200-page bound only stops a loop. Not a finding; and postulo-chromium#50 (group by `posting_key`) changes the counting, not the reading. - **Recounting per storage change** (the scout's N²): `background.js:59-66` calls `showUnsentCount` on every `storage.onChanged` that touches a capture key. `deliver` (`src/lib/outbox.js:44-110`) writes each record at least once (`store.update`, lines 83 and 100-103), and `showUnsentCount` (`src/lib/local.js:325-340`) reads the index and every record (`store.list()`), the kept list from Postulo and the connection record, then sets badge text, colours, title and icon. So a delivery of N captures does about N to 2N full recounts, each O(N): quadratic in storage reads inside the service worker, for a value only the last one shows. `store.dropPage` (`store.js:133-141`) also reads every record once per sent capture. - **No back-off while unreachable**: with nothing to send, `deliverAndRead` (`background.js:18-26`) calls `checkPostulo()` and then `readWaitingList()` even when the check just recorded `unreachable`, so each alarm makes two failing requests. A five-minute alarm is already gentle; the waste is the second request, not the rhythm. ## What would change - Coalesce `showUnsentCount` in the background: a call while one is pending sets a flag and the running one goes once more at the end (or a 100 ms debounce). The last state always wins, so the badge and title end where they do today. - In `deliverAndRead`, skip `readWaitingList` when `checkPostulo` has just recorded `unreachable`, `noPermission` or `tokenRefused`; the last list stays, as `waiting.js` already promises ("a Postulo that cannot be reached leaves the number where it was"). - `dropPage`: check the siblings from the batch's own records (`record.batch`) rather than listing every capture. No back-off schedule beyond that: the alarm interval is the grey-icon and badge refresh (#4) as well, and lengthening it while unreachable would make the icon slower to turn back. ## What it saves or protects small: a batch delivery of 40 captures stops making about 80 badge recounts, each reading all 40 records and setting badge, title and icon; an unreachable Postulo gets one request per alarm instead of two ## Accessibility must be checked: the badge text and the button's title (`waitingForReview`, `tokenRefused` and the other reasons) must still end on the right value after a delivery; the popup's spoken status (`say()`) is not touched. Guarded by the unit tests of `showUnsentCount`/`toolbarFor` and the badge tests in `tests/`. ## Decisions - **Back off the alarm while Postulo is unreachable?** Recommended: no; dropping the second request is enough, and the icon's state (#4) depends on the five-minute check. --- Found by the efficiency and reliability audit of 2026-10-30 (finding PR10; index postulo/postulo#1108). Checked against `main` at `daee30b15` (2026-10-30).
tiagoagueda added this to the 0.6.0 milestone 2026-10-31 03:04:34 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo-chromium#53
No description provided.