← All source files

V7 / 2a442462cf3f

ScheduleDelivery.cs

Lilith/Core/Scheduling/ScheduleDelivery.cs

Unchanged from the preceding version
CS
namespace Lilith.Core.Scheduling;

/// <summary>The host calls this only while it owns conversation and narration access.</summary>
public static class ScheduleDelivery
{
    public static async Task DrainAsync(ProviderClient provider, Func<string, CancellationToken, Task> narrate,
        CancellationToken ct = default)
    {
        var schedules = provider.Schedules ?? throw new InvalidOperationException("Configure schedules first.");
        for (int i = 0; i < 10 && schedules.PeekEvent() is { } item; i++)
        {
            ct.ThrowIfCancellationRequested();
            provider.RecordScheduleEvent(item);
            string? failure = null;
            Exception? speechFailure = null;
            try
            {
                // A speech failure must not prevent the scheduled action from running.
                try { await narrate(item.Message, ct); }
                catch (Exception ex) when (ex is not OperationCanceledException)
                { speechFailure = ex; }
                if (item.Job is { Scenario.Length: > 0 } job)
                {
                    string reply = await provider.RunScheduledScenarioAsync(job.Scenario, job.Inputs, ct);
                    try { await narrate(reply, ct); }
                    catch (Exception ex) when (ex is not OperationCanceledException) { speechFailure = ex; }
                }
            }
            catch (OperationCanceledException) when (ct.IsCancellationRequested) { throw; }
            catch (Exception ex) { failure = ex.Message; }
            schedules.CompleteEvent(item.Id, failure);
            if (speechFailure is not null) throw new InvalidOperationException("Schedule speech failed; the action outcome was retained.", speechFailure);
        }
    }
}