Пример #1
0
        public Task Heartbeat(byte[] data)
        {
            HeartbeatData heartbeatData = HeartbeatDataDotNetSerializer.Deserialize(data);
            IGameGrain    game          = GrainFactory.GetGrain <IGameGrain>(heartbeatData.Game);

            return(game.UpdateGameStatus(heartbeatData.Status));
        }
Пример #2
0
    public Task HeartbeatAsync(byte[] data)
    {
        var heartbeatData = HeartbeatDataDotNetSerializer.Deserialize(data);
        var game          = GrainFactory.GetGrain <IGameGrain>(heartbeatData.GameKey);

        return(game.UpdateGameStatusAsync(heartbeatData.Status));
    }
Пример #3
0
        /// <summary>
        /// Simulates periodic updates for a bunch of games similar to what game consoles of mobile apps do.
        /// </summary>
        static void Main(string[] args)
        {
            try
            {
                GrainClient.Initialize();

                int      nGames          = 10;                      // number of games to simulate
                int      nPlayersPerGame = 4;                       // number of players in each game
                TimeSpan sendInterval    = TimeSpan.FromSeconds(2); // interval for sending updates
                int      nIterations     = 100;

                // Precreate base heartbeat data objects for each of the games.
                // We'll modify them before every time before sending.
                HeartbeatData[] heartbeats = new HeartbeatData[nGames];
                for (int i = 0; i < nGames; i++)
                {
                    heartbeats[i]      = new HeartbeatData();
                    heartbeats[i].Game = Guid.NewGuid();
                    for (int j = 0; j < nPlayersPerGame; j++)
                    {
                        heartbeats[i].Status.Players.Add(GetPlayerId(i * nPlayersPerGame + j));
                    }
                }

                int            iteration = 0;
                IPresenceGrain presence  = PresenceGrainFactory.GetGrain(0); // PresenceGrain is a StatelessWorker, so we use a single grain ID for auto-scale
                List <Task>    promises  = new List <Task>();

                while (iteration++ < nIterations)
                {
                    Console.WriteLine("Sending heartbeat series #{0}", iteration);

                    promises.Clear();

                    try
                    {
                        for (int i = 0; i < nGames; i++)
                        {
                            heartbeats[i].Status.Score = String.Format("{0}:{1}", iteration, iteration > 5 ? iteration - 5 : 0); // Simultate a meaningful game score

                            // We serialize the HeartbeatData object to a byte[] only to simulate the real life scenario where data comes in
                            // as a binary blob and requires an initial processing before it can be routed to the proper destination.
                            // We could have sent the HeartbeatData object directly to the game grain because we know the game ID.
                            // For the sake of simulation we just pretend we don't.
                            Task t = presence.Heartbeat(HeartbeatDataDotNetSerializer.Serialize(heartbeats[i]));

                            promises.Add(t);
                        }

                        // Wait for all calls to finish.
                        // It is okay to block the thread here because it's a client program with no parallelism.
                        // One should never block a thread in grain code.
                        Task.WaitAll(promises.ToArray());
                    }
                    catch (Exception exc)
                    {
                        Console.WriteLine("Exception: {0}", exc.GetBaseException());
                    }

                    Thread.Sleep(sendInterval);
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine("Unexpected Error: {0}", exc.GetBaseException());
            }
        }
        private async Task RunAsync()
        {
            // number of games to simulate
            var nGames = 10;

            // number of players in each game
            var nPlayersPerGame = 4;

            // interval for sending updates
            var sendInterval = TimeSpan.FromSeconds(2);

            // number of updates to send
            var nIterations = 100;

            // Precreate base heartbeat data objects for each of the games.
            // We'll modify them before every time before sending.
            var heartbeats = new HeartbeatData[nGames];

            for (var i = 0; i < nGames; i++)
            {
                heartbeats[i] = new HeartbeatData(
                    Guid.NewGuid(),
                    new GameStatus(
                        Enumerable.Range(0, nPlayersPerGame).Select(j => GetPlayerId(i * nPlayersPerGame + j)).ToImmutableHashSet(),
                        string.Empty));
            }

            var iteration = 0;

            // PresenceGrain is a StatelessWorker, so we use a single grain ID for auto-scale
            var presence = _client.GetGrain <IPresenceGrain>(0);
            var promises = new Task[nGames];

            while (++iteration < nIterations)
            {
                _logger.LogInformation("Sending heartbeat series #{@Iteration}", iteration);

                try
                {
                    for (var i = 0; i < nGames; i++)
                    {
                        // Simultate a meaningful game score
                        heartbeats[i] = heartbeats[i].WithNewScore($"{iteration}:{(iteration > 5 ? iteration - 5 : 0)}");

                        // We serialize the HeartbeatData object to a byte[] only to simulate the real life scenario where data comes in
                        // as a binary blob and requires an initial processing before it can be routed to the proper destination.
                        // We could have sent the HeartbeatData object directly to the game grain because we know the game ID.
                        // For the sake of simulation we just pretend we don't.
                        promises[i] = presence.HeartbeatAsync(HeartbeatDataDotNetSerializer.Serialize(heartbeats[i]));
                    }

                    // Wait for all calls to finish.
                    await Task.WhenAll(promises);

                    // check for cancellation request
                    if (_executionCancellation.IsCancellationRequested)
                    {
                        return;
                    }
                }
                catch (Exception error)
                {
                    _logger.LogError(error, "Error while sending hearbeats to Orleans cluster");
                }

                try
                {
                    await Task.Delay(sendInterval, _executionCancellation.Token);
                }
                catch (OperationCanceledException)
                {
                    return;
                }
            }
        }
Пример #5
0
        private static async Task RunAsync(string[] args, CancellationToken token)
        {
            // build the orleans client
            var client = new ClientBuilder()
                         .UseLocalhostClustering()
                         .ConfigureLogging(_ =>
            {
                _.AddConsole();
            })
                         .Build();

            // keep a logger for general use
            var logger = client.ServiceProvider.GetService <ILogger <Program> >();

            // connect to the orleans cluster
            var attempt     = 0;
            var maxAttempts = 100;
            var delay       = TimeSpan.FromSeconds(1);
            await client.Connect(async error =>
            {
                if (++attempt < maxAttempts)
                {
                    logger.LogWarning(error,
                                      "Failed to connect to Orleans cluster on attempt {@Attempt} of {@MaxAttempts}.",
                                      attempt, maxAttempts);

                    await Task.Delay(delay, token);

                    return(true);
                }
                else
                {
                    logger.LogError(error,
                                    "Failed to connect to Orleans cluster on attempt {@Attempt} of {@MaxAttempts}.",
                                    attempt, maxAttempts);

                    return(false);
                }
            });

            // number of games to simulate
            var nGames = 10;

            // number of players in each game
            var nPlayersPerGame = 4;

            // interval for sending updates
            var sendInterval = TimeSpan.FromSeconds(2);

            // number of updates to send
            var nIterations = 100;

            // Precreate base heartbeat data objects for each of the games.
            // We'll modify them before every time before sending.
            var heartbeats = new HeartbeatData[nGames];

            for (var i = 0; i < nGames; i++)
            {
                heartbeats[i] = new HeartbeatData(
                    Guid.NewGuid(),
                    new GameStatus(
                        Enumerable.Range(0, nPlayersPerGame).Select(j => GetPlayerId(i * nPlayersPerGame + j)).ToImmutableHashSet(),
                        string.Empty));
            }

            var iteration = 0;

            // PresenceGrain is a StatelessWorker, so we use a single grain ID for auto-scale
            var presence = client.GetGrain <IPresenceGrain>(0);
            var promises = new Task[nGames];

            while (++iteration < nIterations)
            {
                logger.LogInformation("Sending heartbeat series #{@Iteration}", iteration);

                try
                {
                    for (var i = 0; i < nGames; i++)
                    {
                        // Simultate a meaningful game score
                        heartbeats[i] = heartbeats[i].WithNewScore($"{iteration}:{(iteration > 5 ? iteration - 5 : 0)}");

                        // We serialize the HeartbeatData object to a byte[] only to simulate the real life scenario where data comes in
                        // as a binary blob and requires an initial processing before it can be routed to the proper destination.
                        // We could have sent the HeartbeatData object directly to the game grain because we know the game ID.
                        // For the sake of simulation we just pretend we don't.
                        promises[i] = presence.HeartbeatAsync(HeartbeatDataDotNetSerializer.Serialize(heartbeats[i]));
                    }

                    // Wait for all calls to finish.
                    await Task.WhenAll(promises);
                }
                catch (Exception error)
                {
                    logger.LogError(error, "Error while sending hearbeats to Orleans cluster");
                }

                await Task.Delay(sendInterval, token);
            }
        }