Repository navigation
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces publish hedging orchestration and scheduling for the Pub/Sub publisher, adding the CancellationSharer to coordinate attempts and the HedgingScheduler to manage the timing of hedged requests. The review feedback highlights a critical issue where the coordinator prematurely aborts hedged attempts and rejects the promise if the original attempt fails, rather than waiting for all attempts to fail. Additionally, the reviewer recommends rejecting the promise with a cancellation error when cancel() is called to prevent hangs, adding an early return in scheduleFirstHedge if the coordinator is already done, optimizing processQueue by using the pre-calculated now duration, and updating the unit tests to reflect the corrected failure behavior.
54b7b4a to
07ba261
Compare
07ba261 to
97232f5
Compare
97232f5 to
d45823a
Compare
96e021d to
3ed8373
Compare
3ed8373 to
9e130b3
Compare
Overview
This PR is Layer 3 of 7 in Stack #9467, which implements Publish Hedging for
@google-cloud/pubsubto mitigate high-percentile (p99/p99.9) publish tail latencies by sending backup (hedged) publish RPCs when an in-flight batch takes longer than a configurablehedgeDelaythreshold.Stack Structure
feat(gax): support AbortSignal cancellation in CallOptions and createApiCallfeat(pubsub): add HedgingOptions validation and HedgingTokenBucketfeat(pubsub): add CancellationSharer and HedgingScheduler(this PR)feat(pubsub): add OpenTelemetry events and logging for hedged publishfeat(pubsub): integrate publish hedging into MessageQueuetest(pubsub): add unit tests for publish hedging queue integrationtest(pubsub): add publish hedging system testsSummary of Changes in This PR
This layer implements the core hedging state machine (
CancellationSharer) and the event-driven single-timer FIFO hedging queue (HedgingScheduler) usingDurationarithmetic:CancellationSharer(handwritten/pubsub/src/publisher/hedging.ts):attempt 0) and any hedged attempts (attempt 1..N) for a single publish batch.onSuccess()), aborts all other in-flight attempts via theirAbortControllers, and resolvescoordinator.promisewith{response, wasHedged, successfulAttempt}.attempt > 0) fails while the original attempt (attempt 0with GAX retries) is still running, the error is discarded so the batch can still succeed.attempt 0) fails terminally (permanent error or after exhausting GAX retries), all remaining attempts are aborted andcoordinator.promiserejects immediately.HedgedRequest&HedgingScheduler(handwritten/pubsub/src/publisher/hedging.ts):HedgedRequestitems and a singlesetTimeouthandle (queueProcessingTimer) scheduled for the head item'ssendAfterDuration.remainingTimeout:attemptTimeout = atMost(remainingTimeout, MAX_HEDGE_ATTEMPT_TIMEOUT)(capped at10s).tokenBucket.tryAcquireHedgeToken(). If acquired, enqueues the next hedge check (attemptNumber + 1atnow.add(hedgeDelay)) for multiple hedging and invokesstartHedgedAttempt(attemptNumber, attemptTimeout).onRateLimitedand does not re-enqueue the batch.handwritten/pubsub/test/publisher/hedging.ts):CancellationSharer(original wins, hedged wins, hedged failure ignored while original runs, original failure aborts hedged attempts) andHedgingScheduler(multiple hedging athedgeDelayintervals,10s/remainingTimeoutcapping, early completion skipping).