private static Operation <Deployment, CreateDeploymentMetadata> CreateSimPlayerDeploymentAsync(DeploymentServiceClient deploymentServiceClient,
                                                                                                       string projectName, string assemblyName, string runtimeVersion, string mainDeploymentName, string simDeploymentName,
                                                                                                       string simDeploymentJsonPath, string simDeploymentSnapshotPath, string regionCode, string clusterCode, int numSimPlayers, bool useChinaPlatform)
        {
            var snapshotServiceClient = SnapshotServiceClient.Create(GetApiEndpoint(useChinaPlatform), GetPlatformRefreshTokenCredential(useChinaPlatform));

            // Upload snapshots.
            var simDeploymentSnapshotId = UploadSnapshot(snapshotServiceClient, simDeploymentSnapshotPath, projectName,
                                                         simDeploymentName, useChinaPlatform);

            if (simDeploymentSnapshotId.Length == 0)
            {
                throw new Exception("Error while uploading sim player snapshot.");
            }

            var playerAuthServiceClient = PlayerAuthServiceClient.Create(GetApiEndpoint(useChinaPlatform), GetPlatformRefreshTokenCredential(useChinaPlatform));

            // Create development authentication token used by the simulated players.
            var dat = playerAuthServiceClient.CreateDevelopmentAuthenticationToken(
                new CreateDevelopmentAuthenticationTokenRequest
            {
                Description = "DAT for simulated player deployment.",
                Lifetime    = Duration.FromTimeSpan(new TimeSpan(7, 0, 0, 0)),
                ProjectName = projectName
            });

            // Add worker flags to sim deployment JSON.
            var devAuthTokenFlag = new JObject();

            devAuthTokenFlag.Add("name", "simulated_players_dev_auth_token");
            devAuthTokenFlag.Add("value", dat.TokenSecret);

            var targetDeploymentFlag = new JObject();

            targetDeploymentFlag.Add("name", "simulated_players_target_deployment");
            targetDeploymentFlag.Add("value", mainDeploymentName);

            var numSimulatedPlayersFlag = new JObject();

            numSimulatedPlayersFlag.Add("name", "total_num_simulated_players");
            numSimulatedPlayersFlag.Add("value", $"{numSimPlayers}");

            var     simDeploymentConfigJson = File.ReadAllText(simDeploymentJsonPath);
            dynamic simDeploymentConfig     = JObject.Parse(simDeploymentConfigJson);

            if (simDeploymentJsonPath.EndsWith(".pb.json"))
            {
                for (var i = 0; i < simDeploymentConfig.worker_flagz.Count; ++i)
                {
                    if (simDeploymentConfig.worker_flagz[i].worker_type == CoordinatorWorkerName)
                    {
                        simDeploymentConfig.worker_flagz[i].flagz.Add(devAuthTokenFlag);
                        simDeploymentConfig.worker_flagz[i].flagz.Add(targetDeploymentFlag);
                        simDeploymentConfig.worker_flagz[i].flagz.Add(numSimulatedPlayersFlag);
                        break;
                    }
                }

                for (var i = 0; i < simDeploymentConfig.flagz.Count; ++i)
                {
                    if (simDeploymentConfig.flagz[i].name == "loadbalancer_v2_config_json")
                    {
                        string  layerConfigJson       = simDeploymentConfig.flagz[i].value;
                        dynamic loadBalanceConfig     = JObject.Parse(layerConfigJson);
                        var     lbLayerConfigurations = loadBalanceConfig.layerConfigurations;
                        for (var j = 0; j < lbLayerConfigurations.Count; ++j)
                        {
                            if (lbLayerConfigurations[j].layer == CoordinatorWorkerName)
                            {
                                var rectangleGrid = lbLayerConfigurations[j].rectangleGrid;
                                rectangleGrid.cols = numSimPlayers;
                                rectangleGrid.rows = 1;
                                break;
                            }
                        }
                        simDeploymentConfig.flagz[i].value = Newtonsoft.Json.JsonConvert.SerializeObject(loadBalanceConfig);
                        break;
                    }
                }
            }
            else // regular non pb.json
            {
                for (var i = 0; i < simDeploymentConfig.workers.Count; ++i)
                {
                    if (simDeploymentConfig.workers[i].worker_type == CoordinatorWorkerName)
                    {
                        simDeploymentConfig.workers[i].flags.Add(devAuthTokenFlag);
                        simDeploymentConfig.workers[i].flags.Add(targetDeploymentFlag);
                        simDeploymentConfig.workers[i].flags.Add(numSimulatedPlayersFlag);
                    }
                }

                // Specify the number of managed coordinator workers to start by editing
                // the load balancing options in the launch config. It creates a rectangular
                // launch config of N cols X 1 row, N being the number of coordinators
                // to create.
                // This assumes the launch config contains a rectangular load balancing
                // layer configuration already for the coordinator worker.
                var lbLayerConfigurations = simDeploymentConfig.load_balancing.layer_configurations;
                for (var i = 0; i < lbLayerConfigurations.Count; ++i)
                {
                    if (lbLayerConfigurations[i].layer == CoordinatorWorkerName)
                    {
                        var rectangleGrid = lbLayerConfigurations[i].rectangle_grid;
                        rectangleGrid.cols = numSimPlayers;
                        rectangleGrid.rows = 1;
                    }
                }
            }

            // Create simulated player deployment.
            var simDeployment = new Deployment
            {
                AssemblyId   = assemblyName,
                LaunchConfig = new LaunchConfig
                {
                    ConfigJson = simDeploymentConfig.ToString()
                },
                Name               = simDeploymentName,
                ProjectName        = projectName,
                RuntimeVersion     = runtimeVersion,
                StartingSnapshotId = simDeploymentSnapshotId,
            };

            if (!String.IsNullOrEmpty(clusterCode))
            {
                simDeployment.ClusterCode = clusterCode;
            }
            else
            {
                simDeployment.RegionCode = regionCode;
            }

            simDeployment.Tag.Add(DEPLOYMENT_LAUNCHED_BY_LAUNCHER_TAG);
            simDeployment.Tag.Add(SIM_PLAYER_DEPLOYMENT_TAG);

            Console.WriteLine(
                $"Creating the simulated player deployment {simDeploymentName} in project {projectName} with {numSimPlayers} simulated players. Link: https://console.improbable.io/projects/{projectName}/deployments/{simDeploymentName}/overview");

            var simDeploymentCreateOp = deploymentServiceClient.CreateDeployment(new CreateDeploymentRequest
            {
                Deployment = simDeployment
            });

            return(simDeploymentCreateOp);
        }
