-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathProcess.cs
148 lines (119 loc) · 5.12 KB
/
Process.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using NFX;
using NFX.DataAccess.CRUD;
using NFX.Environment;
using NFX.Security;
namespace Agni.Workers
{
/// <summary>
/// Represents a context for units of work (like Todos) executing in the distributed system.
/// Processes are controlled via AgniSystem.ProcessManager implementation
/// </summary>
[Serializable]
public abstract class Process : AmorphousTypedRow
{
/// <summary>
/// Factory method that creates new Process based on provided PID
/// </summary>
public static TProcess MakeNew<TProcess>(PID pid) where TProcess : Process, new() { return makeDefault(new TProcess(), pid); }
/// <summary>
/// Factory method that creates new Process based on provided Type, PID and Configuration
/// </summary>
public static Process MakeNew(Type type, PID pid, IConfigSectionNode args) { return makeDefault(FactoryUtils.MakeAndConfigure<Process>(args, type), pid); }
private static TProcess makeDefault<TProcess>(TProcess process, PID pid) where TProcess : Process
{
var attr = GuidTypeAttribute.GetGuidTypeAttribute<Process, ProcessAttribute>(process.GetType());
var descriptor = new ProcessDescriptor(
pid,
attr.Description,
App.TimeSource.UTCNow,
"{0}@{1}@{2}".Args(App.CurrentCallUser.Name, App.Name, AgniSystem.HostName));
process.m_SysDescriptor = descriptor;
return process;
}
protected Process() { }
private ProcessDescriptor m_SysDescriptor;
/// <summary>
/// Infrustructure method, developers do not call
/// </summary>
public void ____Deserialize(ProcessDescriptor descriptor)
{ m_SysDescriptor = descriptor; }
/// <summary>
/// Globally-unique ID of the TODO
/// </summary>
public PID SysPID { get { return m_SysDescriptor.PID; } }
/// <summary>
/// When was created
/// </summary>
public ProcessDescriptor SysDescriptor { get { return m_SysDescriptor; } }
public override string ToString() { return "{0}('{1}')".Args(GetType().FullName, SysPID); }
public override int GetHashCode() { return m_SysDescriptor.GetHashCode(); }
public override bool Equals(Row other)
{
var otherProcess = other as Process;
if (otherProcess==null) return false;
return this.m_SysDescriptor.PID.ID == otherProcess.m_SysDescriptor.PID.ID;
}
/// <summary>
/// Executes merge operation on the existing process and another instance which tries to get spawned.
/// This method MUST execute be VERY FAST and only contain merge logic, do not make externall IO calls -
/// all business data must already be contained in the original and another instance
/// </summary>
protected internal abstract void Merge(IProcessHost host, DateTime utcNow, Process another);
protected internal virtual ResultSignal Accept(IProcessHost host, Signal signal)
{
if (signal is FinalizeSignal)
{
host.Finalize(this);
return OkSignal.Make(this);
}
if (signal is TerminateSignal)
{
var finish = signal as TerminateSignal;
UpdateStatus(host, ProcessStatus.Terminated, "Treminated!!!!", App.TimeSource.UTCNow, finish.SysAbout);
host.Update(this, true);
return OkSignal.Make(this);
}
// a pochemy net try/cath i ERROR signal???? ili eto v drugom meste
var result = DoAccept(host, signal); //Do Accept razve ne doljen byt POSLE systemnix signalov??
if (result != null) return result;
// a gde ostalnie signali? Terminate etc...?
if (signal is FinishSignal)
{
var finish = signal as FinishSignal;
UpdateStatus(host, ProcessStatus.Finished, finish.Description, App.TimeSource.UTCNow, finish.SysAbout);
host.Update(this, true);
return OkSignal.Make(this);
}
if (signal is CancelSignal)
{
var finish = signal as CancelSignal;
UpdateStatus(host, ProcessStatus.Canceled, "Canceled!!!", App.TimeSource.UTCNow, finish.SysAbout);
host.Update(this, true);
return OkSignal.Make(this);
}
return UnknownSignal.Make(this, signal);
}
protected abstract ResultSignal DoAccept(IProcessHost host, Signal signal);
protected void UpdateStatus(IProcessHost host, ProcessStatus status, string description, DateTime timestamp, string about)
{
m_SysDescriptor = new ProcessDescriptor(SysDescriptor, status, description, timestamp, about);
}
public void ValidateAndPrepareForSpawn(string targetName)
{
DoPrepareForEnqueuePreValidate(targetName);
var ve = this.Validate(targetName);
if (ve != null)
throw new WorkersException(StringConsts.ARGUMENT_ERROR + "Process.ValidateAndPrepareForEnqueue(todo).validate: " + ve.ToMessageWithType(), ve);
DoPrepareForEnqueuePostValidate(targetName);
}
public override Exception Validate(string targetName)
{
var ve = base.Validate(targetName);
if (ve != null) return ve;
return null;
}
protected virtual void DoPrepareForEnqueuePreValidate(string targetName) { }
protected virtual void DoPrepareForEnqueuePostValidate(string targetName) { }
}
}