refactor(worker/queue): split queue waker and picker, auto-wake on enqueue
Slice 3 of the worker state and queue consolidation refactor. - Add IQueueWaker / QueueWaker (singleton holding the wake semaphore). - Add IQueuePicker / QueuePicker; raw SQL UPDATE...RETURNING moves out of TaskRepository.GetNextQueuedAgentTaskAsync (deleted) and now also filters on blocked_by_task_id IS NULL and writes started_at on claim. - TaskStateService takes IQueueWaker directly; the Func<QueueService> indirection is gone. State transitions to Queued auto-wake the dispatcher. - QueueService waits via the shared waker and dispatches via the picker. - Drop explicit _queue.WakeQueue() calls in WorkerHub.QueuePlanningSubtasksAsync and ExternalMcpService.AddTask. The hub WakeQueue endpoint stays for diagnostics, delegating to _waker.Wake(). - Migrate tests; pre-existing flaky AppSettings/ExternalMcp tests untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
8823265e5a
commit
064a903076
@@ -0,0 +1,18 @@
|
||||
namespace ClaudeDo.Worker.Queue;
|
||||
|
||||
/// <summary>
|
||||
/// Owns the wake semaphore. Producers (state mutations, hub) call Wake();
|
||||
/// the queue dispatcher awaits WaitAsync.
|
||||
/// </summary>
|
||||
public sealed class QueueWaker : IQueueWaker
|
||||
{
|
||||
private readonly SemaphoreSlim _signal = new(0, 1);
|
||||
|
||||
public void Wake()
|
||||
{
|
||||
try { _signal.Release(); }
|
||||
catch (SemaphoreFullException) { /* already signalled */ }
|
||||
}
|
||||
|
||||
public Task WaitAsync(CancellationToken ct) => _signal.WaitAsync(ct);
|
||||
}
|
||||
Reference in New Issue
Block a user