Beispiel #2
0
        public static void Main(string[] args)
        {
            // See https://support.microsoft.com/en-gb/help/821268/contention-poor-performance-and-deadlocks-when-you-make-calls-to-web-s
            // Experimentation shows we need the ThreadPool to always spin up threads for good performance under load
            ThreadPool.GetMaxThreads(out var workerThreads, out var ioThreads);
            ThreadPool.SetMinThreads(workerThreads, ioThreads);

            Parser.Default.ParseArguments <PartyServerCommandLineArgs>(args)
            .WithParsed(parsedArgs =>
            {
                parsedArgs.Validate();

                var spatialRefreshToken = Secrets.GetEnvSecret(SpatialRefreshTokenEnvironmentVariable);

                PartyDataModel.Defaults.MinMembers = (uint)parsedArgs.DefaultMinMembers;
                PartyDataModel.Defaults.MaxMembers = (uint)parsedArgs.DefaultMaxMembers;

                Log.Logger = new LoggerConfiguration()
                             .WriteTo.Console(new RenderedCompactJsonFormatter())
                             .Enrich.FromLogContext()
                             .CreateLogger();

                IAnalyticsSender analyticsSender = new AnalyticsSenderBuilder("gateway_party")
                                                   .WithCommandLineArgs(parsedArgs)
                                                   .With(new LogExceptionStrategy(Log.Logger))
                                                   .Build();

                using (var server = GrpcBaseServer.Build(parsedArgs))
                    using (var memoryStoreManager = new RedisClientManager(parsedArgs.RedisConnectionString))
                    {
                        Log.Information($"Successfully connected to Redis at {parsedArgs.RedisConnectionString}");
                        server.AddInterceptor(new PlayerIdentityTokenValidatingInterceptor(
                                                  PlayerAuthServiceClient.Create(/*put my auth server address here*/ credentials: new PlatformRefreshTokenCredential(spatialRefreshToken)),
                                                  memoryStoreManager.GetRawClient(Database.CACHE)
                                                  ))
                        .AddInterceptor(new ExceptionMappingInterceptor(new Dictionary <Type, StatusCode>
                        {
                            { typeof(EntryNotFoundException), StatusCode.NotFound },
                            { typeof(EntryAlreadyExistsException), StatusCode.AlreadyExists },
                            { typeof(TransactionAbortedException), StatusCode.Unavailable }
                        }));
                        server.AddService(
                            PartyService.BindService(new PartyServiceImpl(memoryStoreManager, analyticsSender)));
                        server.AddService(
                            InviteService.BindService(new InviteServiceImpl(memoryStoreManager, analyticsSender)));
                        var serverTask = Task.Run(() => server.Start());
                        var signalTask = Task.Run(() => UnixSignal.WaitAny(new[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM) }));
                        Task.WaitAny(serverTask, signalTask);

                        if (signalTask.IsCompleted)
                        {
                            Log.Information($"Received UNIX signal {signalTask.Result}");
                            Log.Information("Server shutting down...");
                            server.Shutdown();
                            serverTask.Wait();
                            Log.Information("Server stopped cleanly");
                        }
                        else
                        {
                            /* The server task has completed; we can just exit. */
                            Log.Information("The Party server has stopped itself or encountered an unhandled exception.");
                        }
                    }
            });
        }
