Ejemplo n.º 1
0
        private static void InitializeProgressSubscription()
        {
            string receptionistActorPath = string.Format("{3}://App-Cluster@{0}:{1}/system/{2}",
                                                         AkkaDistributedHelper.GetFullyQualifiedDomainName(), Ports.Router, "receptionist", TcpProtocol);
            ImmutableHashSet <ActorPath> initialContacts = ImmutableHashSet.Create(ActorPath.Parse(receptionistActorPath));

            var settings = ClusterClientSettings.Create(MyActorSystem).WithInitialContacts(initialContacts);

            clusterClient = MyActorSystem.ActorOf(ClusterClient.Props(settings), "Client");

            subscriber = MyActorSystem.ActorOf(Props.Create <ProgressSubscriberActor>(), NamesRegistry.ProgressSubscriber);

            Timer progressTimer = new Timer
            {
                Interval = 500
            };

            progressTimer.Enabled  = true;
            progressTimer.Elapsed += (sender, args) =>
            {
                object response = clusterClient.Ask(new ClusterClient.Publish(NamesRegistry.ProgressTopic,
                                                                              new ProgressPublisherActor.ProgressUpdateRequest())).Result;
                subscriber.Tell(response);
            };

            Console.WriteLine($"Created Subscriber for progress updates: {clusterClient.Path} on {MyActorSystem.Name}");
        }
        public void Start()
        {
            var system = ActorSystem.Create(Constants.ActorSystemName, ConfigurationFactory.Load().WithFallback(ClusterSingletonManager.DefaultConfig()));

            system.Settings.InjectTopLevelFallback(ClusterClientReceptionist.DefaultConfig());
            var settings = ClusterClientSettings.Create(system);
            var client   = system.ActorOf(ClusterClient.Props(settings), clientName);

            while (!shouldStop)
            {
                Console.WriteLine("Press key to send message");
                Console.ReadKey();
                client.Ask <ShardEnvelope>(new ClusterClient.Send("/user/sharding/MyActor", new ShardEnvelope(envelopeId, SendMessage)
                {
                    FromClientId = clientId
                }), TimeSpan.FromSeconds(10))
                .ContinueWith(se =>
                {
                    if (se.Status == TaskStatus.Canceled)
                    {
                        Logger.Warn("He ignored me:(");
                    }
                    else
                    {
                        Logger.Info($"Received response with EntityId: {se.Result.EntityId}, Message: {se.Result.Message}, from NodeId: {se.Result.FromNodeId}");
                    }
                });
            }
        }
Ejemplo n.º 3
0
        public static void staticinit()
        {
            Configuration conf = new Configuration {
                Seeds = "localhost:9093"
            };                                                                  //"broker.local:9091"

            conf.ClientId = "LibreriaBProducer";
            conf.ClientRequestTimeoutMs  = 2000;
            conf.RequestTimeoutMs        = 2000;
            conf.RefreshMetadataInterval = new TimeSpan(0, 0, 0, 0, 100);
            conf.CompressionCodec        = CompressionCodec.None;
            conf.ErrorStrategy           = ErrorStrategy.Retry;
            //conf.MaxBufferedMessages = 100;
            conf.MaxRetry             = 10;
            conf.ProduceBatchSize     = 1;
            conf.ProduceBufferingTime = new TimeSpan(0, 0, 0, 0, 10);
            conf.RequiredAcks         = RequiredAcks.Leader;
            logger                 = new CustomLogger();
            cluster                = new ClusterClient(conf, logger);
            prod                   = new KafkaProducer <string, string>(Program.args.KafkaTopic, cluster);
            prod.Acknowledged     += Prod_Acknowledged;
            prod.MessageDiscarded += Prod_MessageDiscarded;
            prod.MessageExpired   += Prod_MessageExpired;
            prod.Throttled        += Prod_Throttled;
        }
