Aias00 commented on PR #7848:
URL: https://github.com/apache/shenyu/pull/7848#issuecomment-6282517186

   ## Review — opt-in token budget reservations
   
   I read the production diff (`RedisTokenBudgetStore`, `TokenBudgetWindow`, 
`TokenBudgetRequest`, the four Lua scripts, `AiTokenLimiterPlugin`, the admin 
validator and the metrics observer). This is unusually disciplined work for a 
change of this size, and I found nothing blocking. Posting as a comment rather 
than an approval because **CI has never run on this branch** — see the end.
   
   ### What I checked and liked
   
   **The Lua scripts are the real contract, and they are written defensively.**
   - `ai_token_reserve.lua` validates every argument with an exact-integer 
guard, checks `used > limit or reserved > limit - used or amount > limit - used 
- reserved` so the comparison itself cannot overflow, and validates the whole 
state *before* writing anything. Returning `6` (window not current) without 
touching state is the right primitive for a fixed window selected with `TIME`.
   - `ai_token_settle.lua` refuses to recreate a missing window, requires a 
repeat settlement to carry the *same* usage, and deliberately allows `actual` 
to exceed the original budget instead of rejecting a truthful measurement.
   - `ai_token_complete_without_usage.lua` distinguishes "provably not 
forwarded" from "usage unknown", and refuses to downgrade a recorded 
`USAGE_UNKNOWN` into a release. That is the exact failure mode a reservation 
scheme usually gets wrong.
   - `string.format('%.0f', ...)` everywhere before `HSET` avoids Lua's 
scientific-notation serialisation for large integers. Small detail, but it is 
the kind of thing that silently corrupts budgets.
   - `ai_token_time.lua` passes a hash-tagged anchor key it never touches, and 
`scopePrefix` SHA-256s the scope so a caller-supplied `{}` cannot move the 
slot. Both correct for Redis Cluster.
   
   **The reactive lifecycle integration is race-safe.**
   `beginForwarding` is a `NOT_FORWARDED → FORWARDED` CAS, and `finish` does 
`getAndSet(CLOSED)`, so a cleanup that wins the race prevents forwarding from 
starting and a request that already forwarded is never reported as released. 
`Mono.usingWhen` covers complete, error and cancel, and `finishReservation` 
bounds cleanup at 5s so a slow Redis cannot hold the response open 
indefinitely. Holding unknown usage until window expiry, rather than guessing 
zero, is the conservative choice and it is documented in the class javadoc.
   
   **Usage extraction distinguishes "zero" from "absent".**
   Using `MAPPER.reader().with(FAIL_ON_TRAILING_TOKENS)` in reservation mode 
means a partially flushed SSE chunk cannot be parsed into a wrong usage number, 
and `isKnownUsage` rejects non-integral, negative and out-of-range values so 
they fall through to `USAGE_UNKNOWN` instead of being coerced to `0`. Skipping 
the legacy `tokensRecorder` path when `reservationMode` is on avoids 
double-counting.
   
   **Validation is applied at both boundaries.** 
`AiTokenLimiterRuleHandleValidator` (admin, before persist/publish), 
`handlerRule` (gateway cache), and 
`AiTokenLimiterHandle.validateReservationSettings()` share one contract, and 
absent legacy handles still pass. The SQL additions cover fresh installs plus 
all five dialects' upgrade scripts.
   
   ### Non-blocking nits
   
   1. `executeWithReservation` constructs `new 
RedisTokenBudgetStore(redisTemplate)` per request. It is a thin wrapper so the 
cost is small, but it is a per-request allocation in the hot path and could be 
a field or a lazily initialised singleton.
   2. `MAX_EXACT_INTEGER` is declared twice — `private` in 
`RedisTokenBudgetStore`, package-private in `TokenBudgetWindow`. One of them 
should reference the other.
   3. `RedisTokenBudgetStore.isValidInteger` does not read instance state; make 
it `static`.
   
   ### ⚠️ CI has not run on this branch
   
   There are no checks on head `ed4c1b5a`, and the reason is not a failure: all 
eight workflow runs for `feat/7702-ai-token-reservation` are in 
`action_required`, i.e. GitHub is waiting for a maintainer to approve workflow 
execution for this fork. Until that happens nothing here is compiled or tested, 
including the new Redis-backed job this PR adds to `ci.yml` — which is 
precisely the job that should validate the Lua scripts.
   
   Please ask a maintainer to approve the pending runs (or push after one has 
been approved), and I will approve once `pr_build` and the new Redis job are 
green. Given the size and the fact that this changes admission control on the 
data plane, I do not want to approve on code reading alone.
   


-- 
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