");
- await context.Response.WriteAsync($"| {entry.Key} | ");
+ await context.Response.WriteAsync($"{entry.Key}");
+ await context.Response.WriteAsync($" ");
+ await context.Response.WriteAsync($"");
+ await context.Response.WriteAsync($"");
+ await context.Response.WriteAsync($" ");
+ await context.Response.WriteAsync($" | ");
await context.Response.WriteAsync($"{schedule} | ");
- await context.Response.WriteAsync($"{cronExpression} | ");
+ await context.Response.WriteAsync($"{cronExpression} | ");
await context.Response.WriteAsync($"");
if (lastRunStarted is not null)
@@ -369,17 +420,106 @@ private static void EnsureNewScheduler(ILogger cronLogger)
}
}
- private void RefreshSchedule([FromForm] string command, HttpContext context)
+ private void RunCommand([FromForm] string command, [FromForm] string? param, HttpContext context)
{
- if (!command.Equals("reload")) return;
+ ScheduledEntry? entry = null;
+ switch (command)
+ {
+ case "run_single":
+ entry = GetScheduleByKey(param!);
+ if (entry != null && entry.LastRunStatus != ScheduledEntry.RUNNING)
+ {
+ _ = Task.Run(() => ProcessContentSyncApi(entry, true));
+ }
+ break;
+ case "run_chain":
+ entry = GetScheduleByKey(param!);
+ if (entry != null && GetRelatedRunningEntry(entry!) == null)
+ {
+ _ = Task.Run(() => ProcessContentSyncApi(entry));
+ }
+ break;
+ case "reload":
+ EnsureNewScheduler(_cronLogger);
+ UpdateScheduler();
+ _scheduler.Start();
+ break;
+ case "resume_chain":
+ ResumeBrokenChains();
+ break;
+ default:
+ break;
+ }
- EnsureNewScheduler(_cronLogger);
+ context.Response.Redirect($"{_baseUrl}/");
+ }
- UpdateScheduler();
+ private void ResumeBrokenChains()
+ {
+ var nextRuns = _scheduler.GetNextOccurrences()
+ .SelectMany(i => i.ScheduledTasks, (i, j) => new { j.Id, i.NextOccurrence })
+ .ToDictionary(o => o.Id, o => o.NextOccurrence);
- _scheduler.Start();
+ foreach (var (key, cronEntry) in _scheduledEntries.Where(k => nextRuns.ContainsKey(k.Key)).OrderBy(kv => nextRuns[kv.Key]))
+ {
+ var entry = cronEntry;
- context.Response.Redirect($"{_baseUrl}/");
+ while (entry is not null)
+ {
+ //await RenderHomePageTableLines(context, entry, nextRuns[key]);
+ entry = entry.RunNext;
+ }
+ }
+
+ foreach (var nextRun in nextRuns)
+ {
+ var entry = _scheduledEntries[nextRun.Key];
+ var baseStartDate = entry.LastRunStarted;
+
+ while(entry != null && entry.LastRunStarted >= baseStartDate)
+ {
+ if (entry.LastRunStatus == CuteSchedule.RUNNING)
+ {
+ entry = null;
+ break;
+ }
+ entry = entry.RunNext;
+ }
+
+ if(entry != null)
+ {
+ _ = Task.Run(() => ProcessContentSyncApi(entry));
+ }
+ }
+ }
+
+ private ScheduledEntry? GetRelatedRunningEntry(ScheduledEntry entry)
+ {
+ string parentKey;
+ if (entry.RunAfter == null)
+ {
+ parentKey = entry.Key;
+ }
+ else
+ {
+ var parentSchedule = entry.RunAfter;
+ while (parentSchedule.RunAfter != null)
+ {
+ parentSchedule = parentSchedule.RunAfter;
+ }
+ parentKey = parentSchedule.Key;
+ }
+
+ var scheduledEntry = _scheduledEntries.Where(k => k.Value.Key == parentKey).FirstOrDefault().Value;
+
+ if (scheduledEntry.LastRunStatus == CuteSchedule.RUNNING) return scheduledEntry;
+ while(scheduledEntry.RunNext != null)
+ {
+ scheduledEntry = scheduledEntry.RunNext;
+ if (scheduledEntry.LastRunStatus == CuteSchedule.RUNNING) return scheduledEntry;
+ }
+
+ return null;
}
private async Task ProcessAndUpdateSchedule(ScheduledEntry entry)
@@ -402,11 +542,11 @@ private void DisplaySchedule()
}
}
- private async Task ProcessContentSyncApi(ScheduledEntry CuteSchedule)
+ private async Task ProcessContentSyncApi(ScheduledEntry cuteSchedule, bool singleRun = false)
{
string verbosity = _settings?.Verbosity.ToString() ?? Verbosity.Normal.ToString();
- var entry = CuteSchedule;
+ var entry = cuteSchedule;
while (entry is not null)
{
@@ -414,7 +554,7 @@ private async Task ProcessContentSyncApi(ScheduledEntry CuteSchedule)
entry.LastRunStarted = DateTime.UtcNow;
entry.LastRunFinished = null;
- entry.LastRunStatus = "running";
+ entry.LastRunStatus = CuteSchedule.RUNNING;
entry.LastRunErrorMessage = string.Empty;
try
@@ -445,13 +585,13 @@ private async Task ProcessContentSyncApi(ScheduledEntry CuteSchedule)
await command.RunAsync(args);
- entry.LastRunStatus = "success";
+ entry.LastRunStatus = CuteSchedule.SUCCESS;
entry.LastRunFinished = DateTime.UtcNow;
}
catch (Exception ex)
{
_console.WriteException(ex);
- entry.LastRunStatus = $"error";
+ entry.LastRunStatus = CuteSchedule.RUNNING;
entry.LastRunErrorMessage = $"Exception: {ex.Message} \nTrace: {ex.StackTrace}";
entry.LastRunFinished = DateTime.UtcNow;
}
@@ -461,6 +601,11 @@ private async Task ProcessContentSyncApi(ScheduledEntry CuteSchedule)
await UpdateScheduleEntry(entry);
}
+ if (singleRun)
+ {
+ break;
+ }
+
entry = entry.RunNext;
}
}
|