public Task RemoveLock(SpawnLock spawnLock, CancellationToken ct)
        => _asyncSemaphore.WaitAsync(() =>
        {
            Logger.LogInformation("[MongoIdentityStorage] DeleteManyAsync");
            if (ct.IsCancellationRequested)
            {
                Logger.LogInformation("[MongoIdentityStorage] DeleteManyAsync, resetting cancellation token.");
                ct = CancellationTokens.WithTimeout(TimeSpan.FromSeconds(5));
            }

            Logger.LogInformation("[MongoIdentityStorage] DeleteManyAsync, LockId {LockId}.", spawnLock.LockId);
            return(_pids.DeleteManyAsync(p => p.LockedBy == spawnLock.LockId, ct));
        });
        public Task RemoveMember(string memberId, CancellationToken ct)
        => _asyncSemaphore.WaitAsync(() =>
        {
            Logger.LogInformation("[MongoIdentityStorage] RemoveMember");
            if (ct.IsCancellationRequested)
            {
                Logger.LogInformation("[MongoIdentityStorage] RemoveMember, resetting cancellation token.");
                ct = CancellationTokens.WithTimeout(TimeSpan.FromSeconds(5));
            }

            Logger.LogInformation("[MongoIdentityStorage] RemoveMember, Pid {MemberId}.", memberId);
            return(_pids.DeleteManyAsync(p => p.MemberId == memberId, ct));
        });
        public async Task RemoveActivation(PID pid, CancellationToken ct)
        {
            Logger.LogDebug("Removing activation: {@PID}", pid);
            await _asyncSemaphore.WaitAsync(() =>
            {
                Logger.LogInformation("[MongoIdentityStorage] RemoveActivation");
                if (ct.IsCancellationRequested)
                {
                    Logger.LogInformation("[MongoIdentityStorage] RemoveActivation, resetting cancellation token.");
                    ct = CancellationTokens.WithTimeout(TimeSpan.FromSeconds(5));
                }

                Logger.LogInformation("[MongoIdentityStorage] RemoveActivation, Pid {PidIs}.", pid.Id);
                return(_pids.DeleteManyAsync(p => p.UniqueIdentity == pid.Id, ct));
            });
        }
        public async Task <PID?> GetAsync(ClusterIdentity clusterIdentity, CancellationToken ct)
        {
            ct = CancellationTokens.WithTimeout(_getPidTimeout);
            //Get address to node owning this ID
            var identityOwner = _partitionManager.Selector.GetIdentityOwner(clusterIdentity.Identity);

            Logger.LogDebug("Identity belongs to {address}", identityOwner);
            if (string.IsNullOrEmpty(identityOwner))
            {
                return(null);
            }

            var remotePid = PartitionManager.RemotePartitionIdentityActor(identityOwner);

            var req = new ActivationRequest
            {
                ClusterIdentity = clusterIdentity
            };

            Logger.LogDebug("Requesting remote PID from {Partition}:{Remote} {@Request}", identityOwner, remotePid, req
                            );

            try
            {
                var resp = await _cluster.System.Root.RequestAsync <ActivationResponse>(remotePid, req, ct);

                return(resp.Pid);
            }
            //TODO: decide if we throw or return null
            catch (DeadLetterException)
            {
                Logger.LogInformation("Remote PID request deadletter {@Request}, identity Owner {Owner}", req, identityOwner);
                return(null);
            }
            catch (TimeoutException)
            {
                Logger.LogInformation("Remote PID request timeout {@Request}, identity Owner {Owner}", req, identityOwner);
                return(null);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Error occured requesting remote PID {@Request}, identity Owner {Owner}", req, identityOwner);
                return(null);
            }
        }
示例#5
0
        public async Task CanWaitForActivation()
        {
            var activator = GetFakeActivator();
            var timeout   = CancellationTokens.WithTimeout(15 * 1000);
            var identity  = new ClusterIdentity {
                Kind = "thing", Identity = NextId().ToString()
            };
            var spawnLock = await _storage.TryAcquireLock(identity, timeout);

            var pid = Activate(activator, identity);

            _ = SafeTask.Run(async() => {
                await Task.Delay(500, timeout);
                await _storage.StoreActivation(activator.Id, spawnLock !, pid, timeout);
            }, timeout
                             );
            var activation = await _storage.WaitForActivation(identity, timeout);

            activation.Should().NotBeNull();
            activation !.MemberId.Should().Be(activator.Id);
            activation !.Pid.Should().BeEquivalentTo(pid);
        }
        private static async Task RunKafkaConsumeLoop(Cluster cluster)
        {
            while (true)
            {
                var sw = Stopwatch.StartNew();
                //get the messages from Kafka or other log/queue
                var messages = GetBatchFromKafka();
                var tasks    = new List <Task>();

                //forward each message to their actors
                foreach (var message in messages)
                {
                    object m = message.MessageCase switch
                    {
                        MyEnvelope.MessageOneofCase.SomeMessage => message.SomeMessage,
                        MyEnvelope.MessageOneofCase.SomeOtherMessage => message.SomeOtherMessage,
                        _ => throw new ArgumentOutOfRangeException(nameof(message), "Unknown message case")
                    };

                    var task = cluster
                               .RequestAsync <Ack>(message.DeviceId, "device", m, CancellationTokens.WithTimeout(5000));

                    tasks.Add(task);
                }

                //await response form all actors
                await Task.WhenAll(tasks);

                //TODO: commit back to Kafka that all messages succeeded
                sw.Stop();
                var tps = 1000.0 / sw.Elapsed.TotalMilliseconds * tasks.Count;

                //show throughput, messages per second
                Console.WriteLine(tps.ToString("n0"));
            }
        }
        public void DumpState(ClusterIdentity clusterIdentity)
        {
            Console.WriteLine("Memberlist members:");
            _cluster.MemberList.DumpState();

            Console.WriteLine("Partition manager selector:");
            _partitionManager.Selector.DumpState();

            //Get address to node owning this ID
            var identityOwner = _partitionManager.Selector.GetIdentityOwner(clusterIdentity.Identity);

            Console.WriteLine("Identity owner for ID:");
            Console.WriteLine(identityOwner);

            var remotePid = PartitionManager.RemotePartitionIdentityActor(identityOwner);

            var req = new ActivationRequest
            {
                ClusterIdentity = clusterIdentity
            };

            var resp = _cluster.System.Root.RequestAsync <ActivationResponse>(remotePid, req, CancellationTokens.WithTimeout(5000)).Result;

            Console.WriteLine("Target Pid:");

            if (resp == null)
            {
                Console.WriteLine("Null response");
            }
            else if (resp.Pid == null)
            {
                Console.WriteLine("Null PID");
            }
            else
            {
                Console.WriteLine(resp.Pid);
            }
        }
示例#8
0
        public static void Run()
        {
            var l = LoggerFactory.Create(x => x.AddConsole().SetMinimumLevel(LogLevel.Information));

            Log.SetLoggerFactory(l);
            var config = ActorSystemConfig.Setup().WithMetricsProviders(new PrometheusConfigurator());

            var remoteConfig = GrpcCoreRemoteConfig
                               .BindToLocalhost()
                               .WithProtoMessages(MessagesReflection.Descriptor);

            var clusterConfig =
                ClusterConfig
                .Setup("MyCluster", new ConsulProvider(new ConsulProviderConfig(), c => c.Address = new Uri("http://127.0.0.1:8500/")),
                       new PartitionIdentityLookup()
                       );

            var system = new ActorSystem(config)
                         .WithRemote(remoteConfig)
                         .WithCluster(clusterConfig);

            system
            .Cluster()
            .StartMemberAsync();

            var props = Props.FromProducer(() => new MyActor());

            var config2 = ActorSystemConfig.Setup().WithMetricsProviders(new PrometheusConfigurator());

            var remoteConfig2 = GrpcCoreRemoteConfig
                                .BindToLocalhost()
                                .WithProtoMessages(MessagesReflection.Descriptor);

            var clusterConfig2 =
                ClusterConfig
                .Setup("MyCluster", new ConsulProvider(new ConsulProviderConfig(), c => c.Address = new Uri("http://127.0.0.1:8500/")),
                       new PartitionIdentityLookup()
                       )
                .WithClusterKind("somekind", props);

            var system2 = new ActorSystem(config2)
                          .WithRemote(remoteConfig2)
                          .WithCluster(clusterConfig2);

            system2
            .Cluster()
            .StartMemberAsync();

            _ = SafeTask.Run(async() => {
                var r = new Random();

                while (true)
                {
                    await Task.Delay(r.Next(1, 2000));
                    await system.Cluster().RequestAsync <SomeResponse>($"someactor{r.Next(1, 100)}", "somekind", new SomeRequest(),
                                                                       CancellationTokens.WithTimeout(5000)
                                                                       );
                }
            }
                             );
        }