示例#1
0
        private async Task Spawning(ActorPidRequest req, string activator, int retryLeft, SpawningProcess spawning)
        {
            if (string.IsNullOrEmpty(activator))
            {
                activator = MemberList.GetActivator(req.Kind);
                if (string.IsNullOrEmpty(activator))
                {
                    //No activator currently available, return unavailable
                    _logger.LogDebug("No activator currently available");
                    spawning.TrySetResult(ActorPidResponse.Unavailable);
                    return;
                }
            }

            ActorPidResponse pidResp;

            try
            {
                pidResp = await Remote.Remote.SpawnNamedAsync(activator, req.Name, req.Kind, Cluster.Config.TimeoutTimespan)
                          .ConfigureAwait(false);
            }
            catch (TimeoutException)
            {
                spawning.TrySetResult(ActorPidResponse.TimeOut);
                return;
            }
            catch
            {
                spawning.TrySetResult(ActorPidResponse.Err);
                return;
            }

            if ((ResponseStatusCode)pidResp.StatusCode == ResponseStatusCode.Unavailable && retryLeft != 0)
            {
                await Spawning(req, null, --retryLeft, spawning).ConfigureAwait(false);

                return;
            }

            spawning.TrySetResult(pidResp);
        }
示例#2
0
        private void Spawn(ActorPidRequest msg, IContext context)
        {
            //Check if exist in current partition dictionary
            if (_partition.TryGetValue(msg.Name, out var pid))
            {
                context.Respond(new ActorPidResponse {
                    Pid = pid
                });
                return;
            }

            //Check if is spawning, if so just await spawning finish.
            SpawningProcess spawning;

            if (_spawningProcs.TryGetValue(msg.Name, out spawning))
            {
                context.ReenterAfter(spawning.Task, rst =>
                {
                    context.Respond(rst.IsFaulted ? ActorPidResponse.Err : rst.Result);
                    return(Actor.Done);
                });
                return;
            }

            //Get activator
            var activator = MemberList.GetActivator(msg.Kind);

            if (string.IsNullOrEmpty(activator))
            {
                //No activator currently available, return unavailable
                _logger.LogDebug("No members currently available");
                context.Respond(ActorPidResponse.Unavailable);
                return;
            }

            //Create SpawningProcess and cache it in spawning dictionary.
            spawning = new SpawningProcess(activator);
            _spawningProcs[msg.Name] = spawning;

            //Await SpawningProcess
            context.ReenterAfter(spawning.Task, rst =>
            {
                _spawningProcs.Remove(msg.Name);

                //Check if exist in current partition dictionary
                //This is necessary to avoid race condition during partition map transfering.
                if (_partition.TryGetValue(msg.Name, out pid))
                {
                    context.Respond(new ActorPidResponse {
                        Pid = pid
                    });
                    return(Actor.Done);
                }

                //Check if process is faulted
                if (rst.IsFaulted)
                {
                    context.Respond(ActorPidResponse.Err);
                    return(Actor.Done);
                }

                var pidResp = rst.Result;
                if ((ResponseStatusCode)pidResp.StatusCode == ResponseStatusCode.OK)
                {
                    pid = pidResp.Pid;
                    _partition[msg.Name]   = pid;
                    _reversePartition[pid] = msg.Name;
                    context.Watch(pid);
                }
                context.Respond(pidResp);
                return(Actor.Done);
            });

            //Perform Spawning
            Task.Factory.StartNew(() => Spawning(msg, activator, 3, spawning));
        }
示例#3
0
        private async Task Spawn(ActorPidRequest msg, IContext context)
        {
            if (_partition.TryGetValue(msg.Name, out var pid))
            {
                context.Respond(new ActorPidResponse {
                    Pid = pid
                });
                return;
            }

            var activator = MemberList.GetActivator(msg.Kind);

            if (string.IsNullOrEmpty(activator))
            {
                //No activator currently available, return unavailable
                _logger.LogDebug("No members currently available");
                context.Respond(new ActorPidResponse {
                    StatusCode = (int)ResponseStatusCode.Unavailable
                });
                return;
            }

            for (var retry = 3; retry >= 0; retry--)
            {
                if (string.IsNullOrEmpty(activator))
                {
                    activator = MemberList.GetActivator(msg.Kind);
                    if (string.IsNullOrEmpty(activator))
                    {
                        //No activator currently available, return unavailable
                        _logger.LogDebug("No activator currently available");
                        context.Respond(new ActorPidResponse {
                            StatusCode = (int)ResponseStatusCode.Unavailable
                        });
                        return;
                    }
                }

                ActorPidResponse pidResp;
                try
                {
                    pidResp = await Remote.Remote.SpawnNamedAsync(activator, msg.Name, msg.Kind, Cluster.cfg.TimeoutTimespan);
                }
                catch (TimeoutException)
                {
                    context.Respond(new ActorPidResponse {
                        StatusCode = (int)ResponseStatusCode.Timeout
                    });
                    throw;
                }
                catch
                {
                    context.Respond(new ActorPidResponse {
                        StatusCode = (int)ResponseStatusCode.Error
                    });
                    throw;
                }

                switch ((ResponseStatusCode)pidResp.StatusCode)
                {
                case ResponseStatusCode.OK:
                    pid = pidResp.Pid;
                    _partition[msg.Name]   = pid;
                    _reversePartition[pid] = msg.Name;
                    context.Watch(pid);
                    context.Respond(pidResp);
                    return;

                case ResponseStatusCode.Unavailable:
                    //Get next activator to spawn
                    if (retry != 0)
                    {
                        activator = null;
                        continue;
                    }
                    context.Respond(pidResp);
                    return;

                default:
                    //Return to requester to wait
                    context.Respond(pidResp);
                    return;
                }
            }
        }