Aias00 opened a new issue, #8026:
URL: https://github.com/apache/shenyu/issues/8026

   ### Is there an existing issue for this?
   
   - [x] I have searched the existing issues.
   
   ### Current Behavior
   
   recordTokensUsage performs SET NX with expiry, optionally reads/repairs TTL, 
and finally INCRBY as separate Redis operations. If an existing counter expires 
between those operations, INCRBY recreates it without an expiration. A 
successful earlier TTL check does not protect against that race; an EXPIRE on a 
now-missing key can also return false before INCRBY recreates it. If the 
recorded usage reaches tokenLimit, admission rejects subsequent requests and no 
new response accounting may occur to repair the missing TTL, so rejection can 
outlive the configured window indefinitely.
   
   ### Expected Behavior
   
   Every counter created by accounting must have the configured window expiry, 
including at expiry races. An existing live fixed-window counter must keep its 
remaining TTL rather than having it extended on every increment. Budget 
recovery after the window must not require another successful request.
   
   ### Steps To Reproduce
   
   Use a real Redis integration test with barriers between accounting commands:
   
   1. Seed the rule/key counter with a short positive TTL.
   2. Let SET NX observe the existing key and let getExpire return a positive 
TTL, so no expiry repair is scheduled.
   3. Allow the key to expire before the increment command (or delete it at a 
test barrier to model expiry).
   4. Execute INCRBY with usage >= tokenLimit; inspect the recreated key's TTL, 
which is now -1.
   5. Invoke admission after one configured window. GET still sees the limit 
and requests remain rejected.
   
   Also test expiry between a missing-key TTL result/EXPIRE and INCRBY. This 
interleaving is source-derived and has not been executed here.
   
   ### Environment
   
   - ShenYu master / 2.7.2-SNAPSHOT, commit 
`34f2ed036747936a5e28aea2c94cd9b3cddcce47`.
   - Source-inspection report. The reporting environment has no available JDK; 
no Maven/JUnit, live backend or Redis reproduction is claimed.
   - Existing runtime behavior; unrelated to proposed plugin orchestration.
   
   ### Debug logs
   
   No runtime logs captured. Code evidence follows.
   
   ### Code evidence
   
   - [Non-atomic initialization, TTL inspection and 
increment](https://github.com/apache/shenyu/blob/34f2ed036747936a5e28aea2c94cd9b3cddcce47/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-token-limiter/src/main/java/org/apache/shenyu/plugin/ai/token/limiter/AiTokenLimiterPlugin.java#L184-L196)
   - [Admission only reads accumulated 
usage](https://github.com/apache/shenyu/blob/34f2ed036747936a5e28aea2c94cd9b3cddcce47/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-token-limiter/src/main/java/org/apache/shenyu/plugin/ai/token/limiter/AiTokenLimiterPlugin.java#L143-L157)
   - [Existing tests mock isolated TTL outcomes, not expiry between 
commands](https://github.com/apache/shenyu/blob/34f2ed036747936a5e28aea2c94cd9b3cddcce47/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-token-limiter/src/test/java/org/apache/shenyu/plugin/ai/token/limiter/AiTokenLimiterPluginTest.java)
   
   ### Suggested fix direction
   
   Use a single atomic Redis script/function for increment plus expiry 
initialization/repair. Preserve an already-valid fixed-window TTL, assign 
expiry to a newly created/no-TTL counter, and define the zero-remaining-expiry 
boundary. Handle accounting failures explicitly rather than rely on a future 
request to repair state.
   
   ### Acceptance criteria
   
   - Forced expiry at every prior command boundary cannot produce a persistent 
no-TTL counter.
   - A live counter retains its original deadline under sustained increments.
   - Concurrent writers across gateway instances cannot strand a permanent 
counter.
   - Admission recovers after the configured window even when the final 
accounting increment exceeded the limit.
   - Cover absent key, legacy no-TTL key, live key and response accounting 
across window boundaries.
   
   ### Related work and scope
   
   Distinct from #6649 (refreshing TTL on every increment prevents reset) and 
#7702 (in-flight token reservation/overshoot). This is a non-atomic 
expiry/recreation correctness defect in existing completed-usage accounting. 
Suggested priority: P1.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to