Ejemplo n.º 4
0
        public static void AddApiKey(string adminApiKey, string apiKey, IClusterProvider managementApiTopology, ILog log)
        {
            var client = new ClusterClient(
                log,
                configuration =>
            {
                configuration.ClusterProvider = managementApiTopology;
                configuration.Transport       = new UniversalTransport(log);
            });

            var task = client.SendAsync(
                Request.Post("/rules/set")
                .WithHeader("apiKey", adminApiKey)
                .WithAdditionalQueryParameter("key", apiKey)
                .WithAdditionalQueryParameter("pattern", "*")
                .WithAdditionalQueryParameter("rights", "rwm"),
                15.Seconds()
                );

            var result = task.GetAwaiter().GetResult();

            if (result.Status != ClusterResultStatus.Success || result.Response.Code != ResponseCode.Ok)
            {
                throw new Exception($"Failed to add api key '{apiKey}'. Server responded with {result.Response.Code}: '{result.Response.Content}'.");
            }
        }
Ejemplo n.º 5
0
 public KafkaConsumerService(ILogger <KafkaConsumerService> logger, IConfiguration cfg) : base(logger, cfg)
 {
     _cluster = new ClusterClient(new Configuration
     {
         Seeds = _bootstrapServers
     }, new ConsoleLogger());
 }
