@remit/web-client 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/web-client",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "description": "Remit web client, published as composable primitives — the app shell, auth shells, and runtime config. A distributor imports what it composes and bundles it.",
6
6
  "exports": {
@@ -7,7 +7,9 @@ import {
7
7
  __resetStaleAccountSyncGuard,
8
8
  handleBackgroundSyncFailure,
9
9
  hasPollIntervalElapsed,
10
+ MIN_POLL_INTERVAL_MS,
10
11
  POLL_INTERVAL_MS,
12
+ resolvePollIntervalMs,
11
13
  STALENESS_THRESHOLD_MS,
12
14
  selectPollableAccountIds,
13
15
  selectStaleAccountIds,
@@ -104,6 +106,35 @@ describe("POLL_INTERVAL_MS", () => {
104
106
  });
105
107
  });
106
108
 
109
+ describe("resolvePollIntervalMs", () => {
110
+ // This poll shares POST /sync with the refresh control, and that endpoint's
111
+ // triggers skip the server's per-mailbox freshness gate
112
+ // (MAILBOX_FRESHNESS_MS in imap-worker's sync-mailboxes fan-out). A timer is
113
+ // not a person: without this floor, configuring a sub-window interval turns
114
+ // every tick into a full folder-by-folder re-enumeration for every open
115
+ // account, which is exactly the fan-out storm the gate prevents. The floor
116
+ // is what stops a config value from reintroducing it.
117
+ test("never returns less than the server's freshness window", () => {
118
+ assert.equal(resolvePollIntervalMs("10"), MIN_POLL_INTERVAL_MS);
119
+ assert.equal(resolvePollIntervalMs("59"), MIN_POLL_INTERVAL_MS);
120
+ });
121
+
122
+ test("matches the freshness window the fan-out gate uses", () => {
123
+ // Keep in step with MAILBOX_FRESHNESS_MS in
124
+ // packages/imap-worker/src/handlers/sync-mailboxes.ts.
125
+ assert.equal(MIN_POLL_INTERVAL_MS, 60_000);
126
+ });
127
+
128
+ test("honours a configured interval above the floor", () => {
129
+ assert.equal(resolvePollIntervalMs("900"), 900_000);
130
+ });
131
+
132
+ test("falls back to the default when unset or unparseable", () => {
133
+ assert.equal(resolvePollIntervalMs(undefined), 5 * 60 * 1000);
134
+ assert.equal(resolvePollIntervalMs("not-a-number"), 5 * 60 * 1000);
135
+ });
136
+ });
137
+
107
138
  describe("hasPollIntervalElapsed", () => {
108
139
  test("is false immediately after a poll", () => {
109
140
  assert.equal(hasPollIntervalElapsed(NOW, NOW, 60_000), false);
@@ -25,16 +25,42 @@ const parsePositiveIntSeconds = (
25
25
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
26
26
  };
27
27
 
28
+ /**
29
+ * Floor for the poll interval, matching `MAILBOX_FRESHNESS_MS` in the
30
+ * imap-worker's sync-mailboxes fan-out.
31
+ *
32
+ * This poll uses POST /sync, the same endpoint as a person pressing refresh,
33
+ * and that endpoint's triggers skip the server's per-mailbox freshness gate.
34
+ * A timer is not a person: polling faster than the gate's own window would
35
+ * make every tick a full folder-by-folder re-enumeration for every open
36
+ * account — the fan-out storm the gate exists to prevent, reintroduced by a
37
+ * config value. `mailboxPollIntervalSeconds` can lengthen the interval, never
38
+ * shorten it past this: below the window there is nothing to gain, since no
39
+ * mailbox can have become stale in the meantime.
40
+ */
41
+ export const MIN_POLL_INTERVAL_MS = 60 * 1000;
42
+
43
+ /**
44
+ * Resolve the configured poll interval, never returning less than
45
+ * {@link MIN_POLL_INTERVAL_MS}.
46
+ */
47
+ export const resolvePollIntervalMs = (
48
+ configuredSeconds: string | undefined,
49
+ ): number =>
50
+ Math.max(
51
+ parsePositiveIntSeconds(configuredSeconds, DEFAULT_POLL_INTERVAL_SECONDS) *
52
+ 1000,
53
+ MIN_POLL_INTERVAL_MS,
54
+ );
55
+
28
56
  /**
29
57
  * Client-side online-poll interval (#1251): while an account's mail is open,
30
58
  * the tab re-triggers the same sync the pull-to-refresh path uses on this
31
59
  * cadence — the replacement for the server's removed "online tier".
32
60
  */
33
- export const POLL_INTERVAL_MS =
34
- parsePositiveIntSeconds(
35
- getRuntimeConfig().mailboxPollIntervalSeconds,
36
- DEFAULT_POLL_INTERVAL_SECONDS,
37
- ) * 1000;
61
+ export const POLL_INTERVAL_MS = resolvePollIntervalMs(
62
+ getRuntimeConfig().mailboxPollIntervalSeconds,
63
+ );
38
64
 
39
65
  /**
40
66
  * Bounded concurrency for the per-poll fan-out across open accounts —