Beispiel #3
0
        private static Operation <Deployment, CreateDeploymentMetadata> CreateSimPlayerDeploymentAsync(DeploymentServiceClient deploymentServiceClient,
                                                                                                       string projectName, string assemblyName, string mainDeploymentName, string simDeploymentName, string simDeploymentJsonPath, string regionCode, int simNumPlayers)
        {
            var playerAuthServiceClient = PlayerAuthServiceClient.Create();

            // Create development authentication token used by the simulated players.
            var dat = playerAuthServiceClient.CreateDevelopmentAuthenticationToken(
                new CreateDevelopmentAuthenticationTokenRequest
            {
                Description = "DAT for simulated player deployment.",
                Lifetime    = Duration.FromTimeSpan(new TimeSpan(7, 0, 0, 0)),
                ProjectName = projectName
            });

            // Add worker flags to sim deployment JSON.
            var devAuthTokenFlag = new JObject();

            devAuthTokenFlag.Add("name", "simulated_players_dev_auth_token");
            devAuthTokenFlag.Add("value", dat.TokenSecret);

            var targetDeploymentFlag = new JObject();

            targetDeploymentFlag.Add("name", "simulated_players_target_deployment");
            targetDeploymentFlag.Add("value", mainDeploymentName);

            var numSimulatedPlayersFlag = new JObject();

            numSimulatedPlayersFlag.Add("name", "total_num_simulated_players");
            numSimulatedPlayersFlag.Add("value", $"{simNumPlayers}");

            var     simWorkerConfigJson = File.ReadAllText(simDeploymentJsonPath);
            dynamic simWorkerConfig     = JObject.Parse(simWorkerConfigJson);

            for (var i = 0; i < simWorkerConfig.workers.Count; ++i)
            {
                if (simWorkerConfig.workers[i].worker_type == CoordinatorWorkerName)
                {
                    simWorkerConfig.workers[i].flags.Add(devAuthTokenFlag);
                    simWorkerConfig.workers[i].flags.Add(targetDeploymentFlag);
                    simWorkerConfig.workers[i].flags.Add(numSimulatedPlayersFlag);
                }
            }

            // Specify the number of managed coordinator workers to start by editing
            // the load balancing options in the launch config. It creates a rectangular
            // launch config of N cols X 1 row, N being the number of coordinators
            // to create.
            // This assumes the launch config contains a rectangular load balancing
            // layer configuration already for the coordinator worker.
            var lbLayerConfigurations = simWorkerConfig.load_balancing.layer_configurations;

            for (var i = 0; i < lbLayerConfigurations.Count; ++i)
            {
                if (lbLayerConfigurations[i].layer == CoordinatorWorkerName)
                {
                    var rectangleGrid = lbLayerConfigurations[i].rectangle_grid;
                    rectangleGrid.cols = simNumPlayers;
                    rectangleGrid.rows = 1;
                }
            }

            simWorkerConfigJson = simWorkerConfig.ToString();

            // Create simulated player deployment.
            var simDeploymentConfig = new Deployment
            {
                AssemblyId   = assemblyName,
                LaunchConfig = new LaunchConfig
                {
                    ConfigJson = simWorkerConfigJson
                },
                Name        = simDeploymentName,
                ProjectName = projectName,
                RegionCode  = regionCode
                              // No snapshot included for the simulated player deployment
            };

            simDeploymentConfig.Tag.Add(DEPLOYMENT_LAUNCHED_BY_LAUNCHER_TAG);
            simDeploymentConfig.Tag.Add(SIM_PLAYER_DEPLOYMENT_TAG);

            Console.WriteLine(
                $"Creating the simulated player deployment {simDeploymentName} in project {projectName} with {simNumPlayers} simulated players. Link: https://console.improbable.io/projects/{projectName}/deployments/{simDeploymentName}/overview");

            var simDeploymentCreateOp = deploymentServiceClient.CreateDeployment(new CreateDeploymentRequest
            {
                Deployment = simDeploymentConfig
            });

            return(simDeploymentCreateOp);
        }
        public static void Init(string token)
        {
            var credentials = new PlatformRefreshTokenCredential(token);

            PlayerAuthServiceClient = PlayerAuthServiceClient.Create(credentials: credentials);
        }