Skip to content

Commit 4dbb5ea

Browse files
committed
fix: resolve race condition in telemetry queue persist operations
- Move pendingPersist flag clearing inside persistQueue() method - Implement loop-based draining to handle concurrent persist requests - Add comprehensive tests for concurrent operations - Ensures no telemetry events are lost during rapid enqueue operations The previous implementation had a lost-notification bug where the pendingPersist flag was cleared in the setImmediate callback before calling persistQueue(). This could cause events enqueued during an in-flight persist to remain unpersisted. The fix implements Option A: clearing the flag inside persistQueue() and using a while loop to drain all pending requests, ensuring any enqueue that happens during a persist operation triggers another persist pass immediately after.
1 parent ef3aeb3 commit 4dbb5ea

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

packages/telemetry/src/TelemetryQueueManager.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ export class TelemetryQueueManager {
231231

232232
// Use setImmediate to batch multiple rapid enqueue operations
233233
setImmediate(() => {
234-
this.pendingPersist = false
235234
this.persistQueue()
236235
})
237236
}
@@ -240,17 +239,24 @@ export class TelemetryQueueManager {
240239
* Persist queue to disk
241240
*/
242241
private async persistQueue(): Promise<void> {
243-
// If a persist is already in progress, wait for it to complete
242+
// If a persist is already in progress, wait for it to complete first
244243
if (this.persistPromise) {
245244
await this.persistPromise
246-
return
247245
}
248246

249-
this.persistPromise = this.doPersist()
250-
try {
251-
await this.persistPromise
252-
} finally {
253-
this.persistPromise = null
247+
// Drain all pending persist requests in a loop
248+
// This ensures that any enqueue that happens during a persist operation
249+
// will trigger another persist pass immediately after
250+
while (this.pendingPersist) {
251+
this.pendingPersist = false
252+
253+
this.persistPromise = this.doPersist()
254+
try {
255+
await this.persistPromise
256+
} finally {
257+
this.persistPromise = null
258+
}
259+
// If enqueue() ran during doPersist, pendingPersist will be true again
254260
}
255261
}
256262

0 commit comments

Comments
 (0)