refactor: extract interfaces to Interfaces folders and consolidate filters
Move interface declarations into per-area Interfaces/ subfolders, merge the small task-list filter classes into StatusFilter/SmartFlagFilter, and simplify related services, converters and hub DTO handling. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -30,40 +30,35 @@ public sealed class OverrideSlotService
|
||||
{
|
||||
using (var context = _dbFactory.CreateDbContext())
|
||||
{
|
||||
var taskRepo = new TaskRepository(context);
|
||||
var exists = await taskRepo.GetByIdAsync(taskId);
|
||||
var exists = await new TaskRepository(context).GetByIdAsync(taskId);
|
||||
if (exists is null)
|
||||
throw new KeyNotFoundException($"Task '{taskId}' not found.");
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_slot is not null)
|
||||
throw new InvalidOperationException("override slot busy");
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
_slot = new QueueSlotState { TaskId = taskId, StartedAt = DateTime.UtcNow, Cts = cts };
|
||||
|
||||
_ = RunInSlotAsync(taskId, cts.Token).ContinueWith(t =>
|
||||
{
|
||||
if (t.IsFaulted)
|
||||
_logger.LogError(t.Exception, "RunInSlotAsync failed for task {TaskId}", taskId);
|
||||
lock (_lock) { _slot = null; }
|
||||
cts.Dispose();
|
||||
}, TaskScheduler.Default);
|
||||
}
|
||||
StartInSlot(taskId, ct => RunInSlotAsync(taskId, ct), "RunInSlotAsync failed for task {TaskId}");
|
||||
}
|
||||
|
||||
public async Task<string> ContinueTask(string taskId, string followUpPrompt)
|
||||
{
|
||||
using var context = _dbFactory.CreateDbContext();
|
||||
var taskRepo = new TaskRepository(context);
|
||||
var task = await taskRepo.GetByIdAsync(taskId)
|
||||
?? throw new KeyNotFoundException($"Task '{taskId}' not found.");
|
||||
using (var context = _dbFactory.CreateDbContext())
|
||||
{
|
||||
var task = await new TaskRepository(context).GetByIdAsync(taskId)
|
||||
?? throw new KeyNotFoundException($"Task '{taskId}' not found.");
|
||||
|
||||
if (task.Status == Data.Models.TaskStatus.Running)
|
||||
throw new InvalidOperationException("task is already running");
|
||||
if (task.Status == Data.Models.TaskStatus.Running)
|
||||
throw new InvalidOperationException("task is already running");
|
||||
}
|
||||
|
||||
StartInSlot(taskId, ct => RunContinueInSlotAsync(taskId, followUpPrompt, ct),
|
||||
"RunContinueInSlotAsync failed for task {TaskId}");
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
// Claims the single override slot under lock, runs <work> in the background,
|
||||
// and releases the slot when it completes. Throws if the slot is already busy.
|
||||
private void StartInSlot(string taskId, Func<CancellationToken, Task> work, string faultMessage)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_slot is not null)
|
||||
@@ -72,16 +67,14 @@ public sealed class OverrideSlotService
|
||||
var cts = new CancellationTokenSource();
|
||||
_slot = new QueueSlotState { TaskId = taskId, StartedAt = DateTime.UtcNow, Cts = cts };
|
||||
|
||||
_ = RunContinueInSlotAsync(taskId, followUpPrompt, cts.Token).ContinueWith(t =>
|
||||
_ = work(cts.Token).ContinueWith(t =>
|
||||
{
|
||||
if (t.IsFaulted)
|
||||
_logger.LogError(t.Exception, "RunContinueInSlotAsync failed for task {TaskId}", taskId);
|
||||
_logger.LogError(t.Exception, faultMessage, taskId);
|
||||
lock (_lock) { _slot = null; }
|
||||
cts.Dispose();
|
||||
}, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public bool TryCancel(string taskId)
|
||||
|
||||
Reference in New Issue
Block a user