mirror of
https://github.com/HeyPuter/puter.git
synced 2026-11-06 14:07:51 +00:00
`reserveAiCredits` checked the balance and then took an unconditional hold, so concurrent requests could all pass the check before any hold was visible; two 16.2M µ¢ holds were admitted against a 20M µ¢ balance. The hold store now takes a hold only if it fits beside the live holds, in one Lua script on the actor's hold key. A per-user version, bumped when usage is recorded and when a hold is released, lets the script refuse a balance read that a settlement has since overtaken; the service reads the balance again and retries, and skips the version check on its last attempt rather than refuse an account whose balance keeps moving. Both keys share the actor's hash tag, so the script runs on Redis Cluster. The balance read for this check reads purchased credit consistently. `reserveCreditsIfAffordable` carries this through the service, and the AI facade calls it once with the cost factor applied. `reserveCredits` keeps its unconditional semantics. When the cache is unreachable, the balance alone decides and nothing is held, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>