Exemple #1
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));
                }
            }
        }
        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);
            }
        }