/// <summary> /// Directly inject messages into actor receive behavior. Any exceptions /// thrown will be available to you, while still being able to use /// become/unbecome. /// </summary> /// <param name="message">The message.</param> /// <param name="sender">The sender.</param> public void Receive(object message, IActorRef sender = null) { var cell = Cell; sender = sender.IsNobody() ? cell.System.DeadLetters : sender; var envelope = new Envelope { Message = message, Sender = sender }; cell.UseThreadContext(() => cell.ReceiveMessageForTest(envelope)); }
protected override void TellInternal(object message, IActorRef sender) { if(message == null) throw new InvalidMessageException("Message is null"); var d = message as DeadLetter; if (d != null) SpecialHandle(d.Message, d.Sender); else if (!SpecialHandle(message, sender)) { _eventStream.Publish(new DeadLetter(message, sender.IsNobody() ? _provider.DeadLetters : sender, this)); } }
protected virtual void SendUserMessage(object message, IActorRef sender) { if(message == null) throw new InvalidMessageException(); var deadLetter = message as DeadLetter; if(deadLetter != null) HandleDeadLetter(deadLetter); else { var wasHandled = SpecialHandle(message, sender); if(!wasHandled) { _eventStream.Publish(new DeadLetter(message, sender.IsNobody() ? _provider.DeadLetters : sender, this)); } } }
protected virtual bool SpecialHandle(object message, IActorRef sender) { var watch = message as Watch; if (watch != null) { if (watch.Watchee.Equals(this) && !watch.Watcher.Equals(this)) { watch.Watcher.SendSystemMessage(new DeathWatchNotification(watch.Watchee, existenceConfirmed: false, addressTerminated: false)); } return true; } if (message is Unwatch) return true; //Just ignore var identify = message as Identify; if (identify != null) { sender.Tell(new ActorIdentity(identify.MessageId, null)); return true; } var actorSelectionMessage = message as ActorSelectionMessage; if (actorSelectionMessage != null) { var selectionIdentify = actorSelectionMessage.Message as Identify; if (selectionIdentify != null) { if (!actorSelectionMessage.WildCardFanOut) sender.Tell(new ActorIdentity(selectionIdentify.MessageId, null)); } else { _eventStream.Publish(new DeadLetter(actorSelectionMessage.Message, sender.IsNobody() ? _provider.DeadLetters : sender, this)); } return true; } var deadLetterSuppression = message as IDeadLetterSuppression; if (deadLetterSuppression != null) { _eventStream.Publish(new SuppressedDeadLetter(deadLetterSuppression, sender.IsNobody() ? _provider.DeadLetters : sender, this)); return true; } return false; }
private void CheckChange() { if (_PremiseChangeStateActorRef.IsNobody()) { return; } if (attributeRemoteControlState != oldAttributeRemoteControlState) { if (attributeRemoteControlState == (int)RemoteControlState.ButtonPress) { _PremiseChangeStateActorRef.Tell(PremiseAction.MakeTrue); } else if (attributeRemoteControlState == (int)RemoteControlState.Off) { _PremiseChangeStateActorRef.Tell(PremiseAction.MakeFalse); } oldAttributeRemoteControlState = attributeRemoteControlState; } }
protected virtual void SendUserMessage(object message, IActorRef sender) { if (message == null) { throw new InvalidMessageException(); } var deadLetter = message as DeadLetter; if (deadLetter != null) { HandleDeadLetter(deadLetter); } else { var wasHandled = SpecialHandle(message, sender); if (!wasHandled) { _eventStream.Publish(new DeadLetter(message, sender.IsNobody() ? _provider.DeadLetters : sender, this)); } } }
protected override void OnReceive(object message) { if (message is ActorReference) { var temp = message as ActorReference; if (temp.ActorRefID == ActorRefType.FBEGateRef) { SetFBEGateActorRef(temp.Ref); } if (temp.ActorRefID == ActorRefType.FBERemoteControlRef) { SetFBERemoteControl(temp.Ref); } Sender.Tell(true); } else { switch (message) { case ConditionAction.SendClock: if (!_FBEGateActorRef.IsNobody() && isGateOpen == false) { _FBEGateActorRef.Tell(GateAction.Open); } break; case ConditionAction.SendTrue: isGateOpen = true; if (!_FBERemoteControlRef.IsNobody()) { _FBERemoteControlRef.Tell(RemoteControlState.ChangeComplete); } break; case ConditionAction.SendFalse: isGateOpen = false; break; } } }
private void CheckChange() { if (_PremiseIsClosedActorRef.IsNobody() || _PremiseIsOpenActorRef.IsNobody()) { return; } if (attributeGateState != oldAttributeGateState) { if (attributeGateState == (int)GateState.Closed) { _PremiseIsClosedActorRef.Tell(PremiseAction.MakeTrue); _PremiseIsOpenActorRef.Tell(PremiseAction.MakeFalse); } else if (attributeGateState == (int)GateState.Open) { _PremiseIsClosedActorRef.Tell(PremiseAction.MakeFalse); _PremiseIsOpenActorRef.Tell(PremiseAction.MakeTrue); } oldAttributeGateState = attributeGateState; } }
private void ProcessResourceMsgHandler(ProcessResourceMsg msg) { _logger.Info( $"ProcessResourceMsgHandler for {msg.Resource} Epoch={msg.Resource.Content?.MatchStatus}{(msg.Resource.IsMatchOver ? $" isMatchOver=true": "")}"); if (msg.Resource.Content == null) { _logger.Info($"ProcessResourceMsgHandler for {msg.Resource} content=NULL terminating"); return; } IActorRef streamListenerActor = Context.Child(StreamListenerActor.GetName(msg.Resource.Id)); if (streamListenerActor.IsNobody()) { var fixtureState = GetFixtureState(msg.Resource); if (fixtureState != null && fixtureState.Sequence > msg.Resource.Content.Sequence) { _logger.Info($"ProcessResourceMsgHandler for {msg.Resource} message is too old: messageSequence={msg.Resource.Content.Sequence} stateSequence={fixtureState.Sequence} terminating"); return; } _logger.Info( $"Stream listener for {msg.Resource} doesn't exist. Going to trigger creation."); _streamListenerBuilderActorRef.Tell(new CreateStreamListenerMsg { Resource = msg.Resource }); } else { _logger.Info( $"Stream listener for {msg.Resource} already exists. Going to trigger stream health check."); streamListenerActor.Tell(new StreamHealthCheckMsg { Resource = msg.Resource, Time = DateTime.Now }); } }
private void Runner() { if (!_sendBack || _sender.IsNobody()) { return; } var errors = new List <string>(); var fail = false; foreach (var result in _results) { if (result.IsOk) { continue; } fail = true; errors.AddRange(result.Errors.OrElse(Array.Empty <string>)); } _sender.Tell(fail ? OperationResult.Failure(errors.Select(s => new Error(null, s)), _action) : OperationResult.Success(_action), ActorRefs.NoSender); }
private void ProcessResourceMsgHandler(ProcessResourceMsg msg) { _logger.Info( $"ProcessResourceMsgHandler for {msg.Resource} Epoch={msg.Resource.Content.MatchStatus}"); IActorRef streamListenerActor = Context.Child(StreamListenerActor.GetName(msg.Resource.Id)); if (streamListenerActor.IsNobody()) { _logger.Info( $"Stream listener for {msg.Resource} doesn't exist. Going to trigger creation."); _streamListenerBuilderActorRef.Tell(new CreateStreamListenerMsg { Resource = msg.Resource }); } else { _logger.Info( $"Stream listener for {msg.Resource} already exists. Going to trigger stream health check."); streamListenerActor.Tell(new StreamHealthCheckMsg { Resource = msg.Resource }); } }
private Task <SetThrottleAck> AskModeWithDeathCompletion(IActorRef target, ThrottleMode mode, TimeSpan timeout) { if (target.IsNobody()) { return(Task.FromResult(SetThrottleAck.Instance)); } else { return(target.Ask <SetThrottleAck>(mode, timeout)); //TODO: use PromiseActorRef here when implemented //var internalTarget = target.AsInstanceOf<InternalActorRef>(); //var promiseRef = PromiseActorRef.Apply(internalTarget.Provider, timeout, target, mode.GetType().Name); //internalTarget.Tell(new Watch(internalTarget, promiseRef)); //target.Tell(mode, promiseRef); //return promiseRef.Result.Task.ContinueWith(tr => //{ // if (tr.Result is Status.Success) // { // var resultMsg = tr.Result as Status.Success; // if (resultMsg.Status is Terminated && // resultMsg.Status.AsInstanceOf<Terminated>().ActorRef.Path == target.Path) // return SetThrottleAck.Instance; // if (resultMsg.Status is SetThrottleAck) // { // internalTarget.Tell(new Unwatch(target, promiseRef)); // } // return SetThrottleAck.Instance; // } // else // { // internalTarget.Tell(new Unwatch(target, promiseRef)); // return SetThrottleAck.Instance; // } //}, TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously); } }
protected virtual bool SpecialHandle(object message, IActorRef sender) { var w = message as Watch; if(w != null) { if(w.Watchee == this && w.Watcher != this) { w.Watcher.Tell(new DeathWatchNotification(w.Watchee, existenceConfirmed: false, addressTerminated: false)); } return true; } if(message is Unwatch) return true; //Just ignore var identify = message as Identify; if(identify != null) { sender.Tell(new ActorIdentity(identify.MessageId, null)); return true; } var sel = message as ActorSelectionMessage; if(sel != null) { var selectionIdentify = sel.Message as Identify; if(selectionIdentify != null) { if(!sel.WildCardFanOut) sender.Tell(new ActorIdentity(selectionIdentify.MessageId, null)); } else { _eventStream.Publish(new DeadLetter(sel.Message, sender.IsNobody() ? _provider.DeadLetters : sender, this)); } return true; } return false; }
/// <summary> /// Returns the <paramref name="actorRef"/>'s value if it's not <see langword="null"/>, <see cref="Nobody"/>, /// or <see cref="DeadLetterActorRef"/>. Otherwise return the result of evaluating `elseValue`. /// </summary> /// <param name="actorRef">The actor that is being tested.</param> /// <param name="elseValue">TBD</param> public static IActorRef GetOrElse(this IActorRef actorRef, Func <IActorRef> elseValue) { return(actorRef.IsNobody() ? elseValue() : actorRef); }
protected virtual bool SpecialHandle(object message, IActorRef sender) { var watch = message as Watch; if (watch != null) { if (watch.Watchee.Equals(this) && !watch.Watcher.Equals(this)) { watch.Watcher.SendSystemMessage(new DeathWatchNotification(watch.Watchee, existenceConfirmed: false, addressTerminated: false)); } return(true); } if (message is Unwatch) { return(true); //Just ignore } var identify = message as Identify; if (identify != null) { sender.Tell(new ActorIdentity(identify.MessageId, null)); return(true); } var actorSelectionMessage = message as ActorSelectionMessage; if (actorSelectionMessage != null) { var selectionIdentify = actorSelectionMessage.Message as Identify; if (selectionIdentify != null) { if (!actorSelectionMessage.WildCardFanOut) { sender.Tell(new ActorIdentity(selectionIdentify.MessageId, null)); } } else { _eventStream.Publish(new DeadLetter(actorSelectionMessage.Message, sender.IsNobody() ? _provider.DeadLetters : sender, this)); } return(true); } // TODO: DeadLetterSupression return(false); }
private void PublishSupressedDeadLetter(IDeadLetterSuppression msg, IActorRef sender) { _eventStream.Publish(new SuppressedDeadLetter(msg, sender.IsNobody() ? _provider.DeadLetters : sender, this)); }
/// <summary> /// TBD /// </summary> /// <param name="message">TBD</param> /// <param name="sender">TBD</param> /// <returns>TBD</returns> protected virtual bool SpecialHandle(object message, IActorRef sender) { if (message is Watch watch) { if (watch.Watchee.Equals(this) && !watch.Watcher.Equals(this)) { watch.Watcher.SendSystemMessage(new DeathWatchNotification(watch.Watchee, existenceConfirmed: false, addressTerminated: false)); } return(true); } if (message is Unwatch) { return(true); //Just ignore } if (message is Identify identify) { sender.Tell(new ActorIdentity(identify.MessageId, null)); return(true); } if (message is ActorSelectionMessage actorSelectionMessage) { if (actorSelectionMessage.Message is Identify selectionIdentify) { if (!actorSelectionMessage.WildCardFanOut) { sender.Tell(new ActorIdentity(selectionIdentify.MessageId, null)); } } else { if (actorSelectionMessage.Message is IDeadLetterSuppression selectionDeadLetterSuppression) { PublishSupressedDeadLetter(selectionDeadLetterSuppression, sender); } else { _eventStream.Publish(new DeadLetter(actorSelectionMessage.Message, sender.IsNobody() ? _provider.DeadLetters : sender, this)); } } return(true); } if (message is IDeadLetterSuppression deadLetterSuppression) { PublishSupressedDeadLetter(deadLetterSuppression, sender); return(true); } return(false); }
protected override void Load(ContainerBuilder builder) { //TODO: Expose and register this as appart of configuration system ActorAssemblyDefinitionConfiguration actorAssemblyConfig = new ActorAssemblyDefinitionConfiguration(Array.Empty <string>()); foreach (var s in actorAssemblyConfig.AssemblyNames) { Debug.Log($"Actor Assembly: {s}"); } Debug.Log(AppDomain.CurrentDomain.GetAssemblies().Aggregate("Loaded Assemblies: ", (s, assembly) => $"{s} {assembly.GetName().Name}")); //The below loads the actor assemblies defined in the configuration. //It then searches for all message handlers and then registers them. //It's a complicated process. //TODO: Support actually loading unloaded assemblies (like 3rd party user assemblies) foreach (Assembly actorAssemblyToParse in actorAssemblyConfig.AssemblyNames .Select(d => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => d == a.GetName().Name.ToLower())) .Where(a => a != null)) { Debug.Log($"Parsing ActorAssembly: {actorAssemblyToParse.GetName().Name}"); foreach (Type t in actorAssemblyToParse.GetTypes()) { //If they have the handler attribute, we should just register it. if (t.GetCustomAttributes <EntityActorMessageHandlerAttribute>().Any()) { Debug.Log($"Register ActorMessageHandler: {t.Name}"); //Now we need to find the actor state type Type actorStateType = t.GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityActorMessageHandler <,>)) .GenericTypeArguments.First(); var handlerRegisteration = builder.RegisterType(t) .AsSelf() .As(typeof(IEntityActorMessageHandler <,>).MakeGenericType(new Type[2] { actorStateType, typeof(EntityActorMessage) })) .As <IEntityActorMessageHandler>() .SingleInstance(); foreach (var attri in t.GetCustomAttributes <EntityActorMessageHandlerAttribute>()) { //TODO: Support multiple level inherited types. //If the actor has a different state type we should assume it's valid if it can be assigned. Type specificActorStateType = attri.TargetActorType.BaseType.GenericTypeArguments.Reverse().First(); if (specificActorStateType != actorStateType) { if (actorStateType.IsAssignableFrom(specificActorStateType)) { handlerRegisteration = handlerRegisteration .As(typeof(IEntityActorMessageHandler <,>).MakeGenericType(new Type[2] { specificActorStateType, typeof(EntityActorMessage) })); } else { throw new InvalidOperationException($"Actor: {attri.TargetActorType.Name} attempted to use Handler: {t.Name} but had non-matching state Types: {actorStateType.Name}/{specificActorStateType.Name}"); } } } } else if (typeof(IEntityActor).IsAssignableFrom(t)) { //Don't want to register abstract entities. if (!t.IsAbstract) { Debug.Log($"Register Actor: {t.Name}"); builder.RegisterType(t) .AsSelf(); } } } } //Below is an open generic registeration of the generic router //this makes it EASY to inject into the actors builder.RegisterGeneric(typeof(ReflectionBasedGenericMessageRouter <,>)) .As(typeof(IEntityActorMessageRouteable <,>)) .SingleInstance(); //Create the root of the actor system. builder.RegisterInstance(ActorSystem.Create("Root")) .AsSelf() .As <ActorSystem>() .As <IActorRefFactory>() .SingleInstance(); builder.Register <IScheduler>(context => { ActorSystem actorSystem = context.Resolve <ActorSystem>(); return(actorSystem.Scheduler); }) .As <IScheduler>() .SingleInstance(); //Creates the autofac dependency resolver that can be used to actually resolve //the Actor's dependencies. builder.Register(context => { if (!context.IsRegistered <IEntityActorMessageRouteable <DefaultWorldActor, WorldActorState> >()) { Debug.LogError($"CRITICAL dependency for Actor IOC not registered."); } if (!context.IsRegistered <DefaultWorldActor>()) { Debug.LogError($"CRITICAL dependency for Actor IOC not registered."); } return(new AutoFacDependencyResolver(context.Resolve <ILifetimeScope>(), context.Resolve <ActorSystem>())); }) .As <IDependencyResolver>() .AsSelf() .SingleInstance(); builder.RegisterType <DefaultWorldActor>() .AsSelf(); builder.RegisterType <UnityAkkaActorLoggerAdapter>() .AsSelf() .As <ILoggingAdapter>() .SingleInstance(); builder.RegisterType <UnityLoggerActor>() .AsSelf(); builder.RegisterType <DefaultGameObjectEntityActorFactory>() .As <IGameObjectEntityActorFactory>() .SingleInstance(); //This creates the World actor. builder.Register(context => { try { IDependencyResolver resolver = context.Resolve <IDependencyResolver>(); ActorSystem actorSystem = context.Resolve <ActorSystem>(); actorSystem.ActorOf(resolver.Create <UnityLoggerActor>(), "Logger"); IActorRef worldActorReference = actorSystem.ActorOf(resolver.Create <DefaultWorldActor>(), "World"); if (worldActorReference.IsNobody()) { Debug.LogError($"FAILED TO CREATE WORLD ACTOR."); } return(new WorldActorReferenceAdapter(worldActorReference)); } catch (Exception e) { Debug.LogError($"Failed to create WorldActor in IoC. Reason: {e.Message}\n\nStack: {e.StackTrace}"); throw; } }) .As <IWorldActorRef>() .SingleInstance(); }