78 lines
2.7 KiB
C#
78 lines
2.7 KiB
C#
namespace Zcbot.WindowsNode;
|
|
|
|
internal enum JobTransitionMode
|
|
{
|
|
Normal,
|
|
Recovery,
|
|
}
|
|
|
|
internal static class JobStateMachine
|
|
{
|
|
internal const string Accepted = "accepted";
|
|
internal const string DownloadingInputs = "downloading_inputs";
|
|
internal const string ReadyToRun = "ready_to_run";
|
|
internal const string SoftwareRunning = "software_running";
|
|
internal const string UploadingOutputs = "uploading_outputs";
|
|
internal const string Succeeded = "succeeded";
|
|
internal const string Failed = "failed";
|
|
internal const string Cancelled = "cancelled";
|
|
|
|
private static readonly IReadOnlyDictionary<string, IReadOnlySet<string>> Transitions =
|
|
new Dictionary<string, IReadOnlySet<string>>(StringComparer.Ordinal)
|
|
{
|
|
[Accepted] = Set(DownloadingInputs, Failed, Cancelled),
|
|
[DownloadingInputs] = Set(DownloadingInputs, ReadyToRun, Failed, Cancelled),
|
|
[ReadyToRun] = Set(SoftwareRunning, Failed, Cancelled),
|
|
[SoftwareRunning] = Set(UploadingOutputs, Failed, Cancelled),
|
|
[UploadingOutputs] = Set(UploadingOutputs, Succeeded, Failed, Cancelled),
|
|
[Succeeded] = Set(),
|
|
[Failed] = Set(),
|
|
[Cancelled] = Set(),
|
|
};
|
|
|
|
internal static IReadOnlySet<string> Stages { get; } =
|
|
Transitions.Keys.ToHashSet(StringComparer.Ordinal);
|
|
|
|
internal static IReadOnlySet<string> TerminalStages { get; } =
|
|
Set(Succeeded, Failed, Cancelled);
|
|
|
|
internal static bool IsTerminal(string stage) => TerminalStages.Contains(stage);
|
|
|
|
internal static void EnsureTransition(
|
|
string current,
|
|
string next,
|
|
JobTransitionMode mode = JobTransitionMode.Normal)
|
|
{
|
|
if (!Transitions.ContainsKey(current) || !Transitions.ContainsKey(next))
|
|
{
|
|
throw new InvalidDataException("Unsupported local job stage.");
|
|
}
|
|
if (current == next && !IsTerminal(current))
|
|
{
|
|
return;
|
|
}
|
|
if (Transitions[current].Contains(next))
|
|
{
|
|
return;
|
|
}
|
|
if (mode == JobTransitionMode.Recovery
|
|
&& !IsTerminal(current)
|
|
&& next is DownloadingInputs or UploadingOutputs)
|
|
{
|
|
return;
|
|
}
|
|
throw new InvalidDataException($"Invalid local job transition: {current} -> {next}.");
|
|
}
|
|
|
|
internal static void EnsureTerminalStatus(string status)
|
|
{
|
|
if (!TerminalStages.Contains(status))
|
|
{
|
|
throw new InvalidDataException("Unsupported local terminal status.");
|
|
}
|
|
}
|
|
|
|
private static IReadOnlySet<string> Set(params string[] values) =>
|
|
values.ToHashSet(StringComparer.Ordinal);
|
|
}
|