// Inject background service, for receiving message public void ConfigureServices(IServiceCollection services) { var serviceProvider = services.BuildServiceProvider(); var loggerFactorySrv = serviceProvider.GetService <ILoggerFactory>(); services.AddDbContextPool <CustomerDbContext>(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 workers #region customer worker services.AddSingleton <IHostedService, RabbitMQSubscriberWorker>(srv => { //get Vehicle service var customerSrv = new CustomerManager(loggerFactorySrv, srv.GetService <CustomerDbContext>()); 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 <DomainModels.Business.CustomerDomain.CustomerModel>(message); var customer = new CustomerSQLDB.DbModels.Customer(domainModel.Body); customerSrv.Add(customer).Wait(); cacheSrv.SetBinary(customer.Id.ToString(), Utilities.JsonBinarySerialize(customer)).Wait(); } Logger.LogInformation($"[x] Customer 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 customer query client services.AddScoped <IMessageRequest <CustomerFilterModel, IEnumerable <DomainModels.Business.CustomerDomain.Customer> >, RabbitMQRequestClient <CustomerFilterModel, IEnumerable <DomainModels.Business.CustomerDomain.Customer> > >( srv => { return(new RabbitMQRequestClient <CustomerFilterModel, IEnumerable <DomainModels.Business.CustomerDomain.Customer> > (loggerFactorySrv, new RabbitMQConfiguration { exchange = "", hostName = _systemLocalConfiguration.MessagesMiddleware, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { "rpc_queue_customer_filter" }, })); }); #endregion #region customer query worker // business logic services.AddSingleton <IHostedService, RabbitMQRequestWorker>(srv => { var customerSrv = new CustomerManager(loggerFactorySrv, srv.GetService <CustomerDbContext>()); return(new RabbitMQRequestWorker (serviceProvider, loggerFactorySrv, new RabbitMQConfiguration { exchange = "", hostName = _systemLocalConfiguration.MessagesMiddleware, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { "rpc_queue_customer_filter" }, } , (customerFilterMessageRequest) => { try { //TODO: add business logic, result should be serializable var customerFilter = Utilities.JsonBinaryDeserialize <CustomerFilterModel>(customerFilterMessageRequest); Logger.LogInformation($"[x] callback of RabbitMQ customer worker=> a message"); var response = customerSrv.Query((c) => { return c.CorrelationId == customerFilter.Body?.CorrelationId; })?.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 #region tracking vehicle query client services.AddScoped <IMessageRequest <VehicleFilterModel, IEnumerable <Vehicle> >, RabbitMQRequestClient <VehicleFilterModel, IEnumerable <Vehicle> > >( srv => { return(new RabbitMQRequestClient <VehicleFilterModel, IEnumerable <Vehicle> > (loggerFactorySrv, new RabbitMQConfiguration { exchange = "", hostName = _systemLocalConfiguration.MessagesMiddleware, userName = _systemLocalConfiguration.MessagesMiddlewareUsername, password = _systemLocalConfiguration.MessagesMiddlewarePassword, routes = new string[] { "rpc_queue_vehicle_filter" }, })); }); #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)); }); }