示例#1
0
 public override async Task IfEffect(StateMachineEvent evt, Command parameter)
 {
     var command = (Information)parameter;
     await _user.UpdateInformation(command);
     var hubInformation = CreateHubInformation();
     await Sender.SendMessage(hubInformation.ToMessage());
 }
示例#2
0
 public override async Task IfEffect(StateMachineEvent evt, Command parameter)
 {
     var supportsMessage = new Supports(InformationMessageHeader, new HashSet<string>(Features), null);
     await Sender.SendMessage(supportsMessage.ToMessage());
     var sidMessage = new Sid(new InformationMessageHeader(), User.Sid);
     await Sender.SendMessage(sidMessage.ToMessage());
 }
示例#3
0
 public void StateMachineEvent(StateMachineEvent stateMachineEvent)
 {
     if (onStateMachineEvent != null)
     {
         onStateMachineEvent.OnNext(stateMachineEvent);
     }
 }
示例#4
0
        /// <summary>
        /// Declares a data event on a property of the state machine, and initializes the property
        /// </summary>
        /// <param name="propertyExpression">The property</param>
        /// <param name="eventPropertyExpression">The event property on the property</param>
        protected virtual void Event <TProperty, T>(Expression <Func <TProperty> > propertyExpression,
                                                    Expression <Func <TProperty, Event <T> > > eventPropertyExpression)
            where TProperty : class
        {
            PropertyInfo property      = propertyExpression.GetPropertyInfo();
            var          propertyValue = property.GetValue(this, null) as TProperty;

            if (propertyValue == null)
            {
                throw new ArgumentException("The property is not initialized: " + property.Name, nameof(propertyExpression));
            }

            PropertyInfo eventProperty = eventPropertyExpression.GetPropertyInfo();

            string name = $"{property.Name}.{eventProperty.Name}";

            var @event = new DataEvent <T>(name);

            if (eventProperty.CanWrite)
            {
                eventProperty.SetValue(propertyValue, @event);
            }
            else
            {
                var objectProperty = propertyValue.GetType().GetProperty(eventProperty.Name, typeof(Event <T>));
                if (objectProperty == null || !objectProperty.CanWrite)
                {
                    throw new ArgumentException($"The event property is not writable: {eventProperty.Name}");
                }

                objectProperty.SetValue(propertyValue, @event);
            }

            _eventCache[name] = new StateMachineEvent <TInstance>(@event, false);
        }
示例#5
0
        public override async Task<bool> Guard(StateMachineEvent evt, Command parameter)
        {
            var command = (Information)parameter;
            if (!command.Pid.IsDefined)
            {
                CreateRequiredFieldIsMissing("PD");
                return false;
            }

            if (!command.Cid.IsDefined)
            {
                CreateRequiredFieldIsMissing("ID");
                return false;
            }

            var cid = AdcBase32Encoder.Decode(command.Cid.Value);
            var pid = AdcBase32Encoder.Decode(command.Pid.Value);
            var hash = new TigerHash().ComputeHash(pid);
            if (!hash.SequenceEqual(cid))
            {
                CreateInvalidPid();
                return false;
            }

            if (!command.IpAddressV4.IsDefined && !command.IpAddressV6.IsDefined)
            {
                CreateRequiredFieldIsMissing("I4");
                return false;
            }

            if (command.IpAddressV4.IsDefined && command.IpAddressV4.Value != _user.ClientIPv4.ToString())
            {
                CreateInvalidIPv4(_user.ClientIPv4.ToString());
                return false;
            }

            if (command.IpAddressV6.IsDefined && command.IpAddressV6.Value != _user.ClientIPv6.ToString())
            {
                CreateInvalidIPv6(_user.ClientIPv6.ToString());
                return false;
            }

            if (!command.Nickname.IsDefined || string.IsNullOrWhiteSpace(command.Nickname.Value))
            {
                CreateInvalidNick();
                return false;
            }

            var catalog = ServiceProxy.Create<ICatalog>(new Uri("fabric:/FabricAdcHub.ServiceFabric/Catalog"));
            if (!await catalog.ReserveNick(_user.Sid, command.Nickname.Value))
            {
                CreateNonUniqueNick();
                return false;
            }

            return true;
        }
示例#6
0
 /// <summary>
 /// Raise an event of type command
 /// </summary>
 /// <param name="eventName"></param>
 /// <param name="eventInfo"></param>
 private void RaiseStateMachineSystemCommand(
     string eventName, string eventInfo)
 {
     // Raise event only, if subscriber exist.
     // Otherwise an exception occurs
     StateMachineEvent?.Invoke(this, new StateMachineEventArgs(
                                   eventName, eventInfo, StateMachineEventType.Command,
                                   "State machine"));
 }
