Skip to content

fix: ensure subsequent slots execute after PriorityWaitException in FlowSlot#3607

Open
daguimu wants to merge 1 commit intoalibaba:masterfrom
daguimu:fix/flow-slot-priority-wait-skips-slots-issue3604
Open

fix: ensure subsequent slots execute after PriorityWaitException in FlowSlot#3607
daguimu wants to merge 1 commit intoalibaba:masterfrom
daguimu:fix/flow-slot-priority-wait-skips-slots-issue3604

Conversation

@daguimu
Copy link
Copy Markdown

@daguimu daguimu commented Mar 26, 2026

Problem

When FlowSlot.checkFlow() throws PriorityWaitException (for prioritized requests that pass flow control by waiting for a future token), fireEntry() is never called. This causes all subsequent slots in the chain to be skipped.

The default slot chain order is:

StatisticSlot(-7000) → ... → FlowSlot(-2000) → DefaultCircuitBreakerSlot(-1500) → DegradeSlot(-1000)

When PriorityWaitException is thrown, DefaultCircuitBreakerSlot and DegradeSlot are never executed. This means circuit breaker checks are bypassed for priority-waited requests — even if a circuit breaker is in the OPEN state, the request passes through unchecked.

Root Cause

In FlowSlot.entry(), checkFlow() is called before fireEntry(). When checkFlow() throws PriorityWaitException, the exception propagates immediately and fireEntry() (which chains to downstream slots) is never reached:

// Before fix
public void entry(...) throws Throwable {
    checkFlow(...);         // throws PriorityWaitException
    fireEntry(...);         // NEVER reached
}

Fix

Catch PriorityWaitException in FlowSlot.entry(), execute downstream slots via fireEntry(), then re-throw the exception for StatisticSlot to handle:

// After fix
public void entry(...) throws Throwable {
    try {
        checkFlow(...);
    } catch (PriorityWaitException ex) {
        fireEntry(...);     // Execute downstream slots (circuit breaker, degrade)
        throw ex;           // Re-throw for StatisticSlot
    }
    fireEntry(...);
}

If a downstream slot throws BlockException (e.g., circuit breaker is OPEN), the BlockException propagates instead of PriorityWaitException, and StatisticSlot handles it as a block.

Tests Added

  • testPriorityWaitExceptionStillFiresSubsequentSlots: Verifies that downstream slots are executed when PriorityWaitException is thrown, and the exception is still re-thrown.
  • testPriorityWaitWithDownstreamBlockPropagatesBlockException: Verifies that if a downstream slot throws BlockException after a priority wait, the BlockException takes precedence.

All 225 tests in sentinel-core pass.

Impact

Only affects FlowSlot.entry() behavior when PriorityWaitException is thrown (prioritized QPS-based flow control with token waiting). Normal flow control (pass/block) is unchanged.

Fixes #3604

…lowSlot

When FlowSlot.checkFlow() throws PriorityWaitException (for prioritized
requests that pass by waiting), fireEntry() was never called, causing
all subsequent slots in the chain (DefaultCircuitBreakerSlot, DegradeSlot)
to be skipped. This means circuit breaker checks were bypassed for
priority-waited requests.

Catch PriorityWaitException in FlowSlot.entry(), execute downstream
slots via fireEntry(), then re-throw the exception for StatisticSlot
to handle. If a downstream slot throws BlockException (e.g. circuit
breaker is open), the BlockException propagates instead.

Fixes alibaba#3604
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant