File tree Expand file tree Collapse file tree 1 file changed +24
-0
lines changed
Expand file tree Collapse file tree 1 file changed +24
-0
lines changed Original file line number Diff line number Diff line change @@ -431,6 +431,30 @@ export class CircuitBreaker<T = unknown> {
431431 * @returns The result of the operation.
432432 * @throws {CircuitBreakerOpenError } If circuit is open.
433433 */
434+ /*
435+ * NOTE: Known race condition in half-open state concurrent tracking.
436+ *
437+ * The `halfOpenInFlight` counter uses a read-modify-write pattern that is
438+ * not atomic. Under high concurrency, more requests than `halfOpenMaxConcurrent`
439+ * may slip through.
440+ *
441+ * Future fix: Once `@std/async/unstable-semaphore` stabilizes, use it to
442+ * guard state transitions:
443+ *
444+ * ```ts
445+ * import { Semaphore } from "@std/async/semaphore";
446+ *
447+ * #stateMutex = new Semaphore(1);
448+ *
449+ * async execute<R extends T>(fn: () => Promise<R>): Promise<R> {
450+ * {
451+ * using _lock = await this.#stateMutex.acquire();
452+ * // Check state and acquire half-open slot atomically
453+ * }
454+ * // Execute fn() outside the lock
455+ * }
456+ * ```
457+ */
434458 async execute < R extends T > ( fn : ( ) => Promise < R > ) : Promise < R > {
435459 const currentTime = Date . now ( ) ;
436460 const currentState = this . #resolveCurrentState( ) ;
You can’t perform that action at this time.
0 commit comments