public void Initialize(Tick senderTick, Tick ackTick, SequenceId ackEventId, IEnumerable <Event> events) { SenderTick = senderTick; AckTick = ackTick; AckEventId = ackEventId; PendingEvents.AddRange(events); EventsWritten = 0; }
public virtual void Reset() { SenderTick = Tick.INVALID; AckTick = Tick.INVALID; AckEventId = SequenceId.INVALID; PendingEvents.Clear(); Events.Clear(); EventsWritten = 0; }
public void AddBillingAddress(Address address) { if (address is null) { throw new ArgumentNullException(nameof(address)); } PendingEvents.Enqueue(new BillingAddressWasAdded(AggregatedId, new { BillingAddress = address })); BillingAddress = address; }
public Customer Create(Document document, Name name, Address address) { AggregatedId = Guid.NewGuid().ToString(); Document = document; Name = name; BillingAddress = address; PendingEvents.Enqueue(new CustomerWasCreated(AggregatedId, new { Document, Name, BillingAddress })); return(this); }
///// <summary> ///// RunStateMachine is the heart of the engine that runs the finite state machine. It is executed in a ///// separate thread that is started when you <see cref="Start(FiniteState)"/> the state machine. ///// All events that have been queued by <see cref="RaiseEvent(FiniteStateEvent)"/>, are processed here. ///// The method runs in an infinite loop that only exits when <see cref="Stop()"/> is called. ///// When it has processed all of the events in the queue, it will sleep until it is pulsed ///// by either <see cref="RaiseEvent(FiniteStateEvent)"/> or <see cref="Stop()"/> ///// </summary> //public void RunStateMachine() //{ // string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; // if (log.IsDebugEnabled) // log.Debug($"{methodName}: enter"); // // try // { // while (!stopRequested) // { // HandlePendingEvents(); // if (!stopRequested) // { // lock (locker) // { // if (log.IsDebugEnabled) // log.Debug($"{methodName}: Putting to sleep the state machine thread."); // // Monitor.Wait(locker); // Nothing to do, so go to sleep until we are pulsed by RaiseEvent or Stop // // if (log.IsDebugEnabled) // log.Debug($"{methodName}: Just woke up :-)"); // } // } // } // } // catch(Exception e) // { // log.Error($"{e.Message}"); // //OnExceptionAction?.Invoke(e); // } // finally // { // if (log.IsDebugEnabled) // log.Debug($"{methodName}: exit"); // } //} // /// <summary> /// This function is called during the first call to RaiseEvent() in Start() because at that point, /// we are not handling a previous event. From then on, every event handler raises an event. /// </summary> public void HandlePendingEvents() { string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; if (log.IsDebugEnabled) { log.Debug($"{methodName}: enter"); } try { while (PendingEvents.Count > 0) { if (log.IsDebugEnabled) { log.Debug($"{methodName}: PendingEvents.Count={PendingEvents.Count}"); } FiniteStateEvent ev = null; lock (PendingEvents) { ev = PendingEvents.Dequeue(); } if (CurrentState.Transitions.TryGetValue(ev.Name, out FiniteStateTransition transition)) { if (log.IsDebugEnabled) { log.Debug($"{methodName}: transition {CurrentState.Name} -> {ev.Name} ->{transition.ToState.Name}"); } SetCurrentState(transition.ToState); if (log.IsDebugEnabled) { log.Debug($"{methodName}: before invoke, PendingEvents.Count={PendingEvents.Count}"); } CurrentState.OnEnterAction?.Invoke(); if (log.IsDebugEnabled) { log.Debug($"{methodName}: after invoke, PendingEvents.Count={PendingEvents.Count}"); } } else { throw new ArgumentException($"Failed to find a transition for event '{ev.Name}' from state '{CurrentState.Name}'."); } } } finally { if (log.IsDebugEnabled) { log.Debug($"{methodName}: exit"); } } }
public void UpdateShippingStatus(ShippingConfirmation shippingConfirmation) { if (shippingConfirmation.Status == ShippingStatus.Success) { Status = Status.Arranged; PendingEvents.Add(new ShippingArranged { OrderId = OrderId }); } else { Status = Status.Postponed; } }
public void ConfirmEmail(Email email) { var exist = Emails.Any(item => item.Equals(email)); if (exist) { Emails.Remove(email); Emails.Add(email); } else { throw new InvalidOperationException("Email not exist"); } PendingEvents.Enqueue(new EmailWasConfirmed(AggregatedId, new { Email = email })); }
/// <summary> /// Raises an event in the finite state machine. /// </summary> /// <param name="e">The instance of the event to raise</param> public void RaiseEvent(FiniteStateEvent e) { string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; if (log.IsDebugEnabled) { log.Debug($"{methodName}: enter"); } try { if (log.IsInfoEnabled) { log.Info($"{methodName}: [{e.Name}]"); } // // Use a queue so that event handlers can raise events. // lock (PendingEvents) { PendingEvents.Enqueue(e); if (log.IsDebugEnabled) { log.Debug($"{methodName}: handlingEvent = {handlingEvent}"); } if (handlingEvent) { return; } handlingEvent = true; } HandlePendingEvents(); // eliminate race for the flag by using the same lock object lock (PendingEvents) { handlingEvent = false; } } finally { if (log.IsDebugEnabled) { log.Debug($"{methodName}: exit"); } } }
public void SimulateTime(double time) { double endTime = CurrentTime + time; while (PendingEvents.HasEvent && PendingEvents.FirstEventTime < endTime) { if (PendingEvents.FirstEventTime > CurrentTime) { CurrentTime = PendingEvents.FirstEventTime; } var e = PendingEvents.NextEvent(); ISimulatedDevice device = e.Origin as ISimulatedDevice; e.Origin.PastEvents.Append(e); switch (e.Type) { case EventType.NodePowerOn: device.DeviceStart(); break; case EventType.NodePowerOff: // Future feature - nodes can be powered off and leave the network. throw new NotImplementedException(); break; case EventType.PacketComplete: var pkt = e.EventContext as WirelessPacketTransmission; e.Origin.InFlightPackets.Remove(pkt); if (pkt.ReceiveSuccess) { device.ReceivePacket(pkt.Packet.PacketContents); } break; case EventType.TimerComplete: e.Origin.TimerAction?.Invoke(); break; default: throw new NotSupportedException("Unsupported event type in queue"); } } CurrentTime = endTime; }
protected void Enqueue(Event @event) { Version++; PendingEvents.Enqueue(@event); }
protected void Dequeue() { PendingEvents.Dequeue(); }