static void Main(string[] args) { Log.Logger = new LoggerConfiguration() .WriteTo.Console(new RenderedCompactJsonFormatter()) .Enrich.FromLogContext() .CreateLogger(); // See https://support.microsoft.com/en-gb/help/821268/contention-poor-performance-and-deadlocks-when-you-make-calls-to-web-s ThreadPool.SetMaxThreads(100, 100); ThreadPool.SetMinThreads(50, 50); Parser.Default.ParseArguments <DeploymentPoolArgs>(args) .WithParsed(parsedArgs => { parsedArgs.Validate(); var spatialRefreshToken = Environment.GetEnvironmentVariable(SpatialRefreshTokenEnvironmentVariable) ?? throw new Exception( $"{SpatialRefreshTokenEnvironmentVariable} environment variable is required."); if (spatialRefreshToken == "") { throw new ArgumentException("Refresh token should not be empty"); } IAnalyticsSender analyticsSender = new AnalyticsSenderBuilder("deployment_pool") .WithCommandLineArgs(parsedArgs) .With(new LogExceptionStrategy(Log.Logger)) .Build(); var spatialDeploymentClient = DeploymentServiceClient.Create(credentials: new PlatformRefreshTokenCredential(spatialRefreshToken)); var spatialSnapshotClient = SnapshotServiceClient.Create(credentials: new PlatformRefreshTokenCredential(spatialRefreshToken)); var platformInvoker = new PlatformInvoker(parsedArgs, spatialDeploymentClient, spatialSnapshotClient, analyticsSender); var cancelTokenSource = new CancellationTokenSource(); var cancelToken = cancelTokenSource.Token; var metricsServer = new MetricServer(parsedArgs.MetricsPort).Start(); var dplPool = new DeploymentPool(parsedArgs, spatialDeploymentClient, platformInvoker, cancelToken, analyticsSender); var dplPoolTask = Task.Run(() => dplPool.Start()); var unixSignalTask = Task.Run(() => UnixSignal.WaitAny(new[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM) })); Task.WaitAny(dplPoolTask, unixSignalTask); if (unixSignalTask.IsCompleted) { Log.Information($"Received UNIX signal {unixSignalTask.Result}"); Log.Information("Server shutting down..."); cancelTokenSource.Cancel(); metricsServer.StopAsync(); dplPoolTask.Wait(); Log.Information("Server stopped cleanly"); } else { /* The server task has completed; we can just exit. */ Log.Information($"The deployment pool has stopped itself or encountered an unhandled exception {dplPoolTask.Exception}"); } }); }
public async Task CallIntoExceptionStrategyWhenHttpRequestFails() { Mock <IDispatchExceptionStrategy> strategyMock = new Mock <IDispatchExceptionStrategy>(); HttpRequestException exception = new HttpRequestException(); Mock <HttpMessageHandler> httpReqHandlerMock = new Mock <HttpMessageHandler>(); httpReqHandlerMock.Protected() .Setup <Task <HttpResponseMessage> >( "SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>() ) .Throws(exception) .Verifiable(); using (var sender = new AnalyticsSenderBuilder(AnalyticsEnvironment.Testing, KeyVal, SourceVal) .WithMaxQueueSize(1) .WithCommandLineArgs($"--{AnalyticsCommandLineArgs.EndpointName}", "https://example.com/") .With(strategyMock.Object) .With(new HttpClient(httpReqHandlerMock.Object)) .Build()) { await sender.SendAsync(ClassVal, TypeVal, new Dictionary <string, string>()); strategyMock.Verify(s => s.ProcessException(exception), Times.Once()); } }
public async Task SendAnalyticEventsToHttpsEndpoint() { var client = new HttpClient(_messageHandlerMock.Object); using (var sender = new AnalyticsSenderBuilder(AnalyticsEnvironment.Testing, KeyVal, SourceVal) .WithCommandLineArgs($"--{AnalyticsCommandLineArgs.EndpointName}", "https://example.com/") .WithMaxQueueTime(TimeSpan.FromMilliseconds(5)) .With(client) .Build()) { await sender.SendAsync(ClassVal, TypeVal, new Dictionary <string, object> { { "dogs", "excellent" }, { "animals", new Dictionary <string, List <string> > { { "mammals", new List <string> { "dolphins", "cats" } }, { "lizards", new List <string> { "iguanas", "chameleons" } } } } }, "12345678"); await Task.Delay(TimeSpan.FromMilliseconds(20)); _messageHandlerMock.Protected().Verify("SendAsync", Times.Exactly(1), ItExpr.Is <HttpRequestMessage>(req => SendAnalyticEventsToHttpsEndpointExpectedMessage(req)), ItExpr.IsAny <CancellationToken>()); } }
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 <PlayFabAuthArguments>(args) .WithParsed(parsedArgs => { Log.Logger = new LoggerConfiguration() .WriteTo.Console(new RenderedCompactJsonFormatter()) .Enrich.FromLogContext() .CreateLogger(); //spatial service account token i set up and entered into kubernets var spatialRefreshToken = Secrets.GetEnvSecret(SpatialRefreshTokenEnvironmentVariable).Trim(); var playfabDeveloperKey = Secrets.GetEnvSecret(PlayFabSecretKeyEnvironmentVariable).Trim(); PlayFabSettings.DeveloperSecretKey = playfabDeveloperKey; PlayFabSettings.TitleId = parsedArgs.PlayFabTitleId; IAnalyticsSender analyticsSender = new AnalyticsSenderBuilder("playfab_auth") .WithCommandLineArgs(parsedArgs) .With(new LogExceptionStrategy(Log.Logger)) .Build(); var server = GrpcBaseServer.Build(parsedArgs); server.AddService(AuthService.BindService( new PlayFabAuthImpl( parsedArgs.SpatialProject, PlayerAuthServiceClient.Create( /*endpoint: new PlatformApiEndpoint("playerauth.api.improbable.io", 443),*/ credentials: new PlatformRefreshTokenCredential(spatialRefreshToken)), analyticsSender) )); var serverTask = Task.Run(() => server.Start()); var signalTask = Task.Run(() => UnixSignal.WaitAny(new[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM) })); Log.Information("PlayFab authentication server started up"); 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 PlayFab authentication server has stopped itself or encountered an unhandled exception."); } Environment.Exit(0); }); }
public void BuildRealAnalyticsSenderIfProvidedWithEndpoint() { using (var analyticsSender = new AnalyticsSenderBuilder(AnalyticsEnvironment.Testing, KeyVal, SourceVal) .WithCommandLineArgs($"--{AnalyticsCommandLineArgs.EndpointName}", "https://example.com/") .Build()) { Assert.IsInstanceOf <AnalyticsSender>(analyticsSender); } }
static void Main(string[] args) { Log.Logger = new LoggerConfiguration() .WriteTo.Console(new RenderedCompactJsonFormatter()) .Enrich.FromLogContext() .CreateLogger(); // 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 <GatewayArgs>(args) .WithParsed(parsedArgs => { var spatialRefreshToken = Secrets.GetEnvSecret(SpatialRefreshTokenEnvironmentVariable); var memoryStoreClientManager = new RedisClientManager(parsedArgs.RedisConnectionString); var playerAuthClient = PlayerAuthServiceClient.Create( credentials: new PlatformRefreshTokenCredential(spatialRefreshToken)); IAnalyticsSender analyticsSender = new AnalyticsSenderBuilder("gateway_gateway") .WithCommandLineArgs(parsedArgs) .With(new LogExceptionStrategy(Log.Logger)) .Build(); var server = GrpcBaseServer.Build(parsedArgs); server.AddInterceptor(new PlayerIdentityTokenValidatingInterceptor( playerAuthClient, memoryStoreClientManager.GetRawClient(Database.CACHE))); server.AddService( GatewayService.BindService(new GatewayServiceImpl(memoryStoreClientManager, playerAuthClient, 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 Gateway server has stopped itself or encountered an unhandled exception."); } }); }
public void AllowsHttpIfInsecureEndpointsEnabled() { using (var sender = new AnalyticsSenderBuilder(AnalyticsEnvironment.Testing, KeyVal, SourceVal) .WithCommandLineArgs( $"--{AnalyticsCommandLineArgs.EndpointName}", "http://example.com/", $"--{AnalyticsCommandLineArgs.AllowInsecureEndpointName}" ) .Build()) { Assert.IsInstanceOf <AnalyticsSender>(sender); } }
static void Main(string[] args) { Log.Logger = new LoggerConfiguration() .WriteTo.Console(new RenderedCompactJsonFormatter()) .Enrich.FromLogContext() .CreateLogger(); Parser.Default.ParseArguments <MatcherArgs>(args) .WithParsed(parsedArgs => { IAnalyticsSender analyticsSender = new AnalyticsSenderBuilder("gateway_matcher") .WithCommandLineArgs(parsedArgs) .With(new LogExceptionStrategy(Log.Logger)) .Build(); var matcher = new Matcher(analyticsSender); var matcherTask = new Task(() => { matcher.Start(); }); var unixSignalTask = new Task <int>(() => { return(UnixSignal.WaitAny(new[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM) })); }); matcherTask.Start(); Console.WriteLine("Matcher started up"); unixSignalTask.Start(); Task.WaitAny(matcherTask, unixSignalTask); if (unixSignalTask.IsCompleted) { Console.WriteLine($"Received UNIX signal {unixSignalTask.Result}"); Console.WriteLine("Matcher shutting down..."); matcher.Stop(); matcherTask.Wait(TimeSpan.FromSeconds(10)); Console.WriteLine("Matcher stopped cleanly"); } else { /* The matcher task has completed; we can just exit. */ Console.WriteLine("The matcher has stopped itself or encountered an unhandled exception."); } Environment.Exit(0); }); }
public async Task NotDispatchAnalyticsEventsWithoutTime() { var client = new HttpClient(_messageHandlerMock.Object); using (var sender = new AnalyticsSenderBuilder(AnalyticsEnvironment.Testing, KeyVal, SourceVal) .WithMaxQueueTime(TimeSpan.FromSeconds(5)) .WithCommandLineArgs($"--{AnalyticsCommandLineArgs.EndpointName}", "https://example.com/") .With(client) .Build()) { await sender.SendAsync(ClassVal, TypeVal, new Dictionary <string, string>()); await sender.SendAsync("class-val-2", "type-val-2", new Dictionary <string, string>()); _messageHandlerMock.Protected().Verify("SendAsync", Times.Exactly(0), ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()); } }
public async Task DispatchAnalyticsEventsAfterQueueFills() { var client = new HttpClient(_messageHandlerMock.Object); using (var sender = new AnalyticsSenderBuilder(AnalyticsEnvironment.Testing, KeyVal, SourceVal) .WithMaxQueueSize(3) // This test will hopefully not take a year to run .WithMaxQueueTime(TimeSpan.FromDays(365.25)) .WithCommandLineArgs($"--{AnalyticsCommandLineArgs.EndpointName}", "https://example.com/") .With(client) .Build()) { await sender.SendAsync(ClassVal, TypeVal, new Dictionary <string, string>()); await sender.SendAsync("class-val-2", "type-val-2", new Dictionary <string, string>()); await sender.SendAsync("class-val-3", "type-val-3", new Dictionary <string, string>()); _messageHandlerMock.Protected().Verify("SendAsync", Times.Exactly(1), ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()); } }
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."); } } }); }