@rtc-agent/component 0.2.8-rc.4 → 0.2.9-rc.0

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.
@@ -44,9 +44,27 @@ export declare class WorkerBridge {
44
44
  /** Comlink-proxied callbacks (for cross-Worker transfer). */
45
45
  private _proxiedCallbacks;
46
46
  private _initialized;
47
+ /** Promise-based dedup guard: concurrent init() calls share the same initialization. */
48
+ private _initPromise;
49
+ /** AbortController for cancelling ongoing catch-up */
50
+ private _catchUpAbortController?;
47
51
  private _config;
48
52
  /** Connection state listeners (main-thread side). */
49
53
  private _connectionListeners;
54
+ /**
55
+ * Whether sessionStorage cursor has been restored (only once per instance lifetime).
56
+ * Prevents destroy(false) + init() from re-loading a stale sessionStorage cursor.
57
+ */
58
+ private _hasRestoredFromStorage;
59
+ /**
60
+ * Last processed UI update sequence number (for catch-up after page refresh).
61
+ * Persisted in sessionStorage to survive page refreshes within the same tab.
62
+ * Updated during both catch-up and real-time broadcasts to minimize redundant replays.
63
+ */
64
+ private _lastProcessedSeq;
65
+ /** Database name for scoping sessionStorage key (prevents cross-instance collisions). */
66
+ private _databaseName;
67
+ private static readonly SESSION_STORAGE_KEY_PREFIX;
50
68
  private static readonly MAX_INIT_RETRIES;
51
69
  private static readonly INIT_RETRY_DELAY_MS;
52
70
  /** Timeout for worker liveness verification (ping/pong). */
@@ -112,19 +130,31 @@ export declare class WorkerBridge {
112
130
  * 1. Call Worker's core.init() to initialize shared state.
113
131
  * 2. Register this tab's callbacks (onUIUpdate + requestToken + onConnectionStateChange).
114
132
  * 3. Open the port to start communication.
133
+ * 4. Catch up on missed UI update events (persisted in Worker's IndexedDB).
134
+ * Callbacks are registered first so real-time events arriving during catch-up
135
+ * update _lastProcessedSeq, preventing both loss and duplication.
115
136
  *
116
137
  * Idempotent: only the first call takes effect.
138
+ * Concurrent calls share the same initialization Promise (no double catch-up).
117
139
  * Must call initWorker() first.
118
140
  */
119
141
  init(config: PersistenceConfig): Promise<void>;
142
+ /**
143
+ * Internal initialization logic.
144
+ */
145
+ private _doInit;
120
146
  /**
121
147
  * Destroy the bridge.
122
148
  *
123
149
  * 1. Unregister callbacks.
124
150
  * 2. Close the port.
125
151
  * 3. Terminate the Worker (note: SharedWorker only terminates after all ports are closed).
152
+ *
153
+ * @param clearStorage - If true, clear sessionStorage cursor (use when tab is closing).
154
+ * If false (default), keep cursor so component remount doesn't trigger
155
+ * redundant catch-up. Only clear on actual tab close (beforeunload).
126
156
  */
127
- destroy(): Promise<void>;
157
+ destroy(clearStorage?: boolean): Promise<void>;
128
158
  /**
129
159
  * Get the current connection state of RTCAgentClient in the Worker.
130
160
  *
@@ -148,5 +178,54 @@ export declare class WorkerBridge {
148
178
  * Note: virtualFS is a module-level singleton; the replacement is global.
149
179
  */
150
180
  installVirtualFSProxy(): void;
181
+ /**
182
+ * Catch up on missed UI update events from the Worker's persistent queue.
183
+ *
184
+ * Called AFTER registerCallback(), so real-time events arriving during catch-up
185
+ * will update _lastProcessedSeq via the onUIUpdate callback. The catch-up query
186
+ * uses `seq > _lastProcessedSeq`, so it automatically skips events already
187
+ * delivered in real-time — preventing both loss and duplication.
188
+ *
189
+ * Paginated: handles >1000 missed events by looping until hasMore is false.
190
+ * Idempotent: skips entries with seq <= _lastProcessedSeq (guards against
191
+ * events delivered in real-time between the query and the loop iteration).
192
+ * Gap-aware: if hasGap is true, stops and signals onStateGap for full refresh.
193
+ */
194
+ private _doCatchUp;
195
+ /**
196
+ * Yield control to the main thread to allow UI rendering and user interaction.
197
+ *
198
+ * Uses MessageChannel to schedule a macrotask without setTimeout's 4ms minimum
199
+ * delay floor (imposed by HTML spec for deeply-nested setTimeout calls).
200
+ * MessageChannel.postMessage() enqueues a 'message' event as a macrotask,
201
+ * which fires on the next event-loop turn with ~0ms latency.
202
+ *
203
+ * Combined with time-slicing in _doCatchUp, this prevents UI jank regardless
204
+ * of browser (works on Safari which lacks requestIdleCallback).
205
+ */
206
+ private _yieldToMain;
207
+ /**
208
+ * Runtime type validation for UIUpdateEvent.
209
+ *
210
+ * Ensures the event structure is valid before processing (guards against
211
+ * corrupted IndexedDB data or schema mismatches after upgrades).
212
+ */
213
+ private _isValidUIUpdateEvent;
214
+ /**
215
+ * Update the last processed seq and persist to sessionStorage.
216
+ */
217
+ private _updateLastProcessedSeq;
218
+ /**
219
+ * Get the sessionStorage key for this instance (scoped by databaseName).
220
+ */
221
+ private _getSessionStorageKey;
222
+ /**
223
+ * Load last processed seq from sessionStorage.
224
+ */
225
+ private _loadLastProcessedSeq;
226
+ /**
227
+ * Save last processed seq to sessionStorage.
228
+ */
229
+ private _saveLastProcessedSeq;
151
230
  }
152
231
  //# sourceMappingURL=worker-bridge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-bridge.d.ts","sourceRoot":"","sources":["../src/worker-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAc,KAAK,MAAM,EAAC,MAAM,SAAS,CAAC;AAEjD,OAAO,KAAK,EAAC,iBAAiB,EAA4C,MAAM,wBAAwB,CAAC;AACzG,OAAO,KAAK,EAAC,eAAe,EAAE,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAE7E,OAAO,KAAK,EAAC,qBAAqB,EAAkB,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAmErE,MAAM,WAAW,kBAAkB;IAC/B;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IAqCjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IApC1B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,UAAU,CAAkB;IACpC,6DAA6D;IAC7D,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAqB;IAEpC,qDAAqD;IACrD,OAAO,CAAC,oBAAoB,CAAoD;IAEhF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAK;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IACnD,4DAA4D;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAQ;IAEvD;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;gBAUR,KAAK,EAAE,cAAc,EACtC,MAAM,GAAE,kBAAuB;IAuDnC;;;;;;;;;;;;OAYG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BjC;;OAEG;YACW,eAAe;IAuG7B;;;;;;OAMG;YACW,kBAAkB;IA0ChC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAY5B;;OAEG;IACH,OAAO,CAAC,MAAM;IAId;;;;;;;OAOG;IACH,IAAI,IAAI,IAAI,MAAM,CAAC,qBAAqB,CAAC,CAExC;IAED;;;;;;;;;OASG;IACG,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBpD;;;;;;OAMG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB9B;;;;OAIG;IACG,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC;IAIpD;;;;OAIG;IACH,uBAAuB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IASpF;;;;;;;;;OASG;IACH,qBAAqB,IAAI,IAAI;CAyChC"}
1
+ {"version":3,"file":"worker-bridge.d.ts","sourceRoot":"","sources":["../src/worker-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAc,KAAK,MAAM,EAAC,MAAM,SAAS,CAAC;AAEjD,OAAO,KAAK,EAAC,iBAAiB,EAA4C,MAAM,wBAAwB,CAAC;AACzG,OAAO,KAAK,EAAC,eAAe,EAAE,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAE7E,OAAO,KAAK,EAAC,qBAAqB,EAAmC,MAAM,mBAAmB,CAAC;AAC/F,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAmErE,MAAM,WAAW,kBAAkB;IAC/B;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IAyDjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAxD1B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,UAAU,CAAkB;IACpC,6DAA6D;IAC7D,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,YAAY,CAAS;IAC7B,wFAAwF;IACxF,OAAO,CAAC,YAAY,CAA8B;IAClD,sDAAsD;IACtD,OAAO,CAAC,uBAAuB,CAAC,CAAkB;IAClD,OAAO,CAAC,OAAO,CAAqB;IAEpC,qDAAqD;IACrD,OAAO,CAAC,oBAAoB,CAAoD;IAEhF;;;OAGG;IACH,OAAO,CAAC,uBAAuB,CAAS;IAExC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB,CAAS;IAClC,yFAAyF;IACzF,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAuB;IAEzE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAK;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IACnD,4DAA4D;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAQ;IAEvD;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;gBAUR,KAAK,EAAE,cAAc,EACtC,MAAM,GAAE,kBAAuB;IA6EnC;;;;;;;;;;;;OAYG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BjC;;OAEG;YACW,eAAe;IAuG7B;;;;;;OAMG;YACW,kBAAkB;IA0ChC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAY5B;;OAEG;IACH,OAAO,CAAC,MAAM;IAId;;;;;;;OAOG;IACH,IAAI,IAAI,IAAI,MAAM,CAAC,qBAAqB,CAAC,CAExC;IAED;;;;;;;;;;;;;OAaG;IACG,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpD;;OAEG;YACW,OAAO;IAiCrB;;;;;;;;;;OAUG;IACG,OAAO,CAAC,YAAY,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAqClD;;;;OAIG;IACG,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC;IAIpD;;;;OAIG;IACH,uBAAuB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IASpF;;;;;;;;;OASG;IACH,qBAAqB,IAAI,IAAI;IA4C7B;;;;;;;;;;;;OAYG;YACW,UAAU;IAmGxB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,YAAY;IAYpB;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAQ7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAK/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAe7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAQhC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rtc-agent/component",
3
- "version": "0.2.8-rc.4",
3
+ "version": "0.2.9-rc.0",
4
4
  "description": "RTC Agent Web Components(基于 Lit)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -32,10 +32,10 @@
32
32
  "lit": "^3.1.0",
33
33
  "marked": "^18.0.11",
34
34
  "zod": "^3.23.8",
35
- "@rtc-agent/client": "0.2.8-rc.4",
36
- "@rtc-agent/protocol": "0.2.8-rc.4",
37
- "@rtc-agent/worker": "0.2.8-rc.4",
38
- "@rtc-agent/persistence": "0.2.8-rc.4"
35
+ "@rtc-agent/client": "0.2.9-rc.0",
36
+ "@rtc-agent/protocol": "0.2.9-rc.0",
37
+ "@rtc-agent/worker": "0.2.9-rc.0",
38
+ "@rtc-agent/persistence": "0.2.9-rc.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@lit/localize-tools": "^0.8.2",