40 lines
1.5 KiB
C#
40 lines
1.5 KiB
C#
namespace KArtSell.Modules.ModelOperations.Domain;
|
|
|
|
public sealed class ScheduleOccurrencePlanner
|
|
{
|
|
public DateTimeOffset GetNextDueAt(
|
|
DateTimeOffset scheduledFor,
|
|
string cadence,
|
|
string catchUpPolicy,
|
|
int maxCatchUp,
|
|
DateTimeOffset now)
|
|
{
|
|
if (maxCatchUp is < 0 or > 31) throw new ArgumentOutOfRangeException(nameof(maxCatchUp));
|
|
var next = Advance(scheduledFor, cadence);
|
|
if (catchUpPolicy.Equals("ALL_WITH_LIMIT", StringComparison.OrdinalIgnoreCase))
|
|
return next;
|
|
|
|
if (!catchUpPolicy.Equals("LATEST_ONLY", StringComparison.OrdinalIgnoreCase)
|
|
&& !catchUpPolicy.Equals("SKIP_MISSED", StringComparison.OrdinalIgnoreCase))
|
|
throw new InvalidOperationException($"Unsupported catch-up policy '{catchUpPolicy}'.");
|
|
|
|
var guard = 0;
|
|
while (next <= now)
|
|
{
|
|
next = Advance(next, cadence);
|
|
if (++guard > 5000) throw new InvalidOperationException("Schedule catch-up exceeded safety guard.");
|
|
}
|
|
return next;
|
|
}
|
|
|
|
private static DateTimeOffset Advance(DateTimeOffset value, string cadence) => cadence.ToUpperInvariant() switch
|
|
{
|
|
"DAILY" => value.AddDays(1),
|
|
"WEEKLY" => value.AddDays(7),
|
|
"MONTHLY" => value.AddMonths(1),
|
|
"QUARTERLY" => value.AddMonths(3),
|
|
"EVENT_DRIVEN" => value.AddYears(100),
|
|
_ => throw new InvalidOperationException($"Unsupported cadence '{cadence}'.")
|
|
};
|
|
}
|