示例#7
0
        void DeclareDataEvent <T>(PropertyInfo property)
        {
            string name = property.Name;

            var @event = new DataEvent <T>(name);

            property.SetValue(this, @event);

            _eventCache[name] = new StateMachineEvent <TInstance>(@event, false);
        }
        public override async Task Effect(StateMachineEvent evt, Command parameter)
        {
            if (parameter != null)
            {
                var status = new Status(new InformationMessageHeader(), Status.ErrorSeverity.Fatal, Status.ErrorCode.InvalidState, $"Command {parameter.FourCc()} is invalid or not available in PROTOCOL state.");
                status.OffendingCommandOrMissingFeature.Value = parameter.FourCc();
                await Sender.SendMessage(status.ToMessage());
            }

            await User.Close();
        }
示例#9
0
        /// <summary>
        /// Raises an event of type command
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="eventInfo"></param>
        private void RaiseStateMachineSystemCommand(string eventName, string eventInfo)
        {
            if (this.StateMachineEvent == null)
            {
                return;
            }

            StateMachineEvent.Invoke(
                this,
                new StateMachineEventArgs(eventName, eventInfo, "State machine", StateMachineEventType.Command));
        }
        protected void Event <T>(Expression <Func <Event <T> > > propertyExpression)
        {
            PropertyInfo property = propertyExpression.GetPropertyInfo();

            string name = property.Name;

            var @event = new DataEvent <T>(name);

            property.SetValue(this, @event);

            _eventCache[name] = new StateMachineEvent <TInstance>(@event);
        }
        public bool Inspect <T, V>(DataEvent <T, V> eevent)
            where T : StateMachine <T>
        {
            var target = eevent.CastAs <DataEvent <TStateMachine, V> >();

            Func <StateMachineEvent <TStateMachine> > factory = () => new StateMachineEvent <TStateMachine, V>(target, typeof(V));

            StateMachineEvent <TStateMachine> sagaEvent = _events.Retrieve(target, factory);

            sagaEvent.AddState(_currentState);

            return(true);
        }
        /// <summary>
        /// Adds a composite event to the state machine. A composite event is triggered when all
        /// off the required events have been raised. Note that required events cannot be in the initial
        /// state since it would cause extra instances of the state machine to be created
        /// </summary>
        /// <param name="propertyExpression">The composite event</param>
        /// <param name="trackingPropertyExpression">The property in the instance used to track the state of the composite event</param>
        /// <param name="events">The events that must be raised before the composite event is raised</param>
        protected void Event(Expression <Func <Event> > propertyExpression,
                             Expression <Func <TInstance, CompositeEventStatus> > trackingPropertyExpression,
                             params Event[] events)
        {
            if (events == null)
            {
                throw new ArgumentNullException("events");
            }
            if (events.Length > 31)
            {
                throw new ArgumentException("No more than 31 events can be combined into a single event");
            }
            if (events.Length == 0)
            {
                throw new ArgumentException("At least one event must be specified for a composite event");
            }
            if (events.Any(x => x == null))
            {
                throw new ArgumentException("One or more events specified has not yet been initialized");
            }

            PropertyInfo eventProperty        = propertyExpression.GetPropertyInfo();
            PropertyInfo trackingPropertyInfo = trackingPropertyExpression.GetPropertyInfo();

            string name = eventProperty.Name;

            var @event = new SimpleEvent(name);

            eventProperty.SetValue(this, @event);

            _eventCache[name] = new StateMachineEvent <TInstance>(@event);

            var complete = new CompositeEventStatus(Enumerable.Range(0, events.Length)
                                                    .Aggregate(0, (current, x) => current | (1 << x)));

            for (int i = 0; i < events.Length; i++)
            {
                int flag = 1 << i;

                var activity = new CompositeEventActivity <TInstance>(trackingPropertyInfo, flag, complete,
                                                                      (consumer, instance) => ((StateMachine <TInstance>) this).RaiseEvent(consumer, instance, @event));

                foreach (var state in _stateCache.Where(x => !Equals(x, Initial)))
                {
                    During(state,
                           When(events[i])
                           .Then(() => activity));
                }
            }
        }
示例#13
0
        public override Task<bool> Guard(StateMachineEvent evt, Command parameter)
        {
            var command = (Supports)parameter;
            for (var index = 0; index != Features.Length; index++)
            {
                var feature = Features[index];
                if (!command.AddFeatures.Value.Contains(feature))
                {
                    CreateRequiredFeatureIsMissing(feature);
                    return Task.FromResult(false);
                }
            }

            return Task.FromResult(true);
        }
