Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
TimedEventNode.cs
1using System;
2using System.Collections.Generic;
3using System.Threading.Tasks;
4using Waher.Content;
5using Waher.Events;
11
13{
17 public abstract class TimedEventNode : EventNode
18 {
19 private static readonly Scheduler pendingEvents = new Scheduler();
20
21 private DateTime timepoint = DateTime.MaxValue;
22 private Duration recurrence = Duration.Zero;
23
28 : base()
29 {
30 }
31
37 public abstract Task<EventTimepoint> GetEventTimepoint(EvaluationArguments Arguments);
38
42 public class EventTimepoint
43 {
48 {
49 this.Current = DateTime.Now;
50 this.Next = DateTime.MaxValue;
51 this.Duration = Duration.Zero;
52 }
53
58 public EventTimepoint(DateTime Next)
59 {
60 this.Current = DateTime.Now;
61 this.Next = Next.ToLocalTime();
62 this.Duration = Duration.Zero;
63 }
64
70 {
71 this.Current = DateTime.Now;
72 this.Next = this.Current + Duration;
73 this.Duration = Duration;
74 }
75
82 {
83 this.Current = DateTime.Now;
84 this.Next = Next.ToLocalTime();
85 this.Duration = Duration;
86 }
87
94 public EventTimepoint(DateTime Current, DateTime Next, Duration Duration)
95 {
96 this.Current = Current;
97 this.Next = Next.ToLocalTime();
98 this.Duration = Duration;
99 }
100
104 public DateTime Current { get; }
105
109 public DateTime Next { get; }
110
114 public Duration Duration { get; }
115 }
116
123 public override async Task<bool> Register(int EventIndex, EvaluationArguments Arguments, OnEvent Event)
124 {
125 EventTimepoint TP = await this.GetEventTimepoint(Arguments);
126
127 this.timepoint = TP.Next;
128 this.recurrence = Event.HasNewState ? Duration.Zero : TP.Duration;
129
130 if (this.timepoint <= DateTime.Now)
131 return true;
132
133 if (this.timepoint == DateTime.MaxValue)
134 return false;
135
136 TimepointEventHandler Handler = new TimepointEventHandler(Arguments, EventIndex, this.timepoint, this.recurrence);
137 await Database.Insert(Handler);
138
139 this.timepoint = pendingEvents.Add(this.timepoint, this.EventElapsed, Handler);
140
141 this.AddIntervalToProfiler(TP, Arguments.Profiler);
142
143 return false;
144 }
145
150 public async Task ReregisterOnStart(TimepointEventHandler Handler)
151 {
152 EventTimepoint TP = new EventTimepoint(Handler.Timepoint, Handler.Recurrence);
153
154 this.timepoint = Handler.Timepoint.ToLocalTime();
155 this.recurrence = Handler.Recurrence;
156
157 if (this.timepoint <= DateTime.Now)
158 await this.EventElapsed(Handler);
159 else if (this.timepoint < DateTime.MaxValue)
160 this.timepoint = pendingEvents.Add(this.timepoint, this.EventElapsed, Handler);
161 }
162
163 private void AddIntervalToProfiler(EventTimepoint TP, Profiler Profiler)
164 {
165 if (Profiler is null)
166 return;
167
168 string Label;
169
170 if (TP.Duration > Duration.Zero)
171 Label = TP.Duration.ToString();
172 else
173 {
174 TimeSpan TS = TP.Next - TP.Current;
175 double d = TS.TotalDays;
176 if (d > 1)
177 Label = d.ToString("F2") + " days";
178 else
179 {
180 d = TS.TotalHours;
181 if (d > 1)
182 Label = d.ToString("F2") + " h";
183 else
184 {
185 d = TS.TotalMinutes;
186 if (d > 1)
187 Label = d.ToString("F2") + " min";
188 else
189 {
190 d = TS.TotalSeconds;
191 if (d > 1)
192 Label = d.ToString("F2") + " s";
193 else
194 {
195 d = TS.TotalMilliseconds;
196 Label = d.ToString("F2") + " ms";
197 }
198 }
199 }
200 }
201 }
202
203 Profiler.Interval(TP.Current, TP.Next, Label);
204 }
205
210 public void Register(TimepointEventHandler Handler)
211 {
212 this.recurrence = Handler.Recurrence;
213 this.timepoint = pendingEvents.Add(Handler.Timepoint, this.EventElapsed, Handler);
214 }
215
221 public override Task Unregister(int EventIndex, EvaluationArguments Arguments)
222 {
223 if (this.timepoint != DateTime.MaxValue)
224 {
225 pendingEvents.Remove(this.timepoint);
226 this.timepoint = DateTime.MaxValue;
227 this.recurrence = Duration.Zero;
228 }
229
230 return Task.CompletedTask; // Do nothing by default.
231 }
232
233 private Task EventElapsed(object State)
234 {
235 return this.EventElapsed((TimepointEventHandler)State);
236 }
237
242 public async Task EventElapsed(TimepointEventHandler Handler)
243 {
244 StateMachineProcessor.CacheRecord Record = null;
245 Duration Recurrence = Handler.Recurrence;
246 bool Recurring = Recurrence > Duration.Zero;
247 DateTime From = Handler.Timepoint;
248
249 try
250 {
251 Record = await StateMachineProcessor.EventRaised(Handler, null, null);
252
253 if (Recurring && !(Record is null))
254 {
255 do
256 {
257 Handler.Timepoint += Recurrence;
258 }
259 while (Handler.Timepoint <= DateTime.Now);
260
261 this.recurrence = Recurrence;
262 this.timepoint = pendingEvents.Add(Handler.Timepoint, this.EventElapsed, Handler);
263
264 this.AddIntervalToProfiler(new EventTimepoint(From, Handler.Timepoint, Recurrence), Record.Profiler);
265
266 await Database.Update(Handler);
267 }
268 else
269 await Database.Delete(Handler);
270 }
271 catch (KeyNotFoundException)
272 {
273 // Already deleted, since state changed.
274 }
275 catch (Exception ex)
276 {
277 Log.Exception(ex);
278
279 if (!(Record.Profiler is null))
280 {
281 int NoteNr = Record.Profiler.AddNote(ex);
282 Record.Profiler?.Exception(ex, "Note" + NoteNr);
283 }
284 }
285 }
286
290 internal static void ClearPendingEvents()
291 {
292 pendingEvents.Clear();
293 }
294 }
295}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
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:1647
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:19
static async Task Update(object Object)
Updates an object in the database.
Definition: Database.cs:626
static async Task Delete(object Object)
Deletes an object in the database.
Definition: Database.cs:717
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Definition: Database.cs:95
Class that keeps track of events and timing.
Definition: Profiler.cs:67
void Interval(DateTime From, DateTime To, string Label)
Records an interval in the main thread.
Definition: Profiler.cs:291
Class that can be used to schedule events in time. It uses a timer to execute tasks at the appointed ...
Definition: Scheduler.cs:26
Contains information required for evaluating script in a state-machine.
Abstract base class for State-Machine event nodes.
Definition: EventNode.cs:10
EventTimepoint(Duration Duration)
Contains information about when a timed event elapses.
EventTimepoint(DateTime Next, Duration Duration)
Contains information about when a timed event elapses.
EventTimepoint(DateTime Next)
Contains information about when a timed event elapses.
EventTimepoint(DateTime Current, DateTime Next, Duration Duration)
Contains information about when a timed event elapses.
Abstract base class for timed State-Machine event nodes.
abstract Task< EventTimepoint > GetEventTimepoint(EvaluationArguments Arguments)
Gets the timepoint for when the event elapses.
override async Task< bool > Register(int EventIndex, EvaluationArguments Arguments, OnEvent Event)
Registers the event
TimedEventNode()
Abstract base class for timed State-Machine event nodes.
async Task EventElapsed(TimepointEventHandler Handler)
Method called when event elapses.
async Task ReregisterOnStart(TimepointEventHandler Handler)
Re-registers the event on module start.
override Task Unregister(int EventIndex, EvaluationArguments Arguments)
Registers the event
void Register(TimepointEventHandler Handler)
Registers an existing event handler.
Action executed when entering a state.
Definition: OnEvent.cs:17
Represents a duration value, as defined by the xsd:duration data type: http://www....
Definition: Duration.cs:13
static readonly Duration Zero
Zero value
Definition: Duration.cs:532