// Inject background service, for receiving message public void ConfigureServices(IServiceCollection services) { var loggerFactorySrv = services.BuildServiceProvider().GetService <ILoggerFactory>(); ILogger _logger = loggerFactorySrv .AddConsole() .AddDebug() .CreateLogger <Startup>(); var _operationalUnit = new OperationalUnit( environment: Environemnt.EnvironmentName, assembly: AssemblyName); services.AddSingleton <IOperationalUnit>(srv => _operationalUnit); services.AddSingleton <LocalConfiguration, LocalConfiguration>(srv => SystemLocalConfiguration); services.AddSingleton <IMessagePublisher, RabbitMQPublisher>(srv => { return(RabbitMQPublisher.Create(loggerFactorySrv, new RabbitMQConfiguration { hostName = SystemLocalConfiguration.MessagesMiddleware, exchange = SystemLocalConfiguration.MiddlewareExchange, userName = SystemLocalConfiguration.MessagesMiddlewareUsername, password = SystemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { SystemLocalConfiguration.MessagePublisherRoute } })); }); /// /// Injecting message receiver background service /// services.AddDistributedRedisCache(redisOptions => { redisOptions.Configuration = SystemLocalConfiguration.CacheServer; redisOptions.Configuration = SystemLocalConfiguration.CacheDBVehicles; }); services.AddApiVersioning(options => { options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); options.AssumeDefaultVersionWhenUnspecified = true; options.ReportApiVersions = true; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = _operationalUnit.Assembly, Version = "v1" }); }); services.AddMvc(options => { //TODO: add practical policy instead of empty policy for authentication / authorization . options.Filters.Add(new CustomAuthorizer(_logger, _operationalUnit)); options.Filters.Add(new CustomeExceptoinHandler(_logger, _operationalUnit, Environemnt)); options.Filters.Add(new CustomResponseResult(_logger, _operationalUnit)); }); }
// Inject background service, for receiving message public void ConfigureServices(IServiceCollection services) { var serviceProvider = services.BuildServiceProvider(); var loggerFactorySrv = serviceProvider.GetService <ILoggerFactory>(); services.AddDbContextPool <TrackingDbContext>(options => options.UseSqlServer( _systemLocalConfiguration.EventDbConnection, //enable connection resilience connectOptions => { connectOptions.EnableRetryOnFailure(); connectOptions.CommandTimeout(Identifiers.TimeoutInSec); }) //.UseLoggerFactory(loggerFactorySrv)// to log queries ); //add application insights information, could be used to monitor the performance, and more analytics when application moved to the cloud. loggerFactorySrv.AddApplicationInsights(services.BuildServiceProvider(), LogLevel.Information); ILogger _logger = loggerFactorySrv .AddConsole() .AddDebug() .AddFile(Configuration.GetSection("Logging")) .CreateLogger <Startup>(); // set cache service for db index 1 services.AddSingleton <ICacheProvider, CacheManager>(srv => new CacheManager(Logger, _systemLocalConfiguration.CacheServer)); services.AddSingleton <MiddlewareConfiguration, MiddlewareConfiguration>(srv => _systemLocalConfiguration); services.AddScoped <IOperationalUnit, IOperationalUnit>(srv => new OperationalUnit( environment: Environemnt.EnvironmentName, assembly: AssemblyName)); services.AddOptions(); #region worker background services #region tracking vehicle query client services.AddScoped <IMessageRequest <TrackingFilterModel, IEnumerable <DomainModels.Business.TrackingDomain.Tracking> >, RabbitMQRequestClient <TrackingFilterModel, IEnumerable <DomainModels.Business.TrackingDomain.Tracking> > >( srv => { return(new RabbitMQRequestClient <TrackingFilterModel, IEnumerable <DomainModels.Business.TrackingDomain.Tracking> > (loggerFactorySrv, new RabbitMQConfiguration { exchange = "", hostName = _systemLocalConfiguration.MessagesMiddleware, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { "rpc_queue_tracking_filter" }, })); }); #endregion #region tracking query worker // business logic services.AddSingleton <IHostedService, RabbitMQRequestWorker>(srv => { var trackingSrv = new TrackingManager(loggerFactorySrv, srv.GetService <TrackingDbContext>()); return(new RabbitMQRequestWorker (serviceProvider, loggerFactorySrv, new RabbitMQConfiguration { exchange = "", hostName = _systemLocalConfiguration.MessagesMiddleware, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { "rpc_queue_tracking_filter" }, } , (trackingMessageRequest) => { try { //TODO: add business logic, result should be serializable var trackingFilter = Utilities.JsonBinaryDeserialize <TrackingFilterModel>(trackingMessageRequest); Logger.LogInformation($"[x] callback of RabbitMQ tracking worker=> a message"); var response = trackingSrv.Query(trackingFilter.Body, predicate: null)?.ToList(); if (response == null) { return new byte[0]; } return Utilities.JsonBinarySerialize(response); } catch (Exception ex) { Logger.LogCritical(ex, "Object de-serialization exception."); //to respond back to RPC client return new byte[0]; } })); }); #endregion //you may get a different cache db, by passing db index parameter. #region cache workers //1- cache vehicle status (key/value) services.AddSingleton <IHostedService, RabbitMQSubscriberWorker>(srv => { var trackingSrv = new TrackingManager(loggerFactorySrv, srv.GetService <TrackingDbContext>()); var cacheSrv = new CacheManager(Logger, _systemLocalConfiguration.CacheServer); cacheSrv.Subscribe(Identifiers.onPing, (message) => { // onPing callback // add status & time stamp to vehicle 'set' var pingModel = Utilities.JsonBinaryDeserialize <PingModel>(message); if (pingModel?.Body != null) { cacheSrv.SetHash(pingModel.Body.ChassisNumber, new Dictionary <string, string> { { pingModel.Header.Timestamp.ToString(), Enum.GetName(typeof(StatusModel), pingModel.Body.Status) } }, Identifiers.cache_db_idx1).Wait(); } }); return(new RabbitMQSubscriberWorker (serviceProvider, loggerFactorySrv, new RabbitMQConfiguration { hostName = _systemLocalConfiguration.MessagesMiddleware, exchange = _systemLocalConfiguration.MiddlewareExchange, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { _systemLocalConfiguration.MessageSubscriberRoute } } , (pingMessageCallback) => { try { var message = pingMessageCallback(); if (message != null) { //get ping model var pingModel = Utilities.JsonBinaryDeserialize <PingModel>(message); if (pingModel != null) { //push vehicle ping on cache that expire after 1 minute, querying this cache db will have vehicles that ping within 1 minute cacheSrv.Set(pingModel.Body.ChassisNumber, pingModel.Header.Timestamp.ToString(), Defaults.CacheTimeout, Identifiers.cache_db_idx2) .Wait(); //get relevant vehicle Vehicle vehicle = null; Customer customer = null; var vehicleBinary = cacheSrv.GetBinary(pingModel.Body.ChassisNumber)?.Result; if (vehicleBinary != null) { vehicle = Utilities.JsonBinaryDeserialize <Vehicle>(vehicleBinary); //get customer by vehicle var customerBinary = cacheSrv.GetBinary(vehicle.CustomerId.ToString())?.Result; if (customerBinary != null) { customer = Utilities.JsonBinaryDeserialize <Customer>(customerBinary); } } //build tracking object var trackingObj = new DomainModels.Business.TrackingDomain.Tracking { CorrelationId = pingModel.Header.CorrelationId, ChassisNumber = vehicle?.ChassisNumber ?? pingModel.Body.ChassisNumber, Model = vehicle?.Model, Owner = customer?.Name, OwnerRef = (customer?.Id)?.ToString(), Status = pingModel.Body.Status, Message = pingModel.Body.Message, Timestamp = pingModel.Header.Timestamp, }; //push tracking object to repository var trackingDbModel = new TrackingSQLDB.DbModels.Tracking(trackingObj); trackingSrv.Add(trackingDbModel).Wait(); // publish on-ping cache event cacheSrv.Publish(Identifiers.onPing, message); } } Logger.LogInformation($"[x] Tracking service received a message from exchange: {_systemLocalConfiguration.MiddlewareExchange}, route :{_systemLocalConfiguration.MessageSubscriberRoute}"); } catch (Exception ex) { Logger.LogCritical(ex, "Object de-serialization exception."); } })); }); #endregion #region internal functions #endregion #endregion /// /// Injecting message receiver background service /// services.AddDistributedRedisCache(redisOptions => { redisOptions.Configuration = _systemLocalConfiguration.CacheServer; redisOptions.InstanceName = _systemLocalConfiguration.VehiclesCacheDB; }); services.AddApiVersioning(options => { options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); options.AssumeDefaultVersionWhenUnspecified = true; options.ReportApiVersions = true; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = AssemblyName, Version = "v1" }); }); services.AddMediatR(); var _operationalUnit = new OperationalUnit( environment: Environemnt.EnvironmentName, assembly: AssemblyName); services.AddMvc(options => { //TODO: add practical policy instead of empty policy for authentication / authorization . options.Filters.Add(new CustomAuthorizer(_logger, _operationalUnit)); options.Filters.Add(new CustomeExceptoinHandler(_logger, _operationalUnit, Environemnt)); options.Filters.Add(new CustomResponseResult(_logger, _operationalUnit)); }); }
// Inject background service, for receiving message public void ConfigureServices(IServiceCollection services) { var serviceProvider = services.BuildServiceProvider(); var loggerFactorySrv = serviceProvider.GetService <ILoggerFactory>(); services.AddDbContextPool <VehicleDbContext>(options => options.UseSqlServer( _systemLocalConfiguration.EventDbConnection, //enable connection resilience connectOptions => { connectOptions.EnableRetryOnFailure(); connectOptions.CommandTimeout(Identifiers.TimeoutInSec); }) //.UseLoggerFactory(loggerFactorySrv)// to log queries ); //add application insights information, could be used to monitor the performance, and more analytics when application moved to the cloud. loggerFactorySrv.AddApplicationInsights(services.BuildServiceProvider(), LogLevel.Information); ILogger _logger = loggerFactorySrv .AddConsole() .AddDebug() .AddFile(Configuration.GetSection("Logging")) .CreateLogger <Startup>(); // no need to inject the following service since, currently they are injected for the mediator. services.AddSingleton <MiddlewareConfiguration, MiddlewareConfiguration>(srv => _systemLocalConfiguration); services.AddScoped <IOperationalUnit, IOperationalUnit>(srv => new OperationalUnit( environment: Environemnt.EnvironmentName, assembly: AssemblyName)); services.AddScoped <IMessageCommand, RabbitMQPublisher>(srv => new RabbitMQPublisher(loggerFactorySrv, new RabbitMQConfiguration { hostName = _systemLocalConfiguration.MessagesMiddleware, exchange = _systemLocalConfiguration.MiddlewareExchange, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { _systemLocalConfiguration.MessagePublisherRoute } })); services.AddOptions(); #region worker #region vehicle worker services.AddSingleton <IHostedService, RabbitMQSubscriberWorker>(srv => { //get Vehicle service var vehicleSrv = new VehicleManager(loggerFactorySrv, srv.GetService <VehicleDbContext>()); var cacheSrv = new CacheManager(Logger, _systemLocalConfiguration.CacheServer); return(new RabbitMQSubscriberWorker (serviceProvider, loggerFactorySrv, new RabbitMQConfiguration { hostName = _systemLocalConfiguration.MessagesMiddleware, exchange = _systemLocalConfiguration.MiddlewareExchange, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = _systemLocalConfiguration.MessageSubscriberRoute?.Split('-') ?? new string[0] } , (messageCallback) => { try { var message = messageCallback(); if (message != null) { var domainModel = Utilities.JsonBinaryDeserialize <VehicleModel>(message); var vehicle = new VehicleSQLDB.DbModels.Vehicle(domainModel.Body); //get the correlated customer from the cache, to fill name field var customerBinary = cacheSrv.GetBinary(vehicle.CustomerId.ToString())?.Result; if (customerBinary != null) { var customer = Utilities.JsonBinaryDeserialize <Customer>(customerBinary); vehicle.CustomerName = customer.Name; } vehicleSrv.Add(vehicle).Wait(); cacheSrv.SetBinary(vehicle.ChassisNumber, Utilities.JsonBinarySerialize(vehicle)).Wait(); } Logger.LogInformation($"[x] Vehicle service receiving a message from exchange: {_systemLocalConfiguration.MiddlewareExchange}, route :{_systemLocalConfiguration.MessageSubscriberRoute}"); } catch (System.Exception ex) { Logger.LogCritical(ex, "Object de-serialization exception."); } })); }); #endregion #region tracking vehicle query client services.AddScoped <IMessageRequest <VehicleFilterModel, IEnumerable <DomainModels.Business.VehicleDomain.Vehicle> >, RabbitMQRequestClient <VehicleFilterModel, IEnumerable <DomainModels.Business.VehicleDomain.Vehicle> > >( srv => { return(new RabbitMQRequestClient <VehicleFilterModel, IEnumerable <DomainModels.Business.VehicleDomain.Vehicle> > (loggerFactorySrv, new RabbitMQConfiguration { exchange = "", hostName = _systemLocalConfiguration.MessagesMiddleware, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { "rpc_queue_vehicle_filter" }, })); }); #endregion #region vehicle query worker // business logic services.AddSingleton <IHostedService, RabbitMQRequestWorker>(srv => { var customerSrv = new VehicleManager(loggerFactorySrv, srv.GetService <VehicleDbContext>()); return(new RabbitMQRequestWorker (serviceProvider, loggerFactorySrv, new RabbitMQConfiguration { exchange = "", hostName = _systemLocalConfiguration.MessagesMiddleware, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { "rpc_queue_vehicle_filter" }, } , (customerFilterMessageRequest) => { try { //TODO: add business logic, result should be serializable var customerFilter = Utilities.JsonBinaryDeserialize <VehicleFilterModel>(customerFilterMessageRequest); Logger.LogInformation($"[x] callback of RabbitMQ customer worker=> a message"); var response = customerSrv.Query((c) => { return c.CustomerId == customerFilter.Body?.CustomerId; })?.ToList(); if (response == null) { return new byte[0]; } return Utilities.JsonBinarySerialize(response); } catch (Exception ex) { Logger.LogCritical(ex, "Object de-serialization exception."); //to respond back to RPC client return new byte[0]; } })); }); #endregion #endregion /// /// Injecting message receiver background service /// services.AddDistributedRedisCache(redisOptions => { redisOptions.Configuration = _systemLocalConfiguration.CacheServer; redisOptions.Configuration = _systemLocalConfiguration.VehiclesCacheDB; }); services.AddApiVersioning(options => { options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); options.AssumeDefaultVersionWhenUnspecified = true; options.ReportApiVersions = true; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = AssemblyName, Version = "v1" }); }); services.AddMediatR(); var _operationalUnit = new OperationalUnit( environment: Environemnt.EnvironmentName, assembly: AssemblyName); services.AddMvc(options => { //TODO: add practical policy instead of empty policy for authentication / authorization . options.Filters.Add(new CustomAuthorizer(_logger, _operationalUnit)); options.Filters.Add(new CustomeExceptoinHandler(_logger, _operationalUnit, Environemnt)); options.Filters.Add(new CustomResponseResult(_logger, _operationalUnit)); }); }
// Inject background service, for receiving message public void ConfigureServices(IServiceCollection services) { var serviceProvider = services.BuildServiceProvider(); var loggerFactorySrv = serviceProvider.GetService <ILoggerFactory>(); //add application insights information, could be used to monitor the performance, and more analytics when application moved to the cloud. loggerFactorySrv.AddApplicationInsights(services.BuildServiceProvider(), LogLevel.Information); ILogger _logger = loggerFactorySrv .AddConsole() .AddDebug() .AddFile(Configuration.GetSection("Logging")) .CreateLogger <Startup>(); // no need to inject the following service since, currently they are injected for the mediator. services.AddSingleton <MiddlewareConfiguration, MiddlewareConfiguration>(srv => _systemLocalConfiguration); services.AddScoped <IOperationalUnit, IOperationalUnit>(srv => new OperationalUnit( environment: Environemnt.EnvironmentName, assembly: AssemblyName)); services.AddScoped <IMessageCommand, RabbitMQPublisher>(srv => new RabbitMQPublisher(loggerFactorySrv, new RabbitMQConfiguration { hostName = _systemLocalConfiguration.MessagesMiddleware, exchange = _systemLocalConfiguration.MiddlewareExchange, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { _systemLocalConfiguration.MessagePublisherRoute } })); services.AddOptions(); #region worker #endregion /// /// Injecting message receiver background service /// services.AddDistributedRedisCache(redisOptions => { redisOptions.Configuration = _systemLocalConfiguration.CacheServer; redisOptions.Configuration = _systemLocalConfiguration.VehiclesCacheDB; }); services.AddApiVersioning(options => { options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); options.AssumeDefaultVersionWhenUnspecified = true; options.ReportApiVersions = true; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = AssemblyName, Version = "v1" }); }); services.AddMediatR(); var _operationalUnit = new OperationalUnit( environment: Environemnt.EnvironmentName, assembly: AssemblyName); services.AddMvc(options => { //TODO: add practical policy instead of empty policy for authentication / authorization . options.Filters.Add(new CustomAuthorizer(_logger, _operationalUnit)); options.Filters.Add(new CustomeExceptoinHandler(_logger, _operationalUnit, Environemnt)); options.Filters.Add(new CustomResponseResult(_logger, _operationalUnit)); }); }