-
Notifications
You must be signed in to change notification settings - Fork 1
/
JobWorker.cs
104 lines (90 loc) · 3.87 KB
/
JobWorker.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace DotStd
{
/// <summary>
/// Declare this as some job/task i want to execute from external source. checked in Compile.
/// Attach some attribute to the job/task so i can know more about it. Must accompany IJobWorker.
/// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/accessing-attributes-by-using-reflection
/// e.g. [Job("MyJobName")]
/// </summary>
public class JobAttribute : Attribute
{
public string Name; // primary name
public List<string>? Aliases; // Other attribute tags.
public JobAttribute(string name)
{
Name = name;
}
}
/// <summary>
/// How is the code for this job executed ? What isolation level?
/// </summary>
public enum JobIsolationId
{
Await, // Await the async entry. (default)
NoAwait, // run directly inline. No thread. No await.
Thread, // Create a thread and call the entry point assembly in my process space.
ProcAssembly, // Use a process isolation wrapper on the assembly. (thread assumed)
Process, // Load a new process with arguments. EXE
}
/// <summary>
/// Persist Last/Current run definition/state of a job. Produce a JobWorker to run.
/// keep this in persistent storage.
/// leave scheduling definition out. when should this run again?
/// </summary>
public class JobState
{
public int Id { get; set; } // int JobId, PK in some persistent storage.
public int RunningAppId { get; set; } = ValidState.kInvalidId; // What AppId is running this now? 0 = not running. else its currently running. (as far as we know on AppProcUtil.Id);
public int RunningStatus { get; private set; } // estimated percent complete. 0-1000
// NOTE: LastRun can be set into the future to delay start.
public DateTime? LastRun { get; set; } // last UTC start time when we tried to run this. or retry this. It might have failed or succeeded. Might not have been the official scheduled time it was supposed to run.
public string? LastResult { get; set; } // what happened at/after LastRun? null = never run, "" = success or error description summary.
public DateTime? LastSuccess { get; set; } // The last UTC start time we ran this and it succeeded. LastResult == ""
public bool IsRunning
{
get
{
// Never run the same job reentrant. always wait for the first to finish or figure out why its failing.
return ValidState.IsValidId(RunningAppId);
}
}
public JobState()
{ }
public JobState(int id)
{
Id = id;
}
public virtual void SetRunningStatus(int statusPercent)
{
// override this to push the update or persist in DB.
RunningStatus = statusPercent;
}
}
/// <summary>
/// abstraction for some job/task to execute. exposed by assembly.
/// Assume this is paired with JobAttribute
/// Code must expose this interface so i can call it.
/// Might Compile code from sources ? or just load some external assembly
/// </summary>
public interface IJobWorker
{
JobState State { get; set; } // Link back to my job state/definition. is it running ? last status etc.
Task ExecuteAsync(string? args); // Run it now.
}
/// <summary>
/// Implement IJobWorker
/// Can be used with JobTracker ?
/// </summary>
public abstract class JobWorker : IJobWorker
{
public JobState State { get; set; }
public abstract Task ExecuteAsync(string? args);
public JobWorker(JobState state)
{
State = state;
}
}
}