Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ScheduledAction.cs
1using System;
3using System.Threading.Tasks;
4using Waher.Events;
11using Waher.Script;
13
15{
19 [CollectionName("ScheduledActions")]
20 [Index("Timepoint", "StateMachineId", "Action")]
21 [Index("StateMachineId", "Timepoint", "Action")]
22 public class ScheduledAction
23 {
28 : base()
29 {
30 }
31
35 [ObjectId]
36 public string ObjectId { get; set; }
37
42
46 public DateTime Timepoint { get; set; }
47
51 public string Action { get; set; }
52
56 public string BeforeActionScript { get; set; }
57
66 internal static async Task Schedule(CaseInsensitiveString StateMachineId,
67 DateTime Timepoint, string Action, string BeforeActionScript)
68 {
69 ScheduledAction Result = new ScheduledAction()
70 {
73 Action = Action,
75 };
76
77 await Database.Insert(Result);
78
79 if (nextAction is null || Result.Timepoint < nextAction.Timepoint)
80 {
81 if (nextActionTimer != DateTime.MinValue)
82 {
83 Gateway.CancelScheduledEvent(nextActionTimer);
84 nextActionTimer = DateTime.MinValue;
85 }
86
87 nextAction = Result;
88 nextActionTimer = Gateway.ScheduleEvent(ExecutePendingActions, nextAction.Timepoint, null);
89 }
90 }
91
96 private static async Task<IEnumerable<ScheduledAction>> GetElapsedActions(int MaxCount)
97 {
98 return await Database.Find<ScheduledAction>(0, MaxCount,
99 new FilterFieldLesserOrEqualTo("Timepoint", DateTime.UtcNow));
100 }
101
106 internal static async Task DeleteScheduledActions(CaseInsensitiveString StateMachineId)
107 {
109 new FilterFieldLesserOrEqualTo("StateMachineId", StateMachineId));
110 }
111
112 internal static async Task ScheduleNext()
113 {
114 try
115 {
116 if (nextActionTimer != DateTime.MinValue)
117 {
118 Gateway.CancelScheduledEvent(nextActionTimer);
119 nextActionTimer = DateTime.MinValue;
120 }
121
122 nextAction = await Database.FindFirstIgnoreRest<ScheduledAction>("Timepoint");
123 if (nextAction is null)
124 return;
125
126 nextActionTimer = Gateway.ScheduleEvent(ExecutePendingActions, nextAction.Timepoint, null);
127 }
128 catch (Exception ex)
129 {
130 Log.Exception(ex);
131 }
132 }
133
134 internal static async Task ExecutePendingActions(object _)
135 {
136 nextActionTimer = DateTime.MinValue;
137
138 try
139 {
140 const int N = 1000;
141 int n;
142
143 do
144 {
145 IEnumerable<ScheduledAction> Actions = await GetElapsedActions(N);
146 n = 0;
147
148 foreach (ScheduledAction Action in Actions)
149 {
150 n++;
151
152 try
153 {
154 using Semaphore Semaphore = await Semaphores.BeginWrite("machine:" + Action.StateMachineId.Value);
155 StateMachineProcessor.CacheRecord Rec = await StateMachineProcessor.GetStateMachine(Action.StateMachineId, true);
156 StateMachine Machine = Rec?.Machine;
157
158 if (!(Machine is null))
159 {
160 if (!Machine.TryGetAction(Action.Action, out Action Action2))
161 throw new StateMachineException(Rec.Machine, "Action '" + Action.Action + "' not found in state machine.");
162
163 Variables Variables = Rec.CurrentState.GetVariables(Machine);
164 EvaluationArguments Arguments = new EvaluationArguments(Variables,
165 Machine, null, Rec.CurrentState, Rec.Legal, Rec.EDaler,
166 Rec.Profiler);
167
168 ProfilerThread Thread = Arguments.Profiler?.GetThread(Action.Action, ProfilerThreadType.Binary);
169 Thread?.High();
170
171 try
172 {
173 if (!string.IsNullOrEmpty(Action.BeforeActionScript))
174 await Expression.EvalAsync(Action.BeforeActionScript, Variables);
175
176 await Action2.Execute(Arguments);
177 }
178 finally
179 {
180 Thread?.Low();
181 }
182 }
183 }
184 catch (Exception ex)
185 {
186 Log.Exception(ex);
187 }
188 finally
189 {
190 await Database.Delete(Action);
191 }
192 }
193 }
194 while (n == N);
195 }
196 catch (Exception ex)
197 {
198 Log.Exception(ex);
199 }
200 finally
201 {
202 await ScheduleNext();
203 }
204 }
205
206 private static ScheduledAction nextAction = null;
207 private static DateTime nextActionTimer = DateTime.MinValue;
208 }
209}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:147
static DateTime ScheduleEvent(Action< object > Callback, DateTime When, object State)
Schedules a one-time event.
Definition: Gateway.cs:4253
static bool CancelScheduledEvent(DateTime When)
Cancels a scheduled event.
Definition: Gateway.cs:4275
Represents a case-insensitive string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
static async Task Delete(object Object)
Deletes an object in the database.
Definition: Database.cs:1291
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
Definition: Database.cs:238
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Definition: Database.cs:97
This filter selects objects that have a named field lesser or equal to a given value.
ProfilerThread GetThread(string Name, ProfilerThreadType Type)
Gets a profiler thread. If none is available, a new is created.
Definition: Profiler.cs:145
Class that keeps track of events and timing for one thread.
void Low()
Sets the (binary) state to "low".
void High()
Sets the (binary) state to "high".
Profiler Profiler
Profiler reference.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Definition: Semaphore.cs:19
Static class of application-wide semaphores that can be used to order access to editable objects.
Definition: Semaphores.cs:17
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Definition: Semaphores.cs:91
Class managing a script expression.
Definition: Expression.cs:41
static Task< object > EvalAsync(string Script)
Evaluates script, in string format.
Definition: Expression.cs:5946
Collection of variables.
Definition: Variables.cs:25
string BeforeActionScript
Any script that needs to be executed before calling the action.
Class representing a state machine.
Definition: StateMachine.cs:43
bool TryGetAction(string Id, out Model.Actions.Action Action)
Tries to get an action.
Definition: ImplTypes.g.cs:58
ProfilerThreadType
Type of profiler thread.