feat(refine): wire RefineTask hub method, broadcaster events, and DI

This commit is contained in:
mika kuns
2026-06-04 23:14:00 +02:00
parent 0460d7bea5
commit e523ed85eb
6 changed files with 29 additions and 5 deletions

View File

@@ -1,10 +1,11 @@
using ClaudeDo.Data.Models; using ClaudeDo.Data.Models;
using ClaudeDo.Worker.Prime; using ClaudeDo.Worker.Prime;
using ClaudeDo.Worker.Refine;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
namespace ClaudeDo.Worker.Hub; namespace ClaudeDo.Worker.Hub;
public sealed class HubBroadcaster : IPrimeBroadcaster public sealed class HubBroadcaster : IPrimeBroadcaster, IRefineBroadcaster
{ {
private readonly IHubContext<WorkerHub> _hub; private readonly IHubContext<WorkerHub> _hub;
@@ -62,4 +63,12 @@ public sealed class HubBroadcaster : IPrimeBroadcaster
Task IPrimeBroadcaster.PrepStartedAsync() => PrepStarted(); Task IPrimeBroadcaster.PrepStartedAsync() => PrepStarted();
Task IPrimeBroadcaster.PrepLineAsync(string line) => PrepLine(line); Task IPrimeBroadcaster.PrepLineAsync(string line) => PrepLine(line);
Task IPrimeBroadcaster.PrepFinishedAsync(bool success) => PrepFinished(success); Task IPrimeBroadcaster.PrepFinishedAsync(bool success) => PrepFinished(success);
public Task RefineStarted(string taskId) => _hub.Clients.All.SendAsync("RefineStarted", taskId);
public Task RefineFinished(string taskId, bool success, string? error) =>
_hub.Clients.All.SendAsync("RefineFinished", taskId, success, error);
Task IRefineBroadcaster.RefineStartedAsync(string taskId) => RefineStarted(taskId);
Task IRefineBroadcaster.RefineFinishedAsync(string taskId, bool success, string? error) =>
RefineFinished(taskId, success, error);
} }

View File

@@ -8,6 +8,7 @@ using ClaudeDo.Worker.Lifecycle;
using ClaudeDo.Worker.Planning; using ClaudeDo.Worker.Planning;
using ClaudeDo.Worker.Prime; using ClaudeDo.Worker.Prime;
using ClaudeDo.Worker.Queue; using ClaudeDo.Worker.Queue;
using ClaudeDo.Worker.Refine;
using ClaudeDo.Worker.Report; using ClaudeDo.Worker.Report;
using ClaudeDo.Worker.Report.Interfaces; using ClaudeDo.Worker.Report.Interfaces;
using ClaudeDo.Worker.State; using ClaudeDo.Worker.State;
@@ -83,6 +84,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
private readonly IPrimeRunner _primeRunner; private readonly IPrimeRunner _primeRunner;
private readonly ITaskStateService _state; private readonly ITaskStateService _state;
private readonly IWeekReportService _report; private readonly IWeekReportService _report;
private readonly IRefineRunner _refineRunner;
public WorkerHub( public WorkerHub(
QueueService queue, QueueService queue,
@@ -102,7 +104,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
IPrimeScheduleSignal primeSignal, IPrimeScheduleSignal primeSignal,
IPrimeRunner primeRunner, IPrimeRunner primeRunner,
ITaskStateService state, ITaskStateService state,
IWeekReportService report) IWeekReportService report,
IRefineRunner refineRunner)
{ {
_queue = queue; _queue = queue;
_waker = waker; _waker = waker;
@@ -122,6 +125,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
_primeRunner = primeRunner; _primeRunner = primeRunner;
_state = state; _state = state;
_report = report; _report = report;
_refineRunner = refineRunner;
} }
// Maps the two exceptions service methods throw into client-facing HubExceptions: // Maps the two exceptions service methods throw into client-facing HubExceptions:
@@ -541,6 +545,12 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
_primeSignal.Signal(); _primeSignal.Signal();
} }
public Task RefineTask(string taskId)
{
_ = _refineRunner.RefineAsync(taskId, CancellationToken.None);
return Task.CompletedTask;
}
public async Task<bool> RunDailyPrepNow() public async Task<bool> RunDailyPrepNow()
{ {
var schedule = new PrimeScheduleDto(Guid.Empty, 0, TimeSpan.Zero, true, null, null); var schedule = new PrimeScheduleDto(Guid.Empty, 0, TimeSpan.Zero, true, null, null);

View File

@@ -12,6 +12,7 @@ using ClaudeDo.Worker.Queue;
using ClaudeDo.Worker.Runner; using ClaudeDo.Worker.Runner;
using ClaudeDo.Worker.State; using ClaudeDo.Worker.State;
using ClaudeDo.Worker.Prime; using ClaudeDo.Worker.Prime;
using ClaudeDo.Worker.Refine;
using ClaudeDo.Worker.Report; using ClaudeDo.Worker.Report;
using ClaudeDo.Worker.Report.Interfaces; using ClaudeDo.Worker.Report.Interfaces;
using ClaudeDo.Worker.Worktrees; using ClaudeDo.Worker.Worktrees;
@@ -108,6 +109,10 @@ builder.Services.AddSingleton(PrimeSchedulerOptions.Default);
builder.Services.AddSingleton<IPrimeBroadcaster>(sp => sp.GetRequiredService<HubBroadcaster>()); builder.Services.AddSingleton<IPrimeBroadcaster>(sp => sp.GetRequiredService<HubBroadcaster>());
builder.Services.AddHostedService<PrimeScheduler>(); builder.Services.AddHostedService<PrimeScheduler>();
// Refine
builder.Services.AddSingleton<IRefineRunner, RefineRunner>();
builder.Services.AddSingleton<IRefineBroadcaster>(sp => sp.GetRequiredService<HubBroadcaster>());
// QueueService: singleton + hosted service (same instance). // QueueService: singleton + hosted service (same instance).
builder.Services.AddSingleton<QueueService>(); builder.Services.AddSingleton<QueueService>();
builder.Services.AddHostedService(sp => sp.GetRequiredService<QueueService>()); builder.Services.AddHostedService(sp => sp.GetRequiredService<QueueService>());

View File

@@ -19,7 +19,7 @@ public sealed class ClearMyDayHubTests : IDisposable
var broadcaster = new HubBroadcaster(new CapturingHubContext()); var broadcaster = new HubBroadcaster(new CapturingHubContext());
var hub = new WorkerHub( var hub = new WorkerHub(
null!, null!, null!, null!, broadcaster, _db.CreateFactory(), null!, null!, null!, null!, broadcaster, _db.CreateFactory(),
null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!); null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
hub.Clients = new FakeHubCallerClients(new RecordingClientProxy()); hub.Clients = new FakeHubCallerClients(new RecordingClientProxy());
hub.Context = new FakeHubCallerContext(); hub.Context = new FakeHubCallerContext();
return hub; return hub;

View File

@@ -55,7 +55,7 @@ public sealed class PlanningHubTests : IDisposable
{ {
var hub = new WorkerHub( var hub = new WorkerHub(
null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!,
_planning, _launcher, null!, null!, null!, null!, null!, null!, null!); _planning, _launcher, null!, null!, null!, null!, null!, null!, null!, null!);
hub.Clients = new FakeHubCallerClients(_proxy); hub.Clients = new FakeHubCallerClients(_proxy);
hub.Context = new FakeHubCallerContext(); hub.Context = new FakeHubCallerContext();
return hub; return hub;

View File

@@ -19,7 +19,7 @@ public sealed class WorktreeStateHubTests : IDisposable
var broadcaster = new HubBroadcaster(new CapturingHubContext()); var broadcaster = new HubBroadcaster(new CapturingHubContext());
var hub = new WorkerHub( var hub = new WorkerHub(
null!, null!, null!, null!, broadcaster, _db.CreateFactory(), null!, null!, null!, null!, broadcaster, _db.CreateFactory(),
null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!); null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!);
hub.Clients = new FakeHubCallerClients(new RecordingClientProxy()); hub.Clients = new FakeHubCallerClients(new RecordingClientProxy());
hub.Context = new FakeHubCallerContext(); hub.Context = new FakeHubCallerContext();
return hub; return hub;