67 lines
2 KiB
C#
67 lines
2 KiB
C#
using System;
|
|
using System.Runtime.CompilerServices;
|
|
using Server.Logging;
|
|
|
|
namespace Server.Engines.Events;
|
|
|
|
public abstract class BaseScheduledEvent
|
|
{
|
|
private static readonly ILogger logger = LogFactory.GetLogger(typeof(BaseScheduledEvent));
|
|
|
|
public TimeZoneInfo TimeZone { get; private set; } = TimeZoneInfo.Utc;
|
|
public DateTime NextOccurrence { get; private set; } = DateTime.MaxValue;
|
|
public bool Cancelled { get; private set; }
|
|
public EventScheduler Scheduler { get; private set; }
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void Schedule(DateTime startAfter, TimeZoneInfo timeZone = null) =>
|
|
Schedule(EventScheduler.Shared, startAfter, timeZone);
|
|
|
|
public void Schedule(EventScheduler scheduler, DateTime startAfter, TimeZoneInfo timeZone = null)
|
|
{
|
|
Cancel();
|
|
Scheduler = scheduler;
|
|
TimeZone = timeZone ?? TimeZoneInfo.Utc;
|
|
Schedule(startAfter, timeZone, true);
|
|
}
|
|
|
|
private void Schedule(DateTime startAfter, TimeZoneInfo timeZone, bool isFirst)
|
|
{
|
|
Cancelled = false;
|
|
var afterUtc = startAfter.Kind == DateTimeKind.Utc ? startAfter : startAfter.LocalToUtc(timeZone);
|
|
|
|
var next = GetNextOccurrence(afterUtc);
|
|
|
|
// For the first occurrence, we should set it to the startAfter date if we have no recurrence.
|
|
NextOccurrence = next == DateTime.MaxValue && isFirst ? afterUtc : next;
|
|
|
|
if (NextOccurrence != DateTime.MaxValue)
|
|
{
|
|
Scheduler.ScheduleEvent(this);
|
|
}
|
|
}
|
|
|
|
protected abstract DateTime GetNextOccurrence(DateTime after);
|
|
|
|
public void Cancel()
|
|
{
|
|
Cancelled = true;
|
|
Scheduler?.UnscheduleEvent(this);
|
|
}
|
|
|
|
public virtual void Advance()
|
|
{
|
|
try
|
|
{
|
|
OnEvent();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.Error(ex, "OnEvent failed to execute.");
|
|
}
|
|
|
|
Schedule(NextOccurrence, TimeZone, false);
|
|
}
|
|
|
|
public abstract void OnEvent();
|
|
}
|