Ejemplo n.º 6
0
        public void ClusterClient_must_report_removal_of_a_receptionist()
        {
            Within(TimeSpan.FromSeconds(30), () =>
            {
                RunOn(() =>
                {
                    var unreachableContact = Node(_config.Client) / "system" / "receptionist";
                    var expectedRoles      =
                        ImmutableHashSet.Create(_config.First, _config.Second, _config.Third, _config.Fourth);
                    var expectedContacts = expectedRoles.Select(x => Node(x) / "system" / "receptionist").ToImmutableHashSet();

                    // We need to slow down things otherwise our receptionists can sometimes tell us
                    // that our unreachableContact is unreachable before we get a chance to
                    // subscribe to events.
                    foreach (var role in expectedRoles)
                    {
                        TestConductor.Blackhole(_config.Client, role, ThrottleTransportAdapter.Direction.Both)
                        .Wait();
                    }

                    var c = Sys.ActorOf(
                        ClusterClient.Props(ClusterClientSettings.Create(Sys)
                                            .WithInitialContacts(expectedContacts.Add(unreachableContact))), "client5");

                    var probe = CreateTestProbe();
                    c.Tell(SubscribeContactPoints.Instance, probe.Ref);

                    foreach (var role in expectedRoles)
                    {
                        TestConductor.PassThrough(_config.Client, role, ThrottleTransportAdapter.Direction.Both)
                        .Wait();
                    }

                    probe.FishForMessage(o => (o is ContactPointRemoved cp && cp.ContactPoint.Equals(unreachableContact)), TimeSpan.FromSeconds(10), "removal");
                }, _config.Client);
        public EvrikaPrinterClient(IEvrikaPrinterClientSettings settings, IMasterPortalSettings masterPortalSettings, IPortalSettings portalSettings)
        {
            var provider   = new ApiKeyAuthenticationProvider(portalSettings.ApiKey);
            var authClient = new AuthClient(new ClientSettings(provider, new FakeLog(), TimeSpan.FromSeconds(15), false),
                                            new TopologyProvider(settings.TestAuthUrls.Length > 0 ? settings.TestAuthUrls : portalSettings.AuthUrls));

            var result = authClient.AuthByPassAsync2(new AuthByPassRequest(masterPortalSettings.MasterLogin, masterPortalSettings.MasterPassword)).Result;

            result.EnsureSuccess();
            var authSid = result.Response.Sid;

            Console.WriteLine($"AuthSid: {authSid}");

            clusterClient = new ClusterClient(null, config =>
            {
                var repeatReplicasCount = settings.RepeatReplicasCount;
                config.ClusterProvider  = new FixedClusterProvider(settings.Host);
                config.SetupKonturHttpTransport();
                config.RepeatReplicas(repeatReplicasCount);
                config.ReplicaOrdering        = new AsIsReplicaOrdering();
                config.DefaultRequestStrategy = new ForkingRequestStrategy(new EqualDelaysProvider(repeatReplicasCount), repeatReplicasCount);
                config.AddRequestTransform(new DefaultHeadersTransform(new[]
                {
                    new Header("Authorization", $"auth.sid {authSid}"),
                    new Header("X-Kontur-Apikey", $"{settings.PortalApiKey}"),
                    new Header(HeaderNames.Accept, "application/json"),
                }));
                config.DefaultTimeout = settings.Timeout;
            });
        }
Ejemplo n.º 8
0
        public RaftService(
            ILoggerFactory logger,
            IOptions <ClusterOptions> clusterOptions,
            IOptions <NodeOptions> nodeOptions,
            IClusterConnectionPool clusterConnectionPool,
            INodeStorage <State> nodeStorage,
            IStateMachine <State> stateMachine,
            NodeStateService nodeStateService,
            ClusterClient clusterClient
            ) : base(logger.CreateLogger <RaftService <State> >(), clusterOptions.Value, nodeOptions.Value, stateMachine, nodeStateService)
        {
            _nodeStorage   = nodeStorage;
            _loggerFactory = logger;
            //Bootstrap the node
            _snapshotService = new Snapshotter <State>(logger.CreateLogger <Snapshotter <State> >(), nodeStorage, stateMachine, nodeStateService);

            _bootstrapService      = new Bootstrapper <State>(logger.CreateLogger <Bootstrapper <State> >(), clusterOptions.Value, nodeOptions.Value, nodeStorage, StateMachine, NodeStateService);
            _commitService         = new CommitService <State>(logger.CreateLogger <CommitService <State> >(), clusterOptions.Value, nodeOptions.Value, nodeStorage, StateMachine, NodeStateService);
            _discovery             = new Discovery(logger.CreateLogger <Discovery>());
            _clusterClient         = clusterClient;
            _clusterConnectionPool = clusterConnectionPool;
            NodeStateService.Id    = _nodeStorage.Id;

            _electionTimeoutTimer = new Timer(ElectionTimeoutEventHandler);
            _heartbeatTimer       = new Timer(HeartbeatTimeoutEventHandler);

            if (!ClusterOptions.TestMode)
            {
                _bootstrapTask = Task.Run(async() =>
                {
                    //Wait for the rest of the node to bootup
                    Logger.LogInformation("Starting bootstrap...");
                    Thread.Sleep(3000);
                    nodeStateService.Url            = await _bootstrapService.GetMyUrl(ClusterOptions.GetClusterUrls(), TimeSpan.FromMilliseconds(ClusterOptions.LatencyToleranceMs));
                    NodeStateService.IsBootstrapped = true;
                    SetNodeRole(NodeState.Follower);
                });
            }
            else
            {
                Logger.LogInformation("Running in test mode...");
                SetNodeRole(NodeState.Leader);
                NodeStateService.IsBootstrapped = true;
                Handle(new ExecuteCommands()
                {
                    Commands = new List <BaseCommand>()
                    {
                        {
                            new UpsertNodeInformation()
                            {
                                Id               = NodeStateService.Id,
                                Name             = "",
                                TransportAddress = "https://localhost:5021",
                                IsContactable    = true
                            }
                        }
                    }
                }).GetAwaiter().GetResult();
            }
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Creates a cluster client, that allows to connect to cluster even thou current actor system is not part of it.
 /// </summary>
 static void RunClusterClient(ActorSystem system)
 {
     //NOTE: to properly run cluster client set up actor ref provider for nodes on `provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"`
     system.Settings.InjectTopLevelFallback(ClusterClientReceptionist.DefaultConfig());
     var clusterClient = system.ActorOf(ClusterClient.Props(ClusterClientSettings.Create(system)));
     clusterClient.Tell(new ClusterClient.Send("/user/my-service", new Echo("hello from cluster client")));
 }
Ejemplo n.º 10
0
        public async Task CanUpdated()
        {
            var entity = new WorkflowForm(Guid.NewGuid())
            {
                Name = "Name2"
            };

            UsingDbContext(dbContext => { dbContext.Set <WorkflowForm>().Add(entity); });
            var grain  = ClusterClient.GetGrain <IWorkflowFormGrain <WorkflowFormDto> >(entity.Id);
            var result = await grain.Get();

            result.Name.ShouldBe(entity.Name);
            await grain.Update(new WorkflowFormDto()
            {
                Id   = entity.Id,
                Name = "Name3"
            });

            var updateResult = await grain.Get();

            updateResult.Name.ShouldBe("Name3");
            await Task.Delay(500);

            UsingDbContext(dbContext =>
            {
                dbContext.Set <WorkflowForm>().Any(x => x.Id == entity.Id).ShouldBeTrue();
                var workflowForm = dbContext.Set <WorkflowForm>().First(x => x.Id == entity.Id);
                workflowForm.Name.ShouldBe("Name3");
            });
        }
Ejemplo n.º 11
0
        public StreamApiRequestSender(
            [NotNull] IClusterProvider clusterProvider,
            [NotNull] ILog log,
            [NotNull] BufferPool bufferPool,
            [CanBeNull] ClusterClientSetup additionalSetup)
        {
            this.log        = log;
            this.bufferPool = bufferPool;

            client = ClusterClientFactory.Create(
                clusterProvider,
                log,
                Constants.ServiceNames.StreamApi,
                config =>
            {
                config.SetupUniversalTransport(
                    new UniversalTransportSettings
                {
                    BufferFactory = bufferPool.Rent
                });
                config.AddResponseTransform(TryDecompress);
                additionalSetup?.Invoke(config);
            });

            responseAnalyzer   = new ResponseAnalyzer(ResponseAnalysisContext.Stream);
            compressionEnabled = LZ4Helper.Enabled;
        }
Ejemplo n.º 12
0
        public async Task <ActionResult> SimLogin([FromBody] SimLoginRequestDTO request)
        {
            LoginResponseDTO res = new LoginResponseDTO();

            try
            {
                IPlatformSession session = ClusterClient.GetGrain <IPlatformSession>(request.user_name);
                Account          account = await session.VerifyAccount(Platform.Sim, request.user_name);

                if (account == null)
                {
                    throw new Exception($"VerifyAccount cant found {request.user_name}");
                }

                string access_token = JWT.GetAccessToken(account);
                await session.RefreshToken(access_token);

                res.data   = access_token;
                res.result = LoginResult.Success;
            }
            catch (Exception ex)
            {
                res.result = LoginResult.None;
                res.data   = ex.ToString();
                Logger.LogError(ex.ToString());
            }

            return(Json(res));
        }
Ejemplo n.º 13
0
        static void Main(string[] args)
        {
            var config = ConfigurationFactory.ParseString(File.ReadAllText("App.Akka.conf"));

            //
            // "{app-name} - akka.tcp://{actorysystem-name}@{hostname}:{port}"
            //
            Console.Title = $"{config.GetString("akka.system.app-name")}" +
                            $" - akka.tcp://{config.GetString("akka.system.actorsystem-name")}" +
                            $"@{config.GetString("akka.remote.dot-netty.tcp.hostname")}" +
                            $":{config.GetString("akka.remote.dot-netty.tcp.port")}";

            ActorSystem system = ActorSystem.Create(config.GetString("akka.system.actorsystem-name"), config);

            var cmd = PetabridgeCmd.Get(system);

            cmd.Start();

            //
            // Cluster 접속하기
            //
            system.ActorOf(
                ClusterClient
                .Props(ClusterClientSettings.Create(system)),
                "ClusterClientActor");

            Console.WriteLine();
            Console.WriteLine("ClusterClientApp1 is running...");
            Console.WriteLine();

            Console.ReadLine();
        }
Ejemplo n.º 14
0
 public static async Task StopAsync()
 {
     if (ClusterClient != null)
     {
         await ClusterClient.Close();
     }
 }
Ejemplo n.º 15
0
        public async Task CanDisabled()
        {
            var id    = Guid.NewGuid();
            var grain = ClusterClient.GetGrain <IWorkflowFormGrain <WorkflowFormDto> >(id);
            var dto   = new WorkflowFormDto {
                Id = id, Name = "Name1", Sort = 1
            };
            await grain.Create(dto);

            await grain.Disable(true);

            var result = await grain.Get();

            result.Name.ShouldBe(dto.Name);
            result.Disabled.ShouldBeTrue();
            await Task.Delay(500);

            UsingDbContext(dbContext =>
            {
                dbContext.Set <WorkflowForm>().Any(x => x.Id == id).ShouldBeTrue();
                var workflowForm = dbContext.Set <WorkflowForm>().First(x => x.Id == id);
                workflowForm.Name.ShouldBe(dto.Name);
                workflowForm.Disabled.ShouldBeTrue();
            });
        }
Ejemplo n.º 16
0
        protected override void PreStart()
        {
            _clusterClient = Context.ActorOf(ClusterClient.Props(
                                                 ClusterClientSettings.Create(Context.System).WithInitialContacts(Consts.ContactPoints)));

            Timers.StartPeriodicTimer(TimerName, SendPing.Instance, TimeSpan.FromSeconds(1));
        }
Ejemplo n.º 17
0
        static void Main(string[] args)
        {
            var initialContacts = ImmutableHashSet <ActorPath> .Empty
                                  .Add(ActorPath.Parse("akka.tcp://Cluster@localhost:12000/system/receptionist"));

            //.Add(ActorPath.Parse("akka.tcp://ClusterClientExample@localhost:12001/user/service"));

            using (var system = ActorSystem.Create("ClusterClient"))
            {
                var clusterClientSettings = ClusterClientSettings.Create(system)
                                            .WithInitialContacts(initialContacts);
                // Creaste the Props used to deploy the cluster client on the local actor system

                var clusterClientProps = ClusterClient.Props(clusterClientSettings);
                //Deploy the cluster client into the local actor system
                //Ovaj dio je prebacen u actora kako bi vidjeli da mozemo iz bilo kojeg actora pristupiti nekom clusteru,
                // a ne samo iz actora stvorenih iz system.ActorOf
                //var clusterClient = system.ActorOf(clusterClientProps, "clusterClient");

                //clusterClient.Tell(new ClusterClient.Send("/user/service", new Msg($"Hello from cluster client")));

                var props = Props.Create(() => new ChatActor(clusterClientProps));
                var actor = system.ActorOf(props);

                Console.ReadLine();
                actor.Tell(new Init());

                Console.ReadLine();
                actor.Tell(new InitPub());

                Console.ReadLine();
            }
        }
Ejemplo n.º 18
0
        protected override void PreStart()
        {
            var props = ClusterClient.Props(_clusterClientSettings);

            _clusterClient = Context.ActorOf(props);
            base.PreStart();
        }
        // Put the code that needs to be executed against the silo in this function.
        //
        // As the example shows, you have access to the `ClusterClient` from where grains can be requested.
        //
        // This example shows a single operation on a grain, after which the client application terminates.
        // For long-running clients and other patterns, refer to
        //   https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services
        //
        // The `ClientConfiguration` host tries to reach a silo as specified by the configuration, and
        // retries 9 times with a 10 second wait between each retry until it either reaches the silo, or finally times out.
        //
        // This function will *only* be executed when the silo has been found and the client has connected to it.
        public override async Task ExecuteAsync()
        {
            var(l, r) = (5, 6);
            var adder  = ClusterClient.GetGrain <ICalculatorGrain>(Guid.NewGuid());
            var result = await adder.Add(l, r);

            Console.WriteLine($"{l} + {r} = {result}");
        }
Ejemplo n.º 20
0
 public DemoConsumerService(ILogger <DemoProducerService> logger)
 {
     _logger  = logger;
     _cluster = new ClusterClient(new Configuration
     {
         Seeds = "localhost:9092"
     }, new ConsoleLogger());
 }
Ejemplo n.º 21
0
 public KafkaConsumerHostedService(ILogger <KafkaConsumerHostedService> logger)
 {
     _logger  = logger;
     _cluster = new ClusterClient(new Configuration
     {
         Seeds = "vs-dc1-mb-ks01.net.berg.ru:9092"
     }, new ConsoleLogger());
 }
Ejemplo n.º 22
0
 public KafkaConsumerHostedService(ILogger <KafkaConsumerHostedService> logger)
 {
     _logger  = logger;
     _cluster = new ClusterClient(new Configuration
     {
         Seeds = "localhost:9092"
     }, new ConsoleLogger());
 }
Ejemplo n.º 23
0
        /// <summary>
        /// Initializes the client's ID and username.
        /// If the client is a Cluster, the username is the key.
        ///
        /// TODO: Change to the cluster config name in the future.
        /// </summary>
        /// <param name="client">The client whose ID and username should be changed.</param>
        /// <param name="packet">The packet containing the new client ID.</param>
        internal static void InitializeCluster(this ClusterClient client, Packet packet)
        {
            string keyName = packet.ReadString();

            client.name = keyName;

            BaseClient.DebugClient(client.id, $"Welcome, {keyName}!");
        }
Ejemplo n.º 24
0
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Disconnecting...");

            await ClusterClient.Close();

            _logger.LogInformation("Disconnected.");
        }
Ejemplo n.º 25
0
 public static ClusterClient UseRedisClusterProvider(this ClusterClient host, Action <RedisOptions> configuration)
 {
     return(host.ConfigureServices(services =>
     {
         var options = new RedisOptions();
         configuration?.Invoke(options);
         services.AddSingleton(options).AddRedis();
     }));
 }
Ejemplo n.º 26
0
        /// <summary>
        /// Reads a keyName and passphrase from the server and attempts to answer it.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="packet"></param>
        internal static void Passphrase(this ClusterClient client, Packet packet)
        {
            string keyName = packet.ReadString();

            byte[] cypher = Convert.FromBase64String(packet.ReadString());
            byte[] iv     = Convert.FromBase64String(packet.ReadString());

            client.AnswerPassphrase(AESManager.Decrypt(keyName, cypher, iv));
        }
Ejemplo n.º 27
0
 public ReutersLinkFinder()
 {
     serializer    = new Serializer();
     clusterClient = new ClusterClient(new ConsoleLog(), configuration =>
     {
         configuration.SetupUniversalTransport();
         configuration.ClusterProvider = new FixedClusterProvider(Url);
     });
 }
Ejemplo n.º 28
0
        /// <summary>
        /// Sends a packet to the master server that requests a string of text that must be
        /// decrypted and sent back.
        /// </summary>
        /// <param name="client">The Cluster Client to run this from.</param>
        /// <param name="keyName">The name of the SSH key stored on the master server. These are
        /// preloaded so there's no need to sanitize directory requests.</param>
        internal static void ValidateCluster(this ClusterClient client, string keyName)
        {
            using (Packet packet = new Packet((int)ClientPackets.validateCluster))
            {
                packet.Write(keyName);

                client.SendTcpData(packet);
            }
        }
Ejemplo n.º 29
0
        //[MultiNodeFact(Skip = "TODO")]
        public void ClusterClient_should_reestablish_connection_to_another_receptionist_when_server_is_shutdown()
        {
            ClusterClient_should_demonstrate_usage();

            Within(TimeSpan.FromSeconds(30), () =>
            {
                RunOn(() =>
                {
                    var service2 = Sys.ActorOf(Props.Create(() => new TestService(TestActor)), "service2");
                    ClusterClientReceptionist.Get(Sys).RegisterService(service2);
                    AwaitCount(8);
                }, _first, _second, _third, _fourth);
                EnterBarrier("service2-replicated");

                RunOn(() =>
                {
                    var c = Sys.ActorOf(ClusterClient.Props(ClusterClientSettings.Create(Sys).WithInitialContacts(InitialContacts)), "client2");
                    c.Tell(new ClusterClient.Send("/user/service2", "bonjour", localAffinity: true));
                    ExpectMsg("bonjour-ack");
                    var lastSenderAddress = LastSender.Path.Address;

                    var receptionistRoleName = RoleName(lastSenderAddress);
                    if (receptionistRoleName == null)
                    {
                        throw new Exception("Unexpected missing role name: " + lastSenderAddress);
                    }

                    TestConductor.Exit(receptionistRoleName, 0).Wait();
                    _remainingServerRoleNames.Remove(receptionistRoleName);

                    Within(Remaining - TimeSpan.FromSeconds(3), () =>
                    {
                        AwaitAssert(() =>
                        {
                            c.Tell(new ClusterClient.Send("/user/service2", "hi again", localAffinity: true));
                            ExpectMsg("hi again-ack", TimeSpan.FromSeconds(1));
                        });
                    });
                    Sys.Stop(c);
                }, _client);
                EnterBarrier("verified-3");

                ReceiveWhile(TimeSpan.FromSeconds(2), msg =>
                {
                    if (msg.Equals("hi again"))
                    {
                        return(msg);
                    }
                    else
                    {
                        throw new Exception("unexpected message: " + msg);
                    }
                });
                EnterBarrier("after-4");
            });
        }
Ejemplo n.º 30
0
        public async Task <ActionResult <int> > Increment(Increment increment)
        {
            //This logging is here to demonstrate it can be read in the tests.
            Logger.LogInformation(Events.TestEvent.Id, Events.TestEvent.FormatString, increment);

            var testStateGrain = ClusterClient.GetGrain <ITestStateGrain>(increment.GrainId);
            var currentState   = await testStateGrain.Increment(increment.IncrementBy).ConfigureAwait(false);

            return(Ok(currentState));
        }