@ -0,0 +1,132 @@ | |||
############################### | |||
# Core EditorConfig Options # | |||
############################### | |||
root = true | |||
# All files | |||
[*] | |||
indent_style = space | |||
# XML project files | |||
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] | |||
indent_size = 2 | |||
# XML config files | |||
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] | |||
indent_size = 2 | |||
# Code files | |||
[*.{cs,csx,vb,vbx}] | |||
indent_size = 4 | |||
insert_final_newline = true | |||
charset = utf-8-bom | |||
############################### | |||
# .NET Coding Conventions # | |||
############################### | |||
[*.{cs,vb}] | |||
# Organize usings | |||
dotnet_sort_system_directives_first = true | |||
# this. preferences | |||
dotnet_style_qualification_for_field = false:silent | |||
dotnet_style_qualification_for_property = false:silent | |||
dotnet_style_qualification_for_method = false:silent | |||
dotnet_style_qualification_for_event = false:silent | |||
# Language keywords vs BCL types preferences | |||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent | |||
dotnet_style_predefined_type_for_member_access = true:silent | |||
# Parentheses preferences | |||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent | |||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent | |||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent | |||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent | |||
# Modifier preferences | |||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent | |||
dotnet_style_readonly_field = true:suggestion | |||
# Expression-level preferences | |||
dotnet_style_object_initializer = true:suggestion | |||
dotnet_style_collection_initializer = true:suggestion | |||
dotnet_style_explicit_tuple_names = true:suggestion | |||
dotnet_style_null_propagation = true:suggestion | |||
dotnet_style_coalesce_expression = true:suggestion | |||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent | |||
dotnet_style_prefer_inferred_tuple_names = true:suggestion | |||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion | |||
dotnet_style_prefer_auto_properties = true:silent | |||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent | |||
dotnet_style_prefer_conditional_expression_over_return = true:silent | |||
############################### | |||
# Naming Conventions # | |||
############################### | |||
# Style Definitions | |||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case | |||
# Use PascalCase for constant fields | |||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion | |||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields | |||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style | |||
dotnet_naming_symbols.constant_fields.applicable_kinds = field | |||
dotnet_naming_symbols.constant_fields.applicable_accessibilities = * | |||
dotnet_naming_symbols.constant_fields.required_modifiers = const | |||
############################### | |||
# C# Coding Conventions # | |||
############################### | |||
[*.cs] | |||
# var preferences | |||
csharp_style_var_for_built_in_types = true:silent | |||
csharp_style_var_when_type_is_apparent = true:silent | |||
csharp_style_var_elsewhere = true:silent | |||
# Expression-bodied members | |||
csharp_style_expression_bodied_methods = false:silent | |||
csharp_style_expression_bodied_constructors = false:silent | |||
csharp_style_expression_bodied_operators = false:silent | |||
csharp_style_expression_bodied_properties = true:silent | |||
csharp_style_expression_bodied_indexers = true:silent | |||
csharp_style_expression_bodied_accessors = true:silent | |||
# Pattern matching preferences | |||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion | |||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion | |||
# Null-checking preferences | |||
csharp_style_throw_expression = true:suggestion | |||
csharp_style_conditional_delegate_call = true:suggestion | |||
# Modifier preferences | |||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion | |||
# Expression-level preferences | |||
csharp_prefer_braces = true:silent | |||
csharp_style_deconstructed_variable_declaration = true:suggestion | |||
csharp_prefer_simple_default_expression = true:suggestion | |||
csharp_style_prefer_local_over_anonymous_function = true:suggestion | |||
csharp_style_inlined_variable_declaration = true:suggestion | |||
############################### | |||
# C# Formatting Rules # | |||
############################### | |||
# New line preferences | |||
csharp_new_line_before_open_brace = all | |||
csharp_new_line_before_else = true | |||
csharp_new_line_before_catch = true | |||
csharp_new_line_before_finally = true | |||
csharp_new_line_before_members_in_object_initializers = true | |||
csharp_new_line_before_members_in_anonymous_types = true | |||
csharp_new_line_between_query_expression_clauses = true | |||
# Indentation preferences | |||
csharp_indent_case_contents = true | |||
csharp_indent_switch_labels = true | |||
csharp_indent_labels = flush_left | |||
# Space preferences | |||
csharp_space_after_cast = false | |||
csharp_space_after_keywords_in_control_flow_statements = true | |||
csharp_space_between_method_call_parameter_list_parentheses = false | |||
csharp_space_between_method_declaration_parameter_list_parentheses = false | |||
csharp_space_between_parentheses = false | |||
csharp_space_before_colon_in_inheritance_clause = true | |||
csharp_space_after_colon_in_inheritance_clause = true | |||
csharp_space_around_binary_operators = before_and_after | |||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false | |||
csharp_space_between_method_call_name_and_opening_parenthesis = false | |||
csharp_space_between_method_call_empty_parameter_list_parentheses = false | |||
# Wrapping preferences | |||
csharp_preserve_single_line_statements = true | |||
csharp_preserve_single_line_blocks = true | |||
############################### | |||
# VB Coding Conventions # | |||
############################### | |||
[*.vb] | |||
# Modifier preferences | |||
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion |
@ -0,0 +1,17 @@ | |||
global using Autofac.Extensions.DependencyInjection; | |||
global using Microsoft.AspNetCore.Hosting; | |||
global using Microsoft.Extensions.Configuration; | |||
global using Microsoft.Extensions.Hosting; | |||
global using Ordering.BackgroundTasks.Extensions; | |||
global using Serilog; | |||
global using System.IO; | |||
global using HealthChecks.UI.Client; | |||
global using Microsoft.AspNetCore.Builder; | |||
global using Microsoft.AspNetCore.Diagnostics.HealthChecks; | |||
global using Microsoft.Extensions.Configuration; | |||
global using Microsoft.Extensions.DependencyInjection; | |||
global using Microsoft.Extensions.Logging; | |||
global using Ordering.BackgroundTasks.Extensions; | |||
global using Ordering.BackgroundTasks.Services; | |||
global using System; | |||
global using Ordering.BackgroundTasks; |
@ -1,35 +1,74 @@ | |||
using Autofac.Extensions.DependencyInjection; | |||
using Microsoft.AspNetCore.Hosting; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.Hosting; | |||
using Ordering.BackgroundTasks.Extensions; | |||
using Serilog; | |||
using System.IO; | |||
var appName = "Ordering.BackgroundTasks"; | |||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions | |||
{ | |||
Args = args, | |||
ApplicationName = typeof(Program).Assembly.FullName | |||
}); | |||
builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()); | |||
builder.Configuration.AddJsonFile("appsettings.json", optional: true); | |||
builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true); | |||
builder.Configuration.AddEnvironmentVariables(); | |||
builder.Host.UseSerilog(CreateSerilogLogger(builder.Configuration)); | |||
builder.Services.AddCustomHealthCheck(builder.Configuration) | |||
.Configure<BackgroundTaskSettings>(builder.Configuration) | |||
.AddOptions() | |||
.AddHostedService<GracePeriodManagerService>() | |||
.AddEventBus(builder.Configuration); | |||
var app = builder.Build(); | |||
if (app.Environment.IsDevelopment()) | |||
{ | |||
app.UseDeveloperExceptionPage(); | |||
} | |||
else | |||
{ | |||
app.UseExceptionHandler("/Home/Error"); | |||
} | |||
app.UseRouting(); | |||
namespace Ordering.BackgroundTasks | |||
app.MapHealthChecks("/hc", new HealthCheckOptions() | |||
{ | |||
public class Program | |||
{ | |||
public static readonly string AppName = typeof(Program).Assembly.GetName().Name; | |||
Predicate = _ => true, | |||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse | |||
}); | |||
app.MapHealthChecks("/liveness", new HealthCheckOptions | |||
{ | |||
Predicate = r => r.Name.Contains("self") | |||
}); | |||
public static void Main(string[] args) | |||
{ | |||
CreateHostBuilder(args).Run(); | |||
} | |||
try | |||
{ | |||
Log.Information("Starting web host ({ApplicationContext})...", Program.AppName); | |||
await app.RunAsync(); | |||
public static IHost CreateHostBuilder(string[] args) => | |||
Host.CreateDefaultBuilder(args) | |||
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) | |||
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>()) | |||
.ConfigureAppConfiguration((host, builder) => | |||
{ | |||
builder.SetBasePath(Directory.GetCurrentDirectory()); | |||
builder.AddJsonFile("appsettings.json", optional: true); | |||
builder.AddJsonFile($"appsettings.{host.HostingEnvironment.EnvironmentName}.json", optional: true); | |||
builder.AddEnvironmentVariables(); | |||
builder.AddCommandLine(args); | |||
}) | |||
.ConfigureLogging((host, builder) => builder.UseSerilog(host.Configuration).AddSerilog()) | |||
.Build(); | |||
} | |||
return 0; | |||
} | |||
catch (Exception ex) | |||
{ | |||
Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", Program.AppName); | |||
return 1; | |||
} | |||
finally | |||
{ | |||
Log.CloseAndFlush(); | |||
} | |||
Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) | |||
{ | |||
var seqServerUrl = configuration["Serilog:SeqServerUrl"]; | |||
var logstashUrl = configuration["Serilog:LogstashgUrl"]; | |||
return new LoggerConfiguration() | |||
.MinimumLevel.Verbose() | |||
.Enrich.WithProperty("ApplicationContext", Program.AppName) | |||
.Enrich.FromLogContext() | |||
.WriteTo.Console() | |||
.WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) | |||
.WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl, null) | |||
.ReadFrom.Configuration(configuration) | |||
.CreateLogger(); | |||
} | |||
public partial class Program | |||
{ | |||
public static string Namespace = typeof(Program).Assembly.GetName().Name; | |||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); | |||
} |
@ -1,48 +0,0 @@ | |||
namespace Ordering.BackgroundTasks | |||
{ | |||
using HealthChecks.UI.Client; | |||
using Microsoft.AspNetCore.Builder; | |||
using Microsoft.AspNetCore.Diagnostics.HealthChecks; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Logging; | |||
using Ordering.BackgroundTasks.Extensions; | |||
using Ordering.BackgroundTasks.Services; | |||
public class Startup | |||
{ | |||
public Startup(IConfiguration configuration) | |||
{ | |||
Configuration = configuration; | |||
} | |||
public IConfiguration Configuration { get; } | |||
public virtual void ConfigureServices(IServiceCollection services) | |||
{ | |||
services.AddCustomHealthCheck(this.Configuration) | |||
.Configure<BackgroundTaskSettings>(this.Configuration) | |||
.AddOptions() | |||
.AddHostedService<GracePeriodManagerService>() | |||
.AddEventBus(this.Configuration); | |||
} | |||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) | |||
{ | |||
app.UseRouting(); | |||
app.UseEndpoints(endpoints => | |||
{ | |||
endpoints.MapHealthChecks("/hc", new HealthCheckOptions() | |||
{ | |||
Predicate = _ => true, | |||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse | |||
}); | |||
endpoints.MapHealthChecks("/liveness", new HealthCheckOptions | |||
{ | |||
Predicate = r => r.Name.Contains("self") | |||
}); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,132 @@ | |||
############################### | |||
# Core EditorConfig Options # | |||
############################### | |||
root = true | |||
# All files | |||
[*] | |||
indent_style = space | |||
# XML project files | |||
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] | |||
indent_size = 2 | |||
# XML config files | |||
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] | |||
indent_size = 2 | |||
# Code files | |||
[*.{cs,csx,vb,vbx}] | |||
indent_size = 4 | |||
insert_final_newline = true | |||
charset = utf-8-bom | |||
############################### | |||
# .NET Coding Conventions # | |||
############################### | |||
[*.{cs,vb}] | |||
# Organize usings | |||
dotnet_sort_system_directives_first = true | |||
# this. preferences | |||
dotnet_style_qualification_for_field = false:silent | |||
dotnet_style_qualification_for_property = false:silent | |||
dotnet_style_qualification_for_method = false:silent | |||
dotnet_style_qualification_for_event = false:silent | |||
# Language keywords vs BCL types preferences | |||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent | |||
dotnet_style_predefined_type_for_member_access = true:silent | |||
# Parentheses preferences | |||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent | |||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent | |||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent | |||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent | |||
# Modifier preferences | |||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent | |||
dotnet_style_readonly_field = true:suggestion | |||
# Expression-level preferences | |||
dotnet_style_object_initializer = true:suggestion | |||
dotnet_style_collection_initializer = true:suggestion | |||
dotnet_style_explicit_tuple_names = true:suggestion | |||
dotnet_style_null_propagation = true:suggestion | |||
dotnet_style_coalesce_expression = true:suggestion | |||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent | |||
dotnet_style_prefer_inferred_tuple_names = true:suggestion | |||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion | |||
dotnet_style_prefer_auto_properties = true:silent | |||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent | |||
dotnet_style_prefer_conditional_expression_over_return = true:silent | |||
############################### | |||
# Naming Conventions # | |||
############################### | |||
# Style Definitions | |||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case | |||
# Use PascalCase for constant fields | |||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion | |||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields | |||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style | |||
dotnet_naming_symbols.constant_fields.applicable_kinds = field | |||
dotnet_naming_symbols.constant_fields.applicable_accessibilities = * | |||
dotnet_naming_symbols.constant_fields.required_modifiers = const | |||
############################### | |||
# C# Coding Conventions # | |||
############################### | |||
[*.cs] | |||
# var preferences | |||
csharp_style_var_for_built_in_types = true:silent | |||
csharp_style_var_when_type_is_apparent = true:silent | |||
csharp_style_var_elsewhere = true:silent | |||
# Expression-bodied members | |||
csharp_style_expression_bodied_methods = false:silent | |||
csharp_style_expression_bodied_constructors = false:silent | |||
csharp_style_expression_bodied_operators = false:silent | |||
csharp_style_expression_bodied_properties = true:silent | |||
csharp_style_expression_bodied_indexers = true:silent | |||
csharp_style_expression_bodied_accessors = true:silent | |||
# Pattern matching preferences | |||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion | |||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion | |||
# Null-checking preferences | |||
csharp_style_throw_expression = true:suggestion | |||
csharp_style_conditional_delegate_call = true:suggestion | |||
# Modifier preferences | |||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion | |||
# Expression-level preferences | |||
csharp_prefer_braces = true:silent | |||
csharp_style_deconstructed_variable_declaration = true:suggestion | |||
csharp_prefer_simple_default_expression = true:suggestion | |||
csharp_style_prefer_local_over_anonymous_function = true:suggestion | |||
csharp_style_inlined_variable_declaration = true:suggestion | |||
############################### | |||
# C# Formatting Rules # | |||
############################### | |||
# New line preferences | |||
csharp_new_line_before_open_brace = all | |||
csharp_new_line_before_else = true | |||
csharp_new_line_before_catch = true | |||
csharp_new_line_before_finally = true | |||
csharp_new_line_before_members_in_object_initializers = true | |||
csharp_new_line_before_members_in_anonymous_types = true | |||
csharp_new_line_between_query_expression_clauses = true | |||
# Indentation preferences | |||
csharp_indent_case_contents = true | |||
csharp_indent_switch_labels = true | |||
csharp_indent_labels = flush_left | |||
# Space preferences | |||
csharp_space_after_cast = false | |||
csharp_space_after_keywords_in_control_flow_statements = true | |||
csharp_space_between_method_call_parameter_list_parentheses = false | |||
csharp_space_between_method_declaration_parameter_list_parentheses = false | |||
csharp_space_between_parentheses = false | |||
csharp_space_before_colon_in_inheritance_clause = true | |||
csharp_space_after_colon_in_inheritance_clause = true | |||
csharp_space_around_binary_operators = before_and_after | |||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false | |||
csharp_space_between_method_call_name_and_opening_parenthesis = false | |||
csharp_space_between_method_call_empty_parameter_list_parentheses = false | |||
# Wrapping preferences | |||
csharp_preserve_single_line_statements = true | |||
csharp_preserve_single_line_blocks = true | |||
############################### | |||
# VB Coding Conventions # | |||
############################### | |||
[*.vb] | |||
# Modifier preferences | |||
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion |
@ -1,251 +0,0 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub; | |||
public class Startup | |||
{ | |||
public Startup(IConfiguration configuration) | |||
{ | |||
Configuration = configuration; | |||
} | |||
public IConfiguration Configuration { get; } | |||
// This method gets called by the runtime. Use this method to add services to the container. | |||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 | |||
public IServiceProvider ConfigureServices(IServiceCollection services) | |||
{ | |||
services | |||
.AddCustomHealthCheck(Configuration) | |||
.AddCors(options => | |||
{ | |||
options.AddPolicy("CorsPolicy", | |||
builder => builder | |||
.AllowAnyMethod() | |||
.AllowAnyHeader() | |||
.SetIsOriginAllowed((host) => true) | |||
.AllowCredentials()); | |||
}); | |||
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString) | |||
{ | |||
services | |||
.AddSignalR() | |||
.AddStackExchangeRedis(Configuration["SignalrStoreConnectionString"]); | |||
} | |||
else | |||
{ | |||
services.AddSignalR(); | |||
} | |||
if (Configuration.GetValue<bool>("AzureServiceBusEnabled")) | |||
{ | |||
services.AddSingleton<IServiceBusPersisterConnection>(sp => | |||
{ | |||
var serviceBusConnectionString = Configuration["EventBusConnection"]; | |||
var subscriptionClientName = Configuration["SubscriptionClientName"]; | |||
return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); | |||
}); | |||
} | |||
else | |||
{ | |||
services.AddSingleton<IRabbitMQPersistentConnection>(sp => | |||
{ | |||
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); | |||
var factory = new ConnectionFactory() | |||
{ | |||
HostName = Configuration["EventBusConnection"], | |||
DispatchConsumersAsync = true | |||
}; | |||
if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) | |||
{ | |||
factory.UserName = Configuration["EventBusUserName"]; | |||
} | |||
if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) | |||
{ | |||
factory.Password = Configuration["EventBusPassword"]; | |||
} | |||
var retryCount = 5; | |||
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) | |||
{ | |||
retryCount = int.Parse(Configuration["EventBusRetryCount"]); | |||
} | |||
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); | |||
}); | |||
} | |||
ConfigureAuthService(services); | |||
RegisterEventBus(services); | |||
services.AddOptions(); | |||
//configure autofac | |||
var container = new ContainerBuilder(); | |||
container.RegisterModule(new ApplicationModule()); | |||
container.Populate(services); | |||
return new AutofacServiceProvider(container.Build()); | |||
} | |||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) | |||
{ | |||
//loggerFactory.AddConsole(Configuration.GetSection("Logging")); | |||
//loggerFactory.AddDebug(); | |||
//loggerFactory.AddAzureWebAppDiagnostics(); | |||
//loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); | |||
var pathBase = Configuration["PATH_BASE"]; | |||
if (!string.IsNullOrEmpty(pathBase)) | |||
{ | |||
loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase); | |||
app.UsePathBase(pathBase); | |||
} | |||
app.UseRouting(); | |||
app.UseCors("CorsPolicy"); | |||
app.UseAuthentication(); | |||
app.UseAuthorization(); | |||
app.UseEndpoints(endpoints => | |||
{ | |||
endpoints.MapHealthChecks("/hc", new HealthCheckOptions() | |||
{ | |||
Predicate = _ => true, | |||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse | |||
}); | |||
endpoints.MapHealthChecks("/liveness", new HealthCheckOptions | |||
{ | |||
Predicate = r => r.Name.Contains("self") | |||
}); | |||
endpoints.MapHub<NotificationsHub>("/hub/notificationhub"); | |||
}); | |||
ConfigureEventBus(app); | |||
} | |||
private void ConfigureEventBus(IApplicationBuilder app) | |||
{ | |||
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>(); | |||
eventBus.Subscribe<OrderStatusChangedToAwaitingValidationIntegrationEvent, OrderStatusChangedToAwaitingValidationIntegrationEventHandler>(); | |||
eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>(); | |||
eventBus.Subscribe<OrderStatusChangedToStockConfirmedIntegrationEvent, OrderStatusChangedToStockConfirmedIntegrationEventHandler>(); | |||
eventBus.Subscribe<OrderStatusChangedToShippedIntegrationEvent, OrderStatusChangedToShippedIntegrationEventHandler>(); | |||
eventBus.Subscribe<OrderStatusChangedToCancelledIntegrationEvent, OrderStatusChangedToCancelledIntegrationEventHandler>(); | |||
eventBus.Subscribe<OrderStatusChangedToSubmittedIntegrationEvent, OrderStatusChangedToSubmittedIntegrationEventHandler>(); | |||
} | |||
private void ConfigureAuthService(IServiceCollection services) | |||
{ | |||
// prevent from mapping "sub" claim to nameidentifier. | |||
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); | |||
var identityUrl = Configuration.GetValue<string>("IdentityUrl"); | |||
services.AddAuthentication("Bearer").AddJwtBearer(options => | |||
{ | |||
options.Authority = identityUrl; | |||
options.RequireHttpsMetadata = false; | |||
options.Audience = "orders.signalrhub"; | |||
options.TokenValidationParameters.ValidateAudience = false; | |||
options.Events = new JwtBearerEvents | |||
{ | |||
OnMessageReceived = context => | |||
{ | |||
var accessToken = context.Request.Query["access_token"]; | |||
var path = context.HttpContext.Request.Path; | |||
if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/hub/notificationhub"))) | |||
{ | |||
context.Token = accessToken; | |||
} | |||
return Task.CompletedTask; | |||
} | |||
}; | |||
}); | |||
services.AddAuthorization(options => | |||
{ | |||
options.AddPolicy("ApiScope", policy => | |||
{ | |||
policy.RequireAuthenticatedUser(); | |||
policy.RequireClaim("scope", "orders.signalrhub"); | |||
}); | |||
}); | |||
} | |||
private void RegisterEventBus(IServiceCollection services) | |||
{ | |||
if (Configuration.GetValue<bool>("AzureServiceBusEnabled")) | |||
{ | |||
services.AddSingleton<IEventBus, EventBusServiceBus>(sp => | |||
{ | |||
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>(); | |||
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>(); | |||
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | |||
string subscriptionName = Configuration["SubscriptionClientName"]; | |||
return new EventBusServiceBus(serviceBusPersisterConnection, logger, | |||
eventBusSubcriptionsManager, sp, subscriptionName); | |||
}); | |||
} | |||
else | |||
{ | |||
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => | |||
{ | |||
var subscriptionClientName = Configuration["SubscriptionClientName"]; | |||
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>(); | |||
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>(); | |||
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | |||
var retryCount = 5; | |||
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) | |||
{ | |||
retryCount = int.Parse(Configuration["EventBusRetryCount"]); | |||
} | |||
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, sp, eventBusSubcriptionsManager, subscriptionClientName, retryCount); | |||
}); | |||
} | |||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>(); | |||
} | |||
} | |||
public static class CustomExtensionMethods | |||
{ | |||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
var hcBuilder = services.AddHealthChecks(); | |||
hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); | |||
if (configuration.GetValue<bool>("AzureServiceBusEnabled")) | |||
{ | |||
hcBuilder | |||
.AddAzureServiceBusTopic( | |||
configuration["EventBusConnection"], | |||
topicName: "eshop_event_bus", | |||
name: "signalr-servicebus-check", | |||
tags: new string[] { "servicebus" }); | |||
} | |||
else | |||
{ | |||
hcBuilder | |||
.AddRabbitMQ( | |||
$"amqp://{configuration["EventBusConnection"]}", | |||
name: "signalr-rabbitmqbus-check", | |||
tags: new string[] { "rabbitmqbus" }); | |||
} | |||
return services; | |||
} | |||
} |