示例#14
0
        void CompositeEvent(Expression <Func <Event> > propertyExpression, CompositeEventStatusAccessor <TInstance> accessor,
                            CompositeEventOptions options, Event[] events)
        {
            if (events == null)
            {
                throw new ArgumentNullException(nameof(events));
            }
            if (events.Length > 31)
            {
                throw new ArgumentException("No more than 31 events can be combined into a single event");
            }
            if (events.Length == 0)
            {
                throw new ArgumentException("At least one event must be specified for a composite event");
            }
            if (events.Any(x => x == null))
            {
                throw new ArgumentException("One or more events specified has not yet been initialized");
            }

            PropertyInfo eventProperty = propertyExpression.GetPropertyInfo();

            string name = eventProperty.Name;

            var @event = new TriggerEvent(name);

            eventProperty.SetValue(this, @event);

            _eventCache[name] = new StateMachineEvent <TInstance>(@event, false);

            var complete = new CompositeEventStatus(Enumerable.Range(0, events.Length)
                                                    .Aggregate(0, (current, x) => current | (1 << x)));

            for (int i = 0; i < events.Length; i++)
            {
                int flag = 1 << i;

                var activity = new CompositeEventActivity <TInstance>(accessor, flag, complete, @event);

                Func <State <TInstance>, bool> filter = x => options.HasFlag(CompositeEventOptions.IncludeInitial) || !Equals(x, Initial);
                foreach (var state in _stateCache.Values.Where(filter))
                {
                    During(state,
                           When(events[i])
                           .Execute(x => activity));
                }
            }
        }
        public override async Task Effect(StateMachineEvent evt, Command parameter)
        {
            if (parameter != null)
            {
                var status = new Status(new InformationMessageHeader(), Status.ErrorSeverity.Fatal, Status.ErrorCode.InvalidState, $"Command {parameter.FourCc()} is invalid or not available in IDENTIFY state.");
                status.OffendingCommandOrMissingFeature.Value = parameter.FourCc();
                await Sender.SendMessage(status.ToMessage());
            }

            if (evt.InternalEvent != InternalEvent.DisconnectOccured)
            {
                var quit = new Quit(new InformationMessageHeader(), User.Sid);
                await Sender.SendMessage(quit.ToMessage());
            }

            await User.Close();
        }
示例#16
0
        public override async Task Effect(StateMachineEvent evt, Command parameter)
        {
            if (evt.InternalEvent == InternalEvent.ConnectionTimedOut)
            {
                // do nothing
                return;
            }

            if (parameter.Type == CommandType.Information)
            {
                await User.UpdateInformation((Information)parameter);
            }
            else if (parameter.Type == CommandType.Supports)
            {
                await User.UpdateInformation((Supports)parameter);
            }

            if (parameter.Header is BroadcastMessageHeader)
            {
                await BroadcastCommand(parameter);
                return;
            }

            if (parameter.Header is DirectMessageHeader)
            {
                await DirectCommand(parameter);
                return;
            }

            if (parameter.Header is EchoMessageHeader)
            {
                await EchoedDirectCommand(parameter);
                return;
            }

            if (parameter.Header is FeatureBroadcastMessageHeader)
            {
                await FeatureBroadcastCommand(parameter);
            }
        }
 protected void SendStateMachineEvent(StateMachineEvent @event)
 {
     stateMachineEventSubject.OnNext(@event);
 }
示例#18
0
 public override Task IfEffect(StateMachineEvent evt, Command parameter)
 {
     return Task.CompletedTask;
 }
示例#19
0
 public override Task<bool> Guard(StateMachineEvent evt, Command parameter)
 {
     var status = (Status)parameter;
     return Task.FromResult(status.Severity == Status.ErrorSeverity.Fatal);
 }
示例#20
0
 public override Task ElseEffect(StateMachineEvent evt, Command parameter)
 {
     return Sender.SendMessage(_errorCommand.ToMessage());
 }
示例#21
0
 public override async Task ElseEffect(StateMachineEvent evt, Command parameter)
 {
     var quit = new Quit(new InformationMessageHeader(), _user.Sid);
     await Sender.SendMessage(quit.ToMessage());
     await _user.Close();
 }
 public override async Task Effect(StateMachineEvent evt, Command parameter)
 {
     await User.Close();
 }
示例#23
0
 private bool isNotFinished(StateMachineEvent next)
 => !(next is StateMachineDeadEnd || next is StateMachineError);
示例#24
0
 private void RaiseStateMachineSystemCommand(string eventName, string eventInfo) =>
 StateMachineEvent?.Invoke(this, new StateMachineEventArgs(eventName, eventInfo, StateMachineEventType.Command, "StateMachine"));