From 50dfd039cbdf69929e525cafc2f0ff6a3b8afc7f Mon Sep 17 00:00:00 2001 From: Saeed Ganji Date: Mon, 20 Jul 2020 18:21:50 +0430 Subject: [PATCH] Removed switch-case from ProcessBatchJobConsumer --- .../Controllers/BatchJobsController.cs | 2 +- src/SampleBatch.Api/SampleBatch.Api.csproj | 14 +-- src/SampleBatch.Api/Startup.cs | 71 ++++++-------- .../SampleBatch.Common.csproj | 4 +- .../Consumers/ProcessBatchJobConsumer.cs | 73 +++----------- .../SampleBatch.Components.csproj | 4 +- .../SampleBatchDbContext.cs | 4 +- .../StateMachines/BatchState.cs | 10 +- .../BatchStateEntityConfiguration.cs | 9 +- .../StateMachines/JobState.cs | 2 +- .../JobStateEntityConfiguration.cs | 8 +- src/SampleBatch.Contracts/BatchJobReceived.cs | 2 +- src/SampleBatch.Contracts/BatchReceived.cs | 2 +- .../Enums/BatchAction.cs | 8 -- .../Enums/BatchActionEnum.cs | 50 ++++++++++ .../Converter/BatchActionEnumConverter.cs | 53 +++++++++++ .../Enums/Internal/CancelOrdersEnum.cs | 41 ++++++++ .../Enums/Internal/SuspendOrdersEnum.cs | 37 ++++++++ src/SampleBatch.Contracts/ProcessBatchJob.cs | 2 +- .../SampleBatch.Contracts.csproj | 2 +- src/SampleBatch.Contracts/SubmitBatch.cs | 2 +- src/SampleBatch.Service/Program.cs | 94 ++++++++----------- .../SampleBatch.Service.csproj | 30 +++--- .../Integration/BatchStateMachineTests.cs | 2 +- .../SampleBatch.Tests.csproj | 13 ++- .../Unit/BatchStateMachineTests.cs | 4 +- 26 files changed, 320 insertions(+), 223 deletions(-) delete mode 100644 src/SampleBatch.Contracts/Enums/BatchAction.cs create mode 100644 src/SampleBatch.Contracts/Enums/BatchActionEnum.cs create mode 100644 src/SampleBatch.Contracts/Enums/Converter/BatchActionEnumConverter.cs create mode 100644 src/SampleBatch.Contracts/Enums/Internal/CancelOrdersEnum.cs create mode 100644 src/SampleBatch.Contracts/Enums/Internal/SuspendOrdersEnum.cs diff --git a/src/SampleBatch.Api/Controllers/BatchJobsController.cs b/src/SampleBatch.Api/Controllers/BatchJobsController.cs index 43d2853..456724e 100644 --- a/src/SampleBatch.Api/Controllers/BatchJobsController.cs +++ b/src/SampleBatch.Api/Controllers/BatchJobsController.cs @@ -88,7 +88,7 @@ public async Task> Post(int jobCount = 100, int activeThresho { BatchId = id, InVar.Timestamp, - Action = BatchAction.CancelOrders, + Action = BatchActionEnum.CancelOrders, OrderIds = orderIds.ToArray(), ActiveThreshold = activeThreshold, DelayInSeconds = delayInSeconds diff --git a/src/SampleBatch.Api/SampleBatch.Api.csproj b/src/SampleBatch.Api/SampleBatch.Api.csproj index 75984b8..da673e9 100644 --- a/src/SampleBatch.Api/SampleBatch.Api.csproj +++ b/src/SampleBatch.Api/SampleBatch.Api.csproj @@ -13,13 +13,13 @@ - - - - - - - + + + + + + + diff --git a/src/SampleBatch.Api/Startup.cs b/src/SampleBatch.Api/Startup.cs index f4194d3..def7ce3 100644 --- a/src/SampleBatch.Api/Startup.cs +++ b/src/SampleBatch.Api/Startup.cs @@ -5,17 +5,13 @@ using System.Text; using Contracts; using MassTransit; - using MassTransit.Azure.ServiceBus.Core; - using MassTransit.Definition; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; - using Microsoft.Extensions.Options; public class Startup @@ -33,14 +29,40 @@ public void ConfigureServices(IServiceCollection services) services.AddHealthChecks(); services.AddMvc(); + var appConfig = Configuration.GetSection(nameof(AppConfig)).Get(); services.Configure(options => Configuration.GetSection("AppConfig").Bind(options)); - services.TryAddSingleton(KebabCaseEndpointNameFormatter.Instance); services.AddMassTransit(cfg => { + cfg.SetKebabCaseEndpointNameFormatter(); cfg.AddRequestClient(); cfg.AddRequestClient(); - cfg.AddBus(ConfigureBus); + + if (appConfig.AzureServiceBus != null) + { + cfg.UsingAzureServiceBus((x, y) => + { + y.Host(appConfig.AzureServiceBus.ConnectionString); + y.ConfigureEndpoints(x); + }); + } + else if (appConfig.RabbitMq != null) + { + cfg.UsingRabbitMq((x, y) => + { + y.Host(appConfig.RabbitMq.HostAddress, appConfig.RabbitMq.VirtualHost, h => + { + h.Username(appConfig.RabbitMq.Username); + h.Password(appConfig.RabbitMq.Password); + }); + + y.ConfigureEndpoints(x); + }); + } + else + { + throw new ApplicationException("Invalid Bus configuration. Couldn't find Azure or RabbitMq config"); + } }); services.AddMassTransitHostedService(); @@ -80,42 +102,5 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApp cache.Set("cachedTimeUTC", encodedCurrentTimeUtc, options); }); } - - static IBusControl ConfigureBus(IServiceProvider provider) - { - var appSettings = provider.GetRequiredService>().Value; - - if (appSettings.AzureServiceBus != null) - return ConfigureAzureSb(provider, appSettings); - - if (appSettings.RabbitMq != null) - return ConfigureRabbitMqBus(provider, appSettings); - - throw new ApplicationException("Invalid Bus configuration. Couldn't find Azure or RabbitMq config"); - } - - static IBusControl ConfigureRabbitMqBus(IServiceProvider provider, AppConfig appConfig) - { - return Bus.Factory.CreateUsingRabbitMq(cfg => - { - cfg.Host(appConfig.RabbitMq.HostAddress, appConfig.RabbitMq.VirtualHost, h => - { - h.Username(appConfig.RabbitMq.Username); - h.Password(appConfig.RabbitMq.Password); - }); - - cfg.ConfigureEndpoints(provider); - }); - } - - static IBusControl ConfigureAzureSb(IServiceProvider provider, AppConfig appConfig) - { - return Bus.Factory.CreateUsingAzureServiceBus(cfg => - { - cfg.Host(appConfig.AzureServiceBus.ConnectionString); - - cfg.ConfigureEndpoints(provider); - }); - } } } \ No newline at end of file diff --git a/src/SampleBatch.Common/SampleBatch.Common.csproj b/src/SampleBatch.Common/SampleBatch.Common.csproj index 353aadb..ba907f7 100644 --- a/src/SampleBatch.Common/SampleBatch.Common.csproj +++ b/src/SampleBatch.Common/SampleBatch.Common.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/src/SampleBatch.Components/Consumers/ProcessBatchJobConsumer.cs b/src/SampleBatch.Components/Consumers/ProcessBatchJobConsumer.cs index e0ba757..6bc94b5 100644 --- a/src/SampleBatch.Components/Consumers/ProcessBatchJobConsumer.cs +++ b/src/SampleBatch.Components/Consumers/ProcessBatchJobConsumer.cs @@ -1,9 +1,7 @@ namespace SampleBatch.Components.Consumers { - using System; using System.Threading.Tasks; using Contracts; - using Contracts.Enums; using MassTransit; using MassTransit.Courier; using MassTransit.Courier.Contracts; @@ -24,64 +22,21 @@ public async Task Consume(ConsumeContext context) { using (_log.BeginScope("ProcessBatchJob {BatchJobId}, {OrderId}", context.Message.BatchJobId, context.Message.OrderId)) { - var builder = new RoutingSlipBuilder(NewId.NextGuid()); - - switch (context.Message.Action) + var routingSlip = await context.Message.Action.SetupRoutingSlip(context, async builder => { - case BatchAction.CancelOrders: - builder.AddActivity( - "CancelOrder", - new Uri("queue:cancel-order_execute"), - new - { - context.Message.OrderId, - Reason = "Product discontinued" - }); - - await builder.AddSubscription( - context.SourceAddress, - RoutingSlipEvents.ActivityFaulted, - RoutingSlipEventContents.None, - "CancelOrder", - x => x.Send(new - { - context.Message.BatchJobId, - context.Message.BatchId, - context.Message.OrderId - })); - break; - - case BatchAction.SuspendOrders: - builder.AddActivity( - "SuspendOrder", - new Uri("queue:suspend-order_execute"), - new {context.Message.OrderId}); - - await builder.AddSubscription( - context.SourceAddress, - RoutingSlipEvents.ActivityFaulted, - RoutingSlipEventContents.None, - "SuspendOrder", - x => x.Send(new - { - context.Message.BatchJobId, - context.Message.BatchId, - context.Message.OrderId - })); - break; - } - - await builder.AddSubscription( - context.SourceAddress, - RoutingSlipEvents.Completed, - x => x.Send(new - { - context.Message.BatchJobId, - context.Message.BatchId - })); - - await context.Execute(builder.Build()); + await builder.AddSubscription( + context.SourceAddress, + RoutingSlipEvents.Completed, + x => x.Send(new + { + context.Message.BatchJobId, + context.Message.BatchId, + InVar.Timestamp + })); + }); + + await context.Execute(routingSlip); } } } -} \ No newline at end of file +} diff --git a/src/SampleBatch.Components/SampleBatch.Components.csproj b/src/SampleBatch.Components/SampleBatch.Components.csproj index 857d25b..af4eb72 100644 --- a/src/SampleBatch.Components/SampleBatch.Components.csproj +++ b/src/SampleBatch.Components/SampleBatch.Components.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/src/SampleBatch.Components/SampleBatchDbContext.cs b/src/SampleBatch.Components/SampleBatchDbContext.cs index c83dabe..ef1e497 100644 --- a/src/SampleBatch.Components/SampleBatchDbContext.cs +++ b/src/SampleBatch.Components/SampleBatchDbContext.cs @@ -1,8 +1,6 @@ using Microsoft.EntityFrameworkCore; using SampleBatch.Components.StateMachines; -using System; -using System.Collections.Generic; -using System.Text; + namespace SampleBatch.Components { diff --git a/src/SampleBatch.Components/StateMachines/BatchState.cs b/src/SampleBatch.Components/StateMachines/BatchState.cs index 36e3023..20fedce 100644 --- a/src/SampleBatch.Components/StateMachines/BatchState.cs +++ b/src/SampleBatch.Components/StateMachines/BatchState.cs @@ -19,12 +19,12 @@ public class BatchState : public DateTime? UpdateTimestamp { get; set; } - public BatchAction? Action { get; set; } + public BatchActionEnum Action { get; set; } - /// - /// The maximum amount of active Jobs allowed to be processing. Typically an amount larger than your Job Consumer can handle concurrently, to allow for some additional prefetch while the Batch Saga dispatches more - /// - public int? ActiveThreshold { get; set; } = 20; + /// + /// The maximum amount of active Jobs allowed to be processing. Typically an amount larger than your Job Consumer can handle concurrently, to allow for some additional prefetch while the Batch Saga dispatches more + /// + public int? ActiveThreshold { get; set; } = 20; public int? Total { get; set; } diff --git a/src/SampleBatch.Components/StateMachines/BatchStateEntityConfiguration.cs b/src/SampleBatch.Components/StateMachines/BatchStateEntityConfiguration.cs index 935827a..58d4881 100644 --- a/src/SampleBatch.Components/StateMachines/BatchStateEntityConfiguration.cs +++ b/src/SampleBatch.Components/StateMachines/BatchStateEntityConfiguration.cs @@ -2,11 +2,11 @@ { using System; using System.Collections.Generic; + using System.Linq; using Common; using Contracts.Enums; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; - using Microsoft.EntityFrameworkCore.Storage.ValueConversion; class BatchStateEntityConfiguration : @@ -22,8 +22,9 @@ public void Configure(EntityTypeBuilder builder) builder.Property(c => c.CurrentState).IsRequired(); - builder.Property(c => c.Action) - .HasConversion(new EnumToStringConverter()); + builder.Property(p => p.Action) + .HasConversion(v => v.Value, i => BatchActionEnum.List().FirstOrDefault(e => e.Value == i)); + builder.Property(c => c.UnprocessedOrderIds) .HasConversion(new JsonValueConverter>()) @@ -34,4 +35,4 @@ public void Configure(EntityTypeBuilder builder) .Metadata.SetValueComparer(new JsonValueComparer>()); } } -} \ No newline at end of file +} diff --git a/src/SampleBatch.Components/StateMachines/JobState.cs b/src/SampleBatch.Components/StateMachines/JobState.cs index 9b45659..a589024 100644 --- a/src/SampleBatch.Components/StateMachines/JobState.cs +++ b/src/SampleBatch.Components/StateMachines/JobState.cs @@ -20,7 +20,7 @@ public class JobState : public DateTime? UpdateTimestamp { get; set; } - public BatchAction Action { get; set; } + public BatchActionEnum Action { get; set; } public string ExceptionMessage { get; set; } diff --git a/src/SampleBatch.Components/StateMachines/JobStateEntityConfiguration.cs b/src/SampleBatch.Components/StateMachines/JobStateEntityConfiguration.cs index d6f6635..ddc0208 100644 --- a/src/SampleBatch.Components/StateMachines/JobStateEntityConfiguration.cs +++ b/src/SampleBatch.Components/StateMachines/JobStateEntityConfiguration.cs @@ -1,9 +1,9 @@ namespace SampleBatch.Components.StateMachines { + using System.Linq; using Contracts.Enums; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; - using Microsoft.EntityFrameworkCore.Storage.ValueConversion; class JobStateEntityConfiguration : @@ -19,8 +19,8 @@ public void Configure(EntityTypeBuilder builder) builder.Property(c => c.CurrentState).IsRequired(); - builder.Property(c => c.Action) - .HasConversion(new EnumToStringConverter()); + builder.Property(p => p.Action) + .HasConversion(v => v.Value, i => BatchActionEnum.List().FirstOrDefault(e => e.Value == i)); } } -} \ No newline at end of file +} diff --git a/src/SampleBatch.Contracts/BatchJobReceived.cs b/src/SampleBatch.Contracts/BatchJobReceived.cs index 941098c..3858ecc 100644 --- a/src/SampleBatch.Contracts/BatchJobReceived.cs +++ b/src/SampleBatch.Contracts/BatchJobReceived.cs @@ -10,6 +10,6 @@ public interface BatchJobReceived Guid BatchId { get; } Guid OrderId { get; } DateTime Timestamp { get; } - BatchAction Action { get; } + BatchActionEnum Action { get; } } } \ No newline at end of file diff --git a/src/SampleBatch.Contracts/BatchReceived.cs b/src/SampleBatch.Contracts/BatchReceived.cs index f908a7a..7b7f603 100644 --- a/src/SampleBatch.Contracts/BatchReceived.cs +++ b/src/SampleBatch.Contracts/BatchReceived.cs @@ -8,7 +8,7 @@ public interface BatchReceived { Guid BatchId { get; } DateTime Timestamp { get; } - BatchAction Action { get; } + BatchActionEnum Action { get; } Guid[] OrderIds { get; } int ActiveThreshold { get; } diff --git a/src/SampleBatch.Contracts/Enums/BatchAction.cs b/src/SampleBatch.Contracts/Enums/BatchAction.cs deleted file mode 100644 index 2b0a779..0000000 --- a/src/SampleBatch.Contracts/Enums/BatchAction.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SampleBatch.Contracts.Enums -{ - public enum BatchAction - { - CancelOrders = 1, - SuspendOrders = 2 - } -} diff --git a/src/SampleBatch.Contracts/Enums/BatchActionEnum.cs b/src/SampleBatch.Contracts/Enums/BatchActionEnum.cs new file mode 100644 index 0000000..78b65ff --- /dev/null +++ b/src/SampleBatch.Contracts/Enums/BatchActionEnum.cs @@ -0,0 +1,50 @@ +namespace SampleBatch.Contracts.Enums +{ + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + using Converter; + using Internal; + using MassTransit; + using MassTransit.Courier; + using MassTransit.Courier.Contracts; + using Newtonsoft.Json; + + + [JsonConverter(typeof(BatchActionEnumConverter))] + public abstract class BatchActionEnum + { + public static readonly BatchActionEnum CancelOrders = new CancelOrdersEnum(); + public static readonly BatchActionEnum SuspendOrders = new SuspendOrdersEnum(); + + public int Value { get; private set; } + public string Name { get; private set; } + + public static IEnumerable List() + { + yield return CancelOrders; + yield return SuspendOrders; + } + + protected BatchActionEnum(int value, string name) + { + Value = value; + Name = name; + } + + public async Task SetupRoutingSlip(ConsumeContext context, Func commonAction) + { + var builder = new RoutingSlipBuilder(NewId.NextGuid()); + + await SetupRoutingSlip(builder, context); + + await commonAction?.Invoke(builder); + + return builder.Build(); + + } + + protected abstract Task SetupRoutingSlip(RoutingSlipBuilder builder, ConsumeContext context); + + } +} diff --git a/src/SampleBatch.Contracts/Enums/Converter/BatchActionEnumConverter.cs b/src/SampleBatch.Contracts/Enums/Converter/BatchActionEnumConverter.cs new file mode 100644 index 0000000..ddc3b95 --- /dev/null +++ b/src/SampleBatch.Contracts/Enums/Converter/BatchActionEnumConverter.cs @@ -0,0 +1,53 @@ +namespace SampleBatch.Contracts.Enums.Converter +{ + using System; + using Internal; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + using Newtonsoft.Json.Serialization; + + + public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver + { + protected override JsonConverter ResolveContractConverter(Type objectType) + { + if (typeof(BatchActionEnum).IsAssignableFrom(objectType) && !objectType.IsAbstract) + return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow) + return base.ResolveContractConverter(objectType); + } + } + + public class BatchActionEnumConverter : JsonConverter + { + static readonly JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new BaseSpecifiedConcreteClassConverter() }; + + public override bool CanConvert(Type objectType) + { + return (objectType == typeof(BatchActionEnum)); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + JObject jo = JObject.Load(reader); + switch (jo["value"].Value()) + { + case 1: + return JsonConvert.DeserializeObject(jo.ToString(), SpecifiedSubclassConversion); + case 2: + return JsonConvert.DeserializeObject(jo.ToString(), SpecifiedSubclassConversion); + default: + throw new Exception(); + } + throw new NotImplementedException(); + } + + public override bool CanWrite { + get { return false; } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); // won't be called because CanWrite returns false + } + } +} \ No newline at end of file diff --git a/src/SampleBatch.Contracts/Enums/Internal/CancelOrdersEnum.cs b/src/SampleBatch.Contracts/Enums/Internal/CancelOrdersEnum.cs new file mode 100644 index 0000000..fdc9597 --- /dev/null +++ b/src/SampleBatch.Contracts/Enums/Internal/CancelOrdersEnum.cs @@ -0,0 +1,41 @@ +namespace SampleBatch.Contracts.Enums.Internal +{ + using System; + using System.Threading.Tasks; + using MassTransit; + using MassTransit.Courier; + using MassTransit.Courier.Contracts; + + + class CancelOrdersEnum : BatchActionEnum + { + public CancelOrdersEnum() + : base(1, "Cancel Orders") + { + } + + protected override async Task SetupRoutingSlip( RoutingSlipBuilder builder, ConsumeContext context) + { + builder.AddActivity( + "CancelOrder", + new Uri("queue:cancel-order_execute"), + new + { + context.Message.OrderId, + Reason = "Product discontinued" + }); + + await builder.AddSubscription( + context.SourceAddress, + RoutingSlipEvents.ActivityFaulted, + RoutingSlipEventContents.None, + "CancelOrder", + x => x.Send(new + { + context.Message.BatchJobId, + context.Message.BatchId, + context.Message.OrderId + })); + } + } +} diff --git a/src/SampleBatch.Contracts/Enums/Internal/SuspendOrdersEnum.cs b/src/SampleBatch.Contracts/Enums/Internal/SuspendOrdersEnum.cs new file mode 100644 index 0000000..42308c5 --- /dev/null +++ b/src/SampleBatch.Contracts/Enums/Internal/SuspendOrdersEnum.cs @@ -0,0 +1,37 @@ +namespace SampleBatch.Contracts.Enums.Internal +{ + using System; + using System.Threading.Tasks; + using MassTransit; + using MassTransit.Courier; + using MassTransit.Courier.Contracts; + + + class SuspendOrdersEnum : BatchActionEnum + { + public SuspendOrdersEnum() + : base(2, "Suspend Orders") + { + } + + protected override async Task SetupRoutingSlip(RoutingSlipBuilder builder, ConsumeContext context) + { + builder.AddActivity( + "SuspendOrder", + new Uri("queue:suspend-order_execute"), + new { context.Message.OrderId }); + + await builder.AddSubscription( + context.SourceAddress, + RoutingSlipEvents.ActivityFaulted, + RoutingSlipEventContents.None, + "SuspendOrder", + x => x.Send(new + { + context.Message.BatchJobId, + context.Message.BatchId, + context.Message.OrderId + })); + } + } +} diff --git a/src/SampleBatch.Contracts/ProcessBatchJob.cs b/src/SampleBatch.Contracts/ProcessBatchJob.cs index 0a5e38d..5132e8d 100644 --- a/src/SampleBatch.Contracts/ProcessBatchJob.cs +++ b/src/SampleBatch.Contracts/ProcessBatchJob.cs @@ -10,6 +10,6 @@ public interface ProcessBatchJob Guid BatchId { get; } DateTime Timestamp { get; } Guid OrderId { get; } - BatchAction Action { get; } + BatchActionEnum Action { get; } } } \ No newline at end of file diff --git a/src/SampleBatch.Contracts/SampleBatch.Contracts.csproj b/src/SampleBatch.Contracts/SampleBatch.Contracts.csproj index 9df6298..aa4404b 100644 --- a/src/SampleBatch.Contracts/SampleBatch.Contracts.csproj +++ b/src/SampleBatch.Contracts/SampleBatch.Contracts.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/SampleBatch.Contracts/SubmitBatch.cs b/src/SampleBatch.Contracts/SubmitBatch.cs index 82e8b63..858a1c8 100644 --- a/src/SampleBatch.Contracts/SubmitBatch.cs +++ b/src/SampleBatch.Contracts/SubmitBatch.cs @@ -10,7 +10,7 @@ public interface SubmitBatch DateTime Timestamp { get; } - BatchAction Action { get; } + BatchActionEnum Action { get; } Guid[] OrderIds { get; } diff --git a/src/SampleBatch.Service/Program.cs b/src/SampleBatch.Service/Program.cs index feec0c6..6483b1a 100644 --- a/src/SampleBatch.Service/Program.cs +++ b/src/SampleBatch.Service/Program.cs @@ -10,17 +10,12 @@ using Components.StateMachines; using Contracts; using MassTransit; - using MassTransit.Azure.ServiceBus.Core; - using MassTransit.Definition; using MassTransit.EntityFrameworkCoreIntegration; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - class Program { @@ -41,11 +36,12 @@ static async Task Main(string[] args) }) .ConfigureServices((hostContext, services) => { + var appConfig = hostContext.Configuration.GetSection(nameof(AppConfig)).Get(); services.Configure(options => hostContext.Configuration.GetSection("AppConfig").Bind(options)); - services.TryAddSingleton(KebabCaseEndpointNameFormatter.Instance); services.AddMassTransit(cfg => { + cfg.SetKebabCaseEndpointNameFormatter(); cfg.AddSagaStateMachine(typeof(BatchStateMachineDefinition)) .EntityFrameworkRepository(r => { @@ -81,7 +77,42 @@ static async Task Main(string[] args) cfg.AddConsumersFromNamespaceContaining(); cfg.AddActivitiesFromNamespaceContaining(); - cfg.AddBus(ConfigureBus); + if (appConfig.AzureServiceBus != null) + { + cfg.UsingAzureServiceBus((x, y) => + { + y.Host(appConfig.AzureServiceBus.ConnectionString); + + var endpointNameFormatter = x.GetRequiredService(); + EndpointConvention.Map(new Uri($"queue:{endpointNameFormatter.Consumer()}")); + + y.UseServiceBusMessageScheduler(); + + y.ConfigureEndpoints(x); + }); + } + else if (appConfig.RabbitMq != null) + { + cfg.UsingRabbitMq((x, y) => + { + y.Host(appConfig.RabbitMq.HostAddress, appConfig.RabbitMq.VirtualHost, h => + { + h.Username(appConfig.RabbitMq.Username); + h.Password(appConfig.RabbitMq.Password); + }); + + var endpointNameFormatter = x.GetRequiredService(); + EndpointConvention.Map(new Uri($"queue:{endpointNameFormatter.Consumer()}")); + + y.UseInMemoryScheduler(); + + y.ConfigureEndpoints(x); + }); + } + else + { + throw new ApplicationException("Invalid Bus configuration. Couldn't find Azure or RabbitMq config"); + } }); services.AddDbContext(x => x.UseSqlServer(hostContext.Configuration.GetConnectionString("sample-batch"))); @@ -108,54 +139,5 @@ static async Task Main(string[] args) else await builder.RunConsoleAsync(); } - - static IBusControl ConfigureBus(IServiceProvider provider) - { - var appSettings = provider.GetRequiredService>().Value; - - if (appSettings.AzureServiceBus != null) - return ConfigureAzureSb(provider, appSettings); - - if (appSettings.RabbitMq != null) - return ConfigureRabbitMqBus(provider, appSettings); - - throw new ApplicationException("Invalid Bus configuration. Couldn't find Azure or RabbitMq config"); - } - - static IBusControl ConfigureRabbitMqBus(IServiceProvider provider, AppConfig appConfig) - { - var endpointNameFormatter = provider.GetService() ?? KebabCaseEndpointNameFormatter.Instance; - - return Bus.Factory.CreateUsingRabbitMq(cfg => - { - cfg.Host(appConfig.RabbitMq.HostAddress, appConfig.RabbitMq.VirtualHost, h => - { - h.Username(appConfig.RabbitMq.Username); - h.Password(appConfig.RabbitMq.Password); - }); - - EndpointConvention.Map(new Uri($"queue:{endpointNameFormatter.Consumer()}")); - - cfg.UseInMemoryScheduler(); - - cfg.ConfigureEndpoints(provider, endpointNameFormatter); - }); - } - - static IBusControl ConfigureAzureSb(IServiceProvider provider, AppConfig appConfig) - { - var endpointNameFormatter = provider.GetService() ?? KebabCaseEndpointNameFormatter.Instance; - - return Bus.Factory.CreateUsingAzureServiceBus(cfg => - { - cfg.Host(appConfig.AzureServiceBus.ConnectionString); - - EndpointConvention.Map(new Uri($"queue:{endpointNameFormatter.Consumer()}")); - - cfg.UseServiceBusMessageScheduler(); - - cfg.ConfigureEndpoints(provider, endpointNameFormatter); - }); - } } } \ No newline at end of file diff --git a/src/SampleBatch.Service/SampleBatch.Service.csproj b/src/SampleBatch.Service/SampleBatch.Service.csproj index 5fde563..07fcba3 100644 --- a/src/SampleBatch.Service/SampleBatch.Service.csproj +++ b/src/SampleBatch.Service/SampleBatch.Service.csproj @@ -17,21 +17,21 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/src/SampleBatch.Tests/Integration/BatchStateMachineTests.cs b/src/SampleBatch.Tests/Integration/BatchStateMachineTests.cs index f23db78..d85baba 100644 --- a/src/SampleBatch.Tests/Integration/BatchStateMachineTests.cs +++ b/src/SampleBatch.Tests/Integration/BatchStateMachineTests.cs @@ -81,7 +81,7 @@ public async Task should_complete_successfully() { BatchId = NewId.NextGuid(), Timestamp = DateTime.UtcNow, - BatchAction = BatchAction.CancelOrders, + BatchAction = BatchActionEnum.CancelOrders, ActiveThreshold = 5, OrderIds = new Guid[] { Guid.NewGuid(), Guid.NewGuid() } }); diff --git a/src/SampleBatch.Tests/SampleBatch.Tests.csproj b/src/SampleBatch.Tests/SampleBatch.Tests.csproj index 4caf613..88e9983 100644 --- a/src/SampleBatch.Tests/SampleBatch.Tests.csproj +++ b/src/SampleBatch.Tests/SampleBatch.Tests.csproj @@ -6,12 +6,15 @@ - - - - + + + + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/SampleBatch.Tests/Unit/BatchStateMachineTests.cs b/src/SampleBatch.Tests/Unit/BatchStateMachineTests.cs index b525dc7..b71ccd6 100644 --- a/src/SampleBatch.Tests/Unit/BatchStateMachineTests.cs +++ b/src/SampleBatch.Tests/Unit/BatchStateMachineTests.cs @@ -59,7 +59,7 @@ public async Task should_start() { BatchId = NewId.NextGuid(), Timestamp = DateTime.UtcNow, - BatchAction = BatchAction.CancelOrders, + BatchAction = BatchActionEnum.CancelOrders, ActiveThreshold = 5, OrderIds = new Guid[] { Guid.NewGuid(), Guid.NewGuid() } }); @@ -87,7 +87,7 @@ public async Task should_receive_and_wait() { BatchId = NewId.NextGuid(), Timestamp = DateTime.UtcNow, - BatchAction = BatchAction.CancelOrders, + BatchAction = BatchActionEnum.CancelOrders, ActiveThreshold = 5, OrderIds = new Guid[] { Guid.NewGuid(), Guid.NewGuid() }, DelayInSeconds = 60