/// <summary>
        /// Remove actor from container
        /// </summary>
        /// <param name="actorType">actor type</param>
        /// <param name="actorKey">actor key</param>
        /// <returns>actor registration or null if not exist</returns>
        public async Task <IActorRegistration?> Remove(IWorkContext context, Type actorType, ActorKey actorKey)
        {
            actorType.Verify(nameof(actorType)).IsNotNull();
            actorKey.Verify(nameof(actorKey)).IsNotNull();
            context = context.With(_tag);

            context.Telemetry.Verbose(context.With(_tag), $"Removing actor {actorKey}");

            IActorRegistration registration;

            lock (_lock)
            {
                var key = new RegistrationKey(actorType, actorKey.Key);
                if (!_actorCache.TryRemove(key, out registration))
                {
                    return(null);
                }
            }

            try
            {
                await registration.Instance.Deactivate(context).ConfigureAwait(false);
            }
            finally
            {
                registration.Instance.Dispose();
            }

            return(registration);
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="actorType">actor type</param>
        /// <param name="actorKey">actor key</param>
        /// <param name="instance">instance of the actor class</param>
        /// <param name="actorProxy">actor proxy</param>
        public ActorRegistration(Type actorType, ActorKey actorKey, IActorBase instance, IActor actorProxy)
        {
            actorType.Verify(nameof(actorType)).IsNotNull();
            actorKey.Verify(nameof(actorKey)).IsNotNull();
            instance.Verify(nameof(instance)).IsNotNull();
            actorProxy.Verify(nameof(actorProxy)).IsNotNull();

            ActorType   = actorType;
            ActorKey    = actorKey;
            _instance   = instance;
            _actorProxy = actorProxy;
        }
        public static void ActorStopTimerEvent(this ActorConfiguration configuration, IWorkContext context, ActorKey actorKey, string?message = null)
        {
            configuration.Verify(nameof(configuration)).IsNotNull();
            actorKey.Verify(nameof(actorKey)).IsNotNull();

            IEventDimensions dimensions = new EventDimensionsBuilder()
                                          .Add(nameof(actorKey), actorKey)
                                          .Add(nameof(message), message)
                                          .Build();

            configuration.WorkContext.Telemetry.LogEvent(context, nameof(ActorStopTimerEvent), dimensions);
        }
Esempio n. 4
0
        /// <summary>
        /// Deactivate actor
        /// </summary>
        /// <typeparam name="T">actor interface</typeparam>
        /// <param name="context">context</param>
        /// <param name="actorKey">actor key</param>
        /// <returns>true if deactivated, false if not found</returns>
        public async Task <bool> Deactivate <T>(ActorKey actorKey)
        {
            Verify.Assert(IsRunning, _disposedTestText);
            actorKey.Verify(nameof(actorKey)).IsNotNull();

            IActorRegistration?actorRegistration = await _actorRepository.Remove(Configuration.WorkContext.With(_tag), typeof(T), actorKey).ConfigureAwait(false);

            if (actorRegistration == null)
            {
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Lookup actor
        /// </summary>
        /// <param name="actorType">actor type</param>
        /// <param name="actorKey">actor key</param>
        /// <returns>actor registration or null if not exist</returns>
        public IActorRegistration?Lookup(Type actorType, ActorKey actorKey)
        {
            actorType.Verify(nameof(actorType)).IsNotNull();
            actorKey.Verify(nameof(actorKey)).IsNotNull();

            lock (_lock)
            {
                var key = new RegistrationKey(actorType, actorKey.Key);

                if (_actorCache.TryGetValue(key, out IActorRegistration registration))
                {
                    return(registration);
                }

                return(null);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Create proxy to actor, return current instance or create one
        /// </summary>
        /// <typeparam name="T">actor interface</typeparam>
        /// <param name="context">context</param>
        /// <param name="actorKey">actor key</param>
        /// <returns>actor proxy interface</returns>
        public async Task <T> CreateProxy <T>(ActorKey actorKey) where T : IActor
        {
            Verify.Assert(IsRunning, _disposedTestText);

            actorKey.Verify(nameof(actorKey)).IsNotNull();

            Type actorType = typeof(T);

            // Lookup instance of actor (type + actorKey)
            IActorRegistration?actorRegistration = _actorRepository.Lookup(actorType, actorKey);

            if (actorRegistration != null)
            {
                return(actorRegistration.GetInstance <T>());
            }

            // Create actor
            IActor actorObject = _typeManager.Create <T>(Configuration.WorkContext.With(_tag), actorKey, this);

            IActorBase?actorBase = actorObject as IActorBase;

            if (actorBase == null)
            {
                var ex = new ArgumentException($"Actor {actorObject.GetType().FullName} does not implement IActorBase");
                Configuration.WorkContext.Telemetry.Error(Configuration.WorkContext.With(_tag), "Cannot create", ex);
                throw ex;
            }

            // Create proxy
            T actorInterface = ActorProxy <T> .Create(Configuration.WorkContext.With(_tag), actorBase, this);

            actorRegistration = new ActorRegistration(typeof(T), actorKey, actorBase, actorInterface);

            await _actorRepository.Set(Configuration.WorkContext.With(_tag), actorRegistration).ConfigureAwait(false);

            // Create proxy for interface
            return(actorRegistration.GetInstance <T>());
        }
Esempio n. 7
0
        /// <summary>
        /// Create actor from either lambda or activator
        /// </summary>
        /// <typeparam name="T">actor interface</typeparam>
        /// <param name="context">context</param>
        /// <param name="actorKey">actor key</param>
        /// <param name="manager">actor manager</param>
        /// <returns>instance of actor implementation</returns>
        public T Create <T>(IWorkContext context, ActorKey actorKey, IActorManager manager) where T : IActor
        {
            context.Verify(nameof(context)).IsNotNull();
            actorKey.Verify(nameof(actorKey)).IsNotNull();
            manager.Verify(nameof(manager)).IsNotNull();

            typeof(T).IsInterface.Verify().Assert(x => x == true, $"{typeof(T)} must be an interface");
            context = context.With(_tag);

            Type actorType = typeof(T);

            ActorTypeRegistration?typeRegistration = GetTypeRegistration(actorType) ?? GetTypeFromDi(context, actorType);

            if (typeRegistration == null)
            {
                var ex = new KeyNotFoundException($"Registration for {actorType.FullName} was not found");
                context.Telemetry.Error(context.With(_tag), "create failure", ex);
                throw ex;
            }

            IActor actorObject = typeRegistration.CreateImplementation(context);

            // Set actor key and manager
            ActorBase?actorBase = actorObject as ActorBase;

            if (actorBase == null)
            {
                string failureMsg = $"Created actor type {actorObject.GetType()} does not derive from ActorBase";
                context.Telemetry.Error(context.With(_tag), failureMsg);
                throw new InvalidOperationException(failureMsg);
            }

            actorBase.ActorKey     = actorKey;
            actorBase.ActorManager = manager;
            actorBase.ActorType    = actorType;

            return((T)actorObject);
        }