Example #1
0
        public Boolean CanProcessMessage(ActorRequest message)
        {
            if (_actorMap.TryGetValue(message.ActorInterface, out var actorType))
            {
                return(HasInstanceFor(actorType, message.ActorId));
            }

            return(false);
        }
Example #2
0
        public async Task <ActorResponse> SendActorRequest(ActorRequest request, TimeSpan?timeout = null)
        {
            timeout = timeout ?? TimeSpan.FromMilliseconds(-1);

            if (_localStage.Enabled)
            {
                //we are inside a stage, forward to server

                if (request.FireAndForget)
                {
                    await _stageServer.ReceivedActorRequest(request, null);

                    return(new ActorResponse()
                    {
                        Success = true
                    });
                }
                else
                {
                    var semaphore = new SemaphoreSlim(0, 1);

                    var queueItem = _localResponseBuffer[request.Id] = new Tuple <SemaphoreSlim, ActorResponse>(semaphore, null);

                    try
                    {
                        await _stageServer.ReceivedActorRequest(request, null);

                        var responseArrived = await semaphore.WaitAsync(timeout.Value);

                        if (responseArrived)
                        {
                            if (_localResponseBuffer.TryRemove(request.Id, out queueItem))
                            {
                                if (queueItem.Item2 != null)
                                {
                                    return(queueItem.Item2);
                                }
                            }
                        }

                        _localResponseBuffer.TryRemove(request.Id, out _);
                        throw new TimeoutException();
                    }
                    finally
                    {
                    }
                }
            }
            else
            {
                //we are on a pure client

                return(await SendRemoteActorRequest(request, timeout));
            }
        }
Example #3
0
        public async Task <ActorResponse> Execute(ActorRequest message, TimeSpan?timeout = null)
        {
            _reqSecondMeter.Tick();

            var actorInstanceKey = string.Join(",", message.ActorInterface, message.ActorId);

            var actorInstance = await ActivateInstance(message.ActorInterface, message.ActorId);

            actorInstance.LastAccess = DateTimeOffset.UtcNow;


            var track = _serviceOptions.TrackActorExecutionDependencyCalls ?
                        _telemetry.Dependency($"actor:{message.ActorInterface}", message.ActorMethodName) : null;

            try
            {
                var result = await actorInstance.Instance.Post(_serializer, message, timeout);

                track?.End(true);

                var response = new ActorResponse()
                {
                    Success  = true,
                    Response = _serializer.Serialize(result),
                    Id       = message.Id
                };

                return(response);
            }
            catch (Exception ex)
            {
                track?.End(false);

                var response = new ActorResponse()
                {
                    Success = false,
                    //Exception = (Exception)ex,
                    Id = message.Id
                };

                _actorInstances.TryRemove(actorInstanceKey, out var instance);
                instance.Instance.Dispose();

                await _actorDirectory.UnregisterActor(instance.ActorTypeName, instance.ActorId, this.StageGuid);

                _telemetry.Exception(ex, "ActorException");

                return(response);
            }
        }
Example #4
0
        public async Task <ActorResponse> SendRemoteActorRequest(String stageId, ActorRequest request, TimeSpan?timeout = null)
        {
            if (request is LocalActorRequest)
            {
                request = ((LocalActorRequest)request).ToRemote(_serializer);
            }

            var message = new RemoteStageMessage()
            {
                ActorRequest = request,
                MessageType  = RemoteMessageType.ActorRequest
            };

            if (request.FireAndForget)
            {
                await _socketClient.SendRequest(stageId, _serializer.Serialize(message));

                return(new ActorResponse()
                {
                    Success = true
                });
            }
            else
            {
                var semaphore = new SemaphoreSlim(0, 1);

                var queueItem = _serverResponseBuffer[request.Id] = new Tuple <SemaphoreSlim, ActorResponse>(semaphore, null);

                try
                {
                    await _socketClient.SendRequest(stageId, _serializer.Serialize(message));

                    var responseArrived = await semaphore.WaitAsync(timeout ?? TimeSpan.FromMilliseconds(-1));

                    if (responseArrived)
                    {
                        if (_serverResponseBuffer.TryRemove(request.Id, out queueItem))
                        {
                            return(queueItem.Item2);
                        }
                    }

                    throw new TimeoutException();
                }
                finally
                {
                    _serverResponseBuffer.TryRemove(request.Id, out _);
                }
            }
        }
Example #5
0
        public async Task <ActorResponse> SendRemoteActorRequest(ActorRequest request, TimeSpan?timeout = null)
        {
            if (request.WorkerActor)
            {
                var allStages = await _stageDirectory.GetAllStages();

                var stageAddress = allStages.OrderBy(a => Guid.NewGuid()).FirstOrDefault();
                return(await SendRemoteActorRequest(stageAddress, request, timeout));
            }
            else
            {
                var stageResponse = await _actorDirectory.GetAddress(request.ActorInterface, request.ActorId);

                if (await _stageDirectory.IsLive(stageResponse.StageId))
                {
                    return(await SendRemoteActorRequest(stageResponse.StageId, request, timeout));
                }
                else
                {
                    return(await SendRemoteActorRequest(null, request, timeout));
                }
            }
        }
Example #6
0
        public ActorRequest ToRemote(ITransportSerializer _serializer)
        {
            var request = new ActorRequest();

            List <byte[]> arguments = new List <byte[]>();

            foreach (var argument in this.ArgumentObjects)
            {
                arguments.Add(_serializer.Serialize(argument));
            }
            request.Arguments       = arguments;
            request.ActorInterface  = this.ActorInterface;
            request.ActorMethodName = this.ActorMethod.Name;

            request.ActorId       = this.ActorId;
            request.FireAndForget = this.FireAndForget;
            request.FromClient    = this.FromClient;
            request.Id            = this.Id;
            request.WorkerActor   = this.WorkerActor;



            return(request);
        }
Example #7
0
        protected async Task ProcessActorRequestLocally(ActorRequest message, string sourceStageId)
        {
            ActorResponse response = null;

            try {
                response = await _localStage.Execute(message);
            }
            catch (Exception ex)
            {
                response = new ActorResponse()
                {
                    Id = message.Id,
                    //Exception = ex,
                    Success = false
                };

                _telemetry.Exception(ex, "ProcessActorRequestLocally");
            }

            if (!message.FireAndForget)
            {
                await this.SendActorResponse(sourceStageId, response);
            }
        }
Example #8
0
        public async Task <object> Post(ITransportSerializer serializer, ActorRequest message, TimeSpan?timeout = null, CancellationToken?ct = null)
        {
            var key = $"{_typeName}.{message.ActorMethodName}";

            if (!_methodCache.TryGetValue(key, out var method))
            {
                method = this.GetType().GetMethod(message.ActorMethodName);

                _methodCache.TryAdd(key, method);
            }

            //timeout attribute
            var timeoutAttribute = method.GetCustomAttribute <MethodTimeoutAttribute>();

            if (timeoutAttribute != null)
            {
                timeout = timeoutAttribute.Timeout;
            }
            else
            {
                timeout = timeout ?? TimeSpan.FromSeconds(_options.DefaultActorMethodTimeout);
            }

            var parameters = method.GetParameters();

            //wire parameters
            List <object> arguments = new List <object>();

            if (message is LocalActorRequest)
            {
                var localMessage = (LocalActorRequest)message;
                for (var i = 0; i < parameters.Length; i++)
                {
                    var parameterInfo = parameters[i];
                    if (localMessage.ArgumentObjects.Length > i)
                    {
                        arguments.Add(localMessage.ArgumentObjects[i]);
                    }
                    else
                    {
                        arguments.Add(Type.Missing);
                    }
                }
            }
            else
            {
                for (var i = 0; i < parameters.Length; i++)
                {
                    var parameterInfo = parameters[i];
                    if (message.Arguments.Count > i)
                    {
                        arguments.Add(serializer.Deserialize(parameterInfo.ParameterType, message.Arguments[i]));
                    }
                    else
                    {
                        arguments.Add(Type.Missing);
                    }
                }
            }

            Task workTask = null;

            var sync = method.GetCustomAttribute <AllowParallel>(true) == null;

            if (sync)
            {
                Interlocked.Increment(ref _queueCount);
                {
                    if (timeout.HasValue)
                    {
                        var sw = Stopwatch.StartNew();

                        //try to acquire lock
                        var asyncLock = await _executionLock.LockAsync(timeout.Value);

                        if (asyncLock == null)
                        {
                            throw new TimeoutException();
                        }

                        try
                        {
                            sw.Stop();

                            //try to run method
                            var timeoutTask = Task.Delay(timeout.Value - sw.Elapsed);

                            workTask = (Task)method.Invoke(this, arguments.ToArray());
                            await Task.WhenAny(workTask, timeoutTask);

                            if (timeoutTask.IsCompleted && !workTask.IsCompleted)
                            {
                                throw new TimeoutException();
                            }
                        }
                        finally
                        {
                            if (asyncLock != null)
                            {
                                asyncLock.Dispose();
                            }
                        }
                    }
                    else
                    {
                        var asyncLock = await _executionLock.LockAsync();

                        workTask = (Task)method.Invoke(this, arguments.ToArray());

                        await workTask;

                        if (asyncLock != null)
                        {
                            asyncLock.Dispose();
                        }
                    }


                    Interlocked.Decrement(ref _queueCount);
                }
            }
            else
            {
                workTask = (Task)method.Invoke(this, arguments.ToArray());
            }


            if (!_returnPropertyCache.TryGetValue(key, out var resultProperty))
            {
                if (method.ReturnType.IsConstructedGenericType)
                {
                    resultProperty = workTask.GetType().GetProperty("Result");

                    _returnPropertyCache.TryAdd(key, resultProperty);
                }
                else
                {
                    _returnPropertyCache.TryAdd(key, null);
                }
            }

            if (resultProperty != null && workTask != null)
            {
                var result = resultProperty.GetValue(workTask);
                return(result);
            }
            else
            {
                return(null);
            }
        }
Example #9
0
        public async Task ReceivedActorRequest(ActorRequest message, string sourceStageId)
        {
            if (_localStage == null || !_localStage.Enabled)
            {
                //we are inside a client, no point on getting actor requests
                _exitSemaphore.Release();
                return;
            }

            if (message.WorkerActor)
            {
                await ProcessActorRequestLocally(message, sourceStageId);

                return;
            }

            if (_localStage.CanProcessMessage(message))
            {
                //we already have a local instance
                await ProcessActorRequestLocally(message, sourceStageId);

                return;
            }

            //query the directory
            var queryResult = await _actorDirectory.GetAddress(message.ActorInterface, message.ActorId);

            if (queryResult.Found)
            {
                if (queryResult.StageId == _localStage.StageGuid)
                {
                    //instance already registered on this stage but not active
                    await ProcessActorRequestLocally(message, sourceStageId);

                    return;
                }
                else
                {
                    if (await _stageDirectory.IsLive(queryResult.StageId))
                    {
                        //proxy request to the right stage
                        var remoteResponse = await _remoteClient.Value.SendRemoteActorRequest(queryResult.StageId, message);

                        if (!message.FireAndForget)
                        {
                            await this.SendActorResponse(sourceStageId, remoteResponse);
                        }
                    }
                    else
                    {
                        //reallocate the actor
                        var newStageId = await _actorDirectory.Reallocate(message.ActorInterface, message.ActorId, queryResult.StageId);

                        //try again
                        await ReceivedActorRequest(message, sourceStageId);
                    }
                }
            }
            else
            {
                //reallocate the actor
                var newStageId = await _actorDirectory.Reallocate(message.ActorInterface, message.ActorId, queryResult.StageId);

                //try again
                await ReceivedActorRequest(message, sourceStageId);
            }
        }
Example #10
0
        public async Task <object> Post(ITransportSerializer serializer, ActorRequest message, TimeSpan?timeout = null, CancellationToken?ct = null)
        {
            if (_taskScheduler == null)
            {
                return(null);
            }

            try
            {
                var key = $"{this.GetType().Name}.{message.ActorMethodName}";

                if (!_methodCache.TryGetValue(key, out var method))
                {
                    method = this.GetType().GetMethod(message.ActorMethodName);

                    _methodCache.TryAdd(key, method);
                }
                var parameters = method.GetParameters();

                List <object> arguments = new List <object>();
                for (var i = 0; i < message.Arguments.Count; i++)
                {
                    var parameterInfo = parameters[i];
                    arguments.Add(serializer.Deserialize(parameterInfo.ParameterType, message.Arguments[i]));
                }

                var taskResult = await Task.Factory.StartNew(async() =>
                {
                    Task workTask = (Task)method.Invoke(this, arguments.ToArray());
                    await workTask;

                    return(workTask);
                }, ct ?? CancellationToken.None, TaskCreationOptions.None, _taskScheduler);


                var doneTask = taskResult.Result;
                if (!_returnPropertyCache.TryGetValue(key, out var resultProperty))
                {
                    if (method.ReturnType.IsConstructedGenericType)
                    {
                        resultProperty = doneTask.GetType().GetProperty("Result");

                        _returnPropertyCache.TryAdd(key, resultProperty);
                    }
                    else
                    {
                        _returnPropertyCache.TryAdd(key, null);
                    }
                }

                if (resultProperty != null)
                {
                    var result = resultProperty.GetValue(doneTask);

                    return(result);
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                {
                    return(ex.InnerException);
                }
                else
                {
                    return(ex);
                }
            }
        }