Added service cache feature flag

Updated scheduler and moved to its own dedicated database
This commit is contained in:
2026-09-18 16:11:14 +02:00
parent 6d554d19a7
commit b703b0c64d
7 changed files with 68 additions and 57 deletions
@@ -26,7 +26,7 @@ public sealed class JobOrchestrator(ISchedulerFactory schedulerFactory) : IJobOr
.StartNow()
.Build();
await scheduler.ScheduleJob(job, new List<ITrigger> { trigger }.AsReadOnly(), replace: true, cancellationToken);
await scheduler.ScheduleJob(job, new List<ITrigger> { trigger }.AsReadOnly(), new ScheduleJobOptions { Replace = true }, cancellationToken);
}
public async ValueTask ScheduleAsync<TNotification>(TNotification notification, string cronExpression, CancellationToken cancellationToken = default)
@@ -51,17 +51,16 @@ public sealed class JobOrchestrator(ISchedulerFactory schedulerFactory) : IJobOr
var trigger = global::Quartz.TriggerBuilder.Create()
.WithIdentity(triggerKey)
.WithDescription($"Scheduled via Main Job at {now:g}")
.WithCronSchedule(cronExpression, cron => cron
.WithMisfireHandlingInstructionIgnoreMisfires())
.WithCronSchedule(cronExpression, cron => cron.WithMisfireInstruction(CronTriggerMisfireInstruction.IgnoreMisfires))
.StartAt((DateTimeOffset)now)
.Build();
await scheduler.AddJob(job, replace: true, cancellationToken);
await scheduler.AddJob(job, new AddJobOptions { Replace = true }, cancellationToken);
if (await scheduler.CheckExists(triggerKey, cancellationToken))
if (await scheduler.Exists(triggerKey, cancellationToken))
await scheduler.RescheduleJob(triggerKey, trigger, cancellationToken);
else
await scheduler.ScheduleJob(job, new List<ITrigger> { trigger }.AsReadOnly(), replace: true, cancellationToken);
await scheduler.ScheduleJob(job, new List<ITrigger> { trigger }.AsReadOnly(), new ScheduleJobOptions { Replace = true }, cancellationToken);
}
public async ValueTask<bool> InterruptAsync(string eventName, string? correlationId = null, CancellationToken cancellationToken = default)
@@ -82,6 +81,6 @@ public sealed class JobOrchestrator(ISchedulerFactory schedulerFactory) : IJobOr
jobGroup = "scheduled-jobs";
}
return await scheduler.Interrupt(JobKey.Create(jobKeyName, jobGroup), cancellationToken);
return await scheduler.Interrupt(new JobKey(jobKeyName, jobGroup), cancellationToken);
}
}
@@ -7,7 +7,8 @@ namespace PostFundManagement.Domain.Quartz;
[DisallowConcurrentExecution]
public sealed class MediatorJob<TNotification>(IMediator mediator) : IJob where TNotification : IEvent
{
public async Task Execute(IJobExecutionContext context)
public async ValueTask Execute(IJobExecutionContext context, CancellationToken cancellationToken = default)
{
if (context.Recovering)
Trace.WriteLine($"CRITICAL RECOVERY: Resurrecting job '{typeof(TNotification).Name}' after a previous cluster node crashed mid-execution.");
@@ -43,7 +44,7 @@ public sealed class MediatorJob<TNotification>(IMediator mediator) : IJob where
catch (OperationCanceledException) when (context.CancellationToken.IsCancellationRequested)
{
Trace.WriteLine($"Job '{typeof(TNotification).Name}' was gracefully interrupted by the cluster control plane.");
activity?.SetStatus(ActivityStatusCode.Ok);
return;
@@ -16,6 +16,23 @@ public sealed class RetryJobListener : IJobListener
return;
if (jobException is not null && context.RefireCount < RetryCount)
jobException.RefireImmediately = true;
{
if (context.JobDetail is null)
return;
var triggers = await context.Scheduler.GetTriggersOfJob(context.JobDetail.Key, cancellationToken);
var oldTrigger = triggers?.FirstOrDefault();
if (oldTrigger is null)
return;
var newTrigger = global::Quartz.TriggerBuilder.Create()
.WithIdentity($"{oldTrigger.Key.Name}-retry-{context.RefireCount}", oldTrigger.Key.Group)
.StartNow()
.ForJob(context.JobDetail.Key)
.Build();
await context.Scheduler.RescheduleJob(oldTrigger.Key, newTrigger, cancellationToken);
}
}
}