diff --git a/README.md b/README.md
index e493e8c7..0b0fc551 100644
--- a/README.md
+++ b/README.md
@@ -73,10 +73,10 @@ You can use **Docker compose** to setup the infrastructure components just by ru
``` bash
cd ./containers
-# Setup the infrastructure
+# Setup the infrastructure. Use this file to setup the basic infrastructure components (RabbitMQ, MongoDB)
docker compose -f ./infrastructure.yml --env-file ./.env --project-name genocs up -d
-# Use this file only in case you want to setup Redis and Postgres db (no need if you use mongo)
+# Use this file only in case you want to setup Redis and PostgreSQL (no need if you use MongoDB)
docker compose -f ./infrastructure-db.yml --env-file ./.env --project-name genocs up -d
# Use this file only in case you want to setup monitoring infrastructure components (Prometheus, Grafana, InfluxDB, Jaeger, Seq)
@@ -88,13 +88,13 @@ docker compose -f ./infrastructure-scaling.yml --env-file ./.env --project-name
# Use this file only in case you want to setup security infrastructure components (Vault)
docker compose -f ./infrastructure-security.yml --env-file ./.env --project-name genocs up -d
-# Use this file only in case you want to setup sqlserver database (no need if you use postgres)
+# Use this file only in case you want to setup sqlserver database (no need if you use PostgreSQL)
docker compose -f ./infrastructure-sqlserver.yml --env-file ./.env --project-name genocs up -d
-# Use this file only in case you want to setup mySql database (no need if you use postgres)
+# Use this file only in case you want to setup mySql database (no need if you use PostgreSQL)
docker compose -f ./infrastructure-mysql.yml --env-file ./.env --project-name genocs up -d
-# Use this file only in case you want to setup oracle database (no need if you use postgres)
+# Use this file only in case you want to setup oracle database (no need if you use PostgreSQL)
docker compose -f ./infrastructure-oracle.yml --env-file ./.env --project-name genocs up -d
# Use this file only in case you want to setup elk stack
@@ -104,18 +104,24 @@ docker compose -f ./infrastructure-elk.yml --env-file ./.env --project-name geno
docker compose -f ./infrastructure-ml.yml --env-file ./.env --project-name genocs up -d
```
-`infrastructure-bare.yml` allows to install the basic infrastructure components. They are:
+`infrastructure.yml` allows to install the basic infrastructure components. They are:
- [RabbitMQ](https://rabbitmq.com)
- [Redis](https://redis.io)
- [MongoDB](https://mongodb.com)
-- [Postgres](https://www.postgresql.org/).
+- [Postgres](https://www.postgresql.org/)
-You can run them locally:
+
+`infrastructure-db.yml` allows to install Redis and PostgreSQL
+- [Redis](https://redis.io)
+- [Postgres](https://www.postgresql.org/)
+
+
+You can check them locally:
- [RabbitMQ](http://localhost:15672): `localhost:15672`
-- Redis: `localhost:6379`
-- MongoDB: `localhost:27017`
-- Postgres: `localhost:5432`
+- Redis: `TCP:localhost:6379`
+- MongoDB: `TCP:localhost:27017`
+- Postgres: `TCP:localhost:5432`
`infrastructure-monitoring.yml` allows to install the monitoring infrastructure components. They are:
@@ -126,7 +132,7 @@ You can run them locally:
- [Seq](https://datalust.co/seq)
-You can run them locally:
+You can find the console locally at:
- [Prometheus](localhost:9090): `localhost:9090`
- [Grafana](localhost:3000): `localhost:3000`
@@ -135,9 +141,13 @@ You can run them locally:
- [Seq](localhost:5341): `localhost:5341`
-`infrastructure-scaling.yml` allows to install the scaling infrastructure components. They are:
-- Fabio
-- Consul
+`infrastructure-scaling.yml` allows to install the scaling infrastructure components composed by Fabio and Consul.
+
+- [Fabio](https://fabiolb.net/)
+- [Consul](https://www.consul.io/)
+
+
+
`infrastructure-security.yml` allows to install the security infrastructure components.
@@ -185,7 +195,7 @@ Use [**api-workbench**](./api-workbench.rest) inside Visual Studio code with [RE
"enabled": false,
"url": "http://localhost:8500",
"service": "demo-service",
- "address": "docker.for.win.localhost",
+ "address": "docker.for.mac.localhost",
"port": "5070",
"pingEnabled": true,
"pingEndpoint": "health",
diff --git a/containers/.env b/containers/.env
new file mode 100644
index 00000000..407449c8
--- /dev/null
+++ b/containers/.env
@@ -0,0 +1,2 @@
+# This file is a template for the .env file that is used by the docker-compose.yml file.
+POSTGRES_PASSWORD=mySecretPassword1234!
diff --git a/genocs.sln b/genocs.sln
index 16581cec..dac56edb 100644
--- a/genocs.sln
+++ b/genocs.sln
@@ -120,9 +120,11 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{B184733D-2415-4517-BC65-26ED22EEB2C2}"
ProjectSection(SolutionItems) = preProject
src\apps\apigateway.dockerfile = src\apps\apigateway.dockerfile
- src\apps\application-docker-compose.yml = src\apps\application-docker-compose.yml
+ src\apps\docker-compose.override.yml = src\apps\docker-compose.override.yml
+ src\apps\docker-compose.yml = src\apps\docker-compose.yml
src\apps\identity-webapi.dockerfile = src\apps\identity-webapi.dockerfile
src\apps\order-webapi.dockerfile = src\apps\order-webapi.dockerfile
+ src\apps\local.env = src\apps\local.env
src\apps\product-webapi.dockerfile = src\apps\product-webapi.dockerfile
src\apps\signalr-webapi.dockerfile = src\apps\signalr-webapi.dockerfile
EndProjectSection
diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj
index 20296ed5..f8482eb1 100644
--- a/src/Genocs.Auth/Genocs.Auth.csproj
+++ b/src/Genocs.Auth/Genocs.Auth.csproj
@@ -24,8 +24,8 @@
-
-
+
+
diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj
index 0e849290..5c297bb3 100644
--- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj
+++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj
index 2f1181c7..5f75ee48 100644
--- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj
+++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj
@@ -12,8 +12,8 @@
-
-
+
+
diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj
index 2e1f5546..85e7e8b6 100644
--- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj
+++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj
@@ -20,22 +20,22 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs
index 8b850a98..33d6eedd 100644
--- a/src/Genocs.Core.Demo.WebApi/Program.cs
+++ b/src/Genocs.Core.Demo.WebApi/Program.cs
@@ -20,10 +20,7 @@
.UseAzureKeyVault()
.UseLogging();
-var services = builder.Services;
-
-services
- .AddGenocs(builder.Configuration)
+builder.AddGenocs()
.AddJwt()
// .AddOpenIdJwt()
.AddOpenTelemetry()
@@ -32,6 +29,8 @@
.AddApplicationServices()
.Build();
+var services = builder.Services;
+
services.AddCors();
services.AddControllers().AddJsonOptions(x =>
{
diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj
index a726e6f8..f9b2dcbc 100644
--- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj
+++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj
@@ -14,9 +14,9 @@
-
-
-
+
+
+
diff --git a/src/Genocs.Core.Demo.Worker/appsettings.json b/src/Genocs.Core.Demo.Worker/appsettings.json
index 9ebf71e1..6391c0f0 100644
--- a/src/Genocs.Core.Demo.Worker/appsettings.json
+++ b/src/Genocs.Core.Demo.Worker/appsettings.json
@@ -43,10 +43,10 @@
"enabled": false,
"url": "http://localhost:8500",
"service": "users-service",
- "address": "docker.for.win.localhost",
+ "address": "docker.for.mac.localhost",
"port": "5070",
"pingEnabled": true,
- "pingEndpoint": "ping",
+ "pingEndpoint": "healthz",
"pingInterval": 3,
"removeAfterInterval": 3
},
@@ -99,7 +99,7 @@
"interval": "day"
},
"seq": {
- "enabled": false,
+ "enabled": true,
"url": "http://localhost:5341",
"apiKey": "secret"
},
diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs
index c389cd7e..4c82f9eb 100644
--- a/src/Genocs.Core/Builders/Extensions.cs
+++ b/src/Genocs.Core/Builders/Extensions.cs
@@ -20,6 +20,7 @@ public static IGenocsBuilder AddGenocs(this WebApplicationBuilder builder)
{
// Create the builder
IGenocsBuilder gnxBuilder = GenocsBuilder.Create(builder);
+ Setup(gnxBuilder);
return gnxBuilder;
}
@@ -33,32 +34,7 @@ public static IGenocsBuilder AddGenocs(this IServiceCollection services, IConfig
{
// Create the builder
IGenocsBuilder builder = GenocsBuilder.Create(services, configuration);
-
- // Get the application options
- AppOptions settings = builder.GetOptions(AppOptions.Position);
- builder.Services.AddSingleton(settings);
-
- // Add the health checks
- builder.Services
- .AddHealthChecks()
- .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); // Add a default liveness check to ensure app is responsive
-
- builder.Services.AddMemoryCache();
-
- builder.Services.AddSingleton();
-
- if (!settings.DisplayBanner || string.IsNullOrWhiteSpace(settings.Name))
- {
- return builder;
- }
-
- string version = settings.DisplayVersion ? $" {settings.Version}" : string.Empty;
- Console.WriteLine(Figgle.FiggleFonts.Doom.Render(settings.Name + version));
- ConsoleColor current = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Blue;
- Console.WriteLine("Runtime Version: {0}", Environment.Version.ToString());
- Console.ForegroundColor = current;
-
+ Setup(builder);
return builder;
}
@@ -160,6 +136,15 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app)
return app;
}
+ // All health checks must pass for app to be considered ready to accept traffic after starting
+ app.MapHealthChecks("/healthz");
+
+ // Only health checks tagged with the "live" tag must pass for app to be considered alive
+ app.MapHealthChecks("/alive", new HealthCheckOptions
+ {
+ Predicate = r => r.Tags.Contains("live")
+ });
+
app.MapGet("/", async context =>
{
// Get the Entry Assembly Name and Version
@@ -170,16 +155,35 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app)
await context.Response.WriteAsync(context.RequestServices.GetService()?.Name ?? message);
});
+ return app;
+ }
- // All health checks must pass for app to be considered ready to accept traffic after starting
- app.MapHealthChecks("/health");
+ private static void Setup(IGenocsBuilder builder)
+ {
+ // Get the application options
+ AppOptions settings = builder.GetOptions(AppOptions.Position);
+ builder.Services.AddSingleton(settings);
- // Only health checks tagged with the "live" tag must pass for app to be considered alive
- app.MapHealthChecks("/alive", new HealthCheckOptions
+ if (!settings.DisplayBanner || string.IsNullOrWhiteSpace(settings.Name))
{
- Predicate = r => r.Tags.Contains("live")
- });
+ return;
+ }
- return app;
+ string version = settings.DisplayVersion ? $" {settings.Version}" : string.Empty;
+ Console.WriteLine(Figgle.FiggleFonts.Doom.Render(settings.Name + version));
+ ConsoleColor current = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Blue;
+ Console.WriteLine("Runtime Version: {0}", Environment.Version.ToString());
+ Console.ForegroundColor = current;
+
+ // Add the health checks
+ builder.Services
+ .AddHealthChecks();
+
+ // .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); // Add a default liveness check to ensure app is responsive
+
+ builder.Services.AddMemoryCache();
+
+ builder.Services.AddSingleton();
}
}
\ No newline at end of file
diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj
index 361e1a50..3d789e37 100644
--- a/src/Genocs.Core/Genocs.Core.csproj
+++ b/src/Genocs.Core/Genocs.Core.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/src/Genocs.Discovery.Consul/Extensions.cs b/src/Genocs.Discovery.Consul/Extensions.cs
index 6a16f2be..a92d068c 100644
--- a/src/Genocs.Discovery.Consul/Extensions.cs
+++ b/src/Genocs.Discovery.Consul/Extensions.cs
@@ -80,7 +80,7 @@ public static void AddConsulHttpClient(this IGenocsBuilder builder, string clien
c.GetRequiredService(),
c.GetRequiredService(), serviceName, true));
- private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulOptions options)
+ private static ServiceRegistration? CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulOptions options)
{
bool enabled = options.Enabled;
string? consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant();
diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj
index 9055f004..1b289f3d 100644
--- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj
+++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj
@@ -24,12 +24,11 @@
-
-
+
+
-
diff --git a/src/Genocs.Discovery.Consul/IConsulService.cs b/src/Genocs.Discovery.Consul/IConsulService.cs
index 9c405e4e..4f92966f 100644
--- a/src/Genocs.Discovery.Consul/IConsulService.cs
+++ b/src/Genocs.Discovery.Consul/IConsulService.cs
@@ -6,5 +6,5 @@ public interface IConsulService
{
Task RegisterServiceAsync(ServiceRegistration registration);
Task DeregisterServiceAsync(string id);
- Task> GetServiceAgentsAsync(string? service = null);
+ Task?> GetServiceAgentsAsync(string? service = null);
}
\ No newline at end of file
diff --git a/src/Genocs.Discovery.Consul/Services/ConsulService.cs b/src/Genocs.Discovery.Consul/Services/ConsulService.cs
index 0f32f333..05a4221e 100644
--- a/src/Genocs.Discovery.Consul/Services/ConsulService.cs
+++ b/src/Genocs.Discovery.Consul/Services/ConsulService.cs
@@ -21,7 +21,7 @@ public Task RegisterServiceAsync(ServiceRegistration regist
public Task DeregisterServiceAsync(string id)
=> _client.PutAsync(GetEndpoint($"agent/service/deregister/{id}"), EmptyRequest);
- public async Task> GetServiceAgentsAsync(string? service = null)
+ public async Task?> GetServiceAgentsAsync(string? service = null)
{
string filter = string.IsNullOrWhiteSpace(service) ? string.Empty : $"?filter=Service==\"{service}\"";
var response = await _client.GetAsync(GetEndpoint($"agent/services{filter}"));
@@ -38,5 +38,6 @@ public async Task> GetServiceAgentsAsync(strin
private static StringContent GetPayload(object request)
=> new(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
- private static string GetEndpoint(string endpoint) => $"{Version}/{endpoint}";
+ private static string GetEndpoint(string endpoint)
+ => $"{Version}/{endpoint}";
}
\ No newline at end of file
diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj
index a6aacfd6..fbd22554 100644
--- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj
+++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj
@@ -25,10 +25,10 @@
-
-
-
-
+
+
+
+
diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj
index 001692e7..bba35e2c 100644
--- a/src/Genocs.HTTP/Genocs.HTTP.csproj
+++ b/src/Genocs.HTTP/Genocs.HTTP.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/src/Genocs.HTTP/GenocsHttpClient.cs b/src/Genocs.HTTP/GenocsHttpClient.cs
index 63d02470..7ccefdad 100644
--- a/src/Genocs.HTTP/GenocsHttpClient.cs
+++ b/src/Genocs.HTTP/GenocsHttpClient.cs
@@ -170,7 +170,8 @@ public void SetHeaders(IDictionary headers)
}
}
- public void SetHeaders(Action headers) => headers?.Invoke(_client.DefaultRequestHeaders);
+ public void SetHeaders(Action headers)
+ => headers?.Invoke(_client.DefaultRequestHeaders);
protected virtual async Task SendAsync(string uri, Method method, HttpContent? content = null, IHttpClientSerializer? serializer = null)
{
@@ -241,7 +242,7 @@ protected virtual Task GetResponseAsync(string uri, Method
return content;
}
- protected async Task DeserializeJsonFromStream(Stream stream, IHttpClientSerializer? serializer = null)
+ protected async Task DeserializeJsonFromStream(Stream stream, IHttpClientSerializer? serializer = null)
{
if (stream is null || stream.CanRead is false)
{
diff --git a/src/Genocs.HTTP/HttpResult.cs b/src/Genocs.HTTP/HttpResult.cs
index e838db6e..8f3b4c6a 100644
--- a/src/Genocs.HTTP/HttpResult.cs
+++ b/src/Genocs.HTTP/HttpResult.cs
@@ -1,14 +1,8 @@
namespace Genocs.HTTP;
-public class HttpResult
+public class HttpResult(T result, HttpResponseMessage response)
{
- public T Result { get; }
- public HttpResponseMessage Response { get; }
+ public T Result { get; } = result;
+ public HttpResponseMessage Response { get; } = response;
public bool HasResult => Result is not null;
-
- public HttpResult(T result, HttpResponseMessage response)
- {
- Result = result;
- Response = response;
- }
}
\ No newline at end of file
diff --git a/src/Genocs.LoadBalancing.Fabio/Extensions.cs b/src/Genocs.LoadBalancing.Fabio/Extensions.cs
index ba3ded7a..2225d5ac 100644
--- a/src/Genocs.LoadBalancing.Fabio/Extensions.cs
+++ b/src/Genocs.LoadBalancing.Fabio/Extensions.cs
@@ -37,22 +37,32 @@ public static IGenocsBuilder AddFabio(
b => b.AddConsul(consulOptions, httpClientOptions));
}
- public static IGenocsBuilder AddFabio(this IGenocsBuilder builder,
- Func buildOptions,
- Func buildConsulOptions,
- HttpClientOptions httpClientOptions)
+ public static IGenocsBuilder AddFabio(
+ this IGenocsBuilder builder,
+ Func buildOptions,
+ Func buildConsulOptions,
+ HttpClientOptions httpClientOptions)
{
var fabioOptions = buildOptions(new FabioOptionsBuilder()).Build();
- return builder.AddFabio(fabioOptions, httpClientOptions,
- b => b.AddConsul(buildConsulOptions, httpClientOptions));
+
+ return builder.AddFabio(
+ fabioOptions,
+ httpClientOptions,
+ b => b.AddConsul(buildConsulOptions, httpClientOptions));
}
- public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioOptions fabioOptions,
- ConsulOptions consulOptions, HttpClientOptions httpClientOptions)
+ public static IGenocsBuilder AddFabio(
+ this IGenocsBuilder builder,
+ FabioOptions fabioOptions,
+ ConsulOptions consulOptions,
+ HttpClientOptions httpClientOptions)
=> builder.AddFabio(fabioOptions, httpClientOptions, b => b.AddConsul(consulOptions, httpClientOptions));
- private static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioOptions fabioOptions,
- HttpClientOptions httpClientOptions, Action registerConsul)
+ private static IGenocsBuilder AddFabio(
+ this IGenocsBuilder builder,
+ FabioOptions fabioOptions,
+ HttpClientOptions httpClientOptions,
+ Action registerConsul)
{
registerConsul(builder);
builder.Services.AddSingleton(fabioOptions);
@@ -64,19 +74,24 @@ private static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioOptions
if (httpClientOptions.Type?.ToLowerInvariant() == "fabio")
{
- builder.Services.AddTransient();
- builder.Services.AddHttpClient("fabio-http")
- .AddHttpMessageHandler();
+ builder.Services
+ .AddTransient();
+ builder.Services
+ .AddHttpClient("fabio-http")
+ .AddHttpMessageHandler();
builder.RemoveHttpClient();
- builder.Services.AddHttpClient("fabio")
- .AddHttpMessageHandler();
+
+ builder.Services
+ .AddHttpClient("fabio")
+ .AddHttpMessageHandler();
}
using var serviceProvider = builder.Services.BuildServiceProvider();
var registration = serviceProvider.GetRequiredService();
var tags = GetFabioTags(registration.Name, fabioOptions.Service);
+
if (registration.Tags is null)
{
registration.Tags = tags;
@@ -91,12 +106,17 @@ private static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioOptions
return builder;
}
- public static void AddFabioHttpClient(this IGenocsBuilder builder, string clientName, string serviceName)
- => builder.Services.AddHttpClient(clientName)
- .AddHttpMessageHandler(c => new FabioMessageHandler(c.GetRequiredService(), serviceName));
-
- private static void UpdateConsulRegistration(this IServiceCollection services,
- ServiceRegistration registration)
+ public static void AddFabioHttpClient(
+ this IGenocsBuilder builder,
+ string clientName,
+ string serviceName)
+ => builder.Services
+ .AddHttpClient(clientName)
+ .AddHttpMessageHandler(c => new FabioMessageHandler(c.GetRequiredService(), serviceName));
+
+ private static void UpdateConsulRegistration(
+ this IServiceCollection services,
+ ServiceRegistration registration)
{
var serviceDescriptor = services.FirstOrDefault(sd => sd.ServiceType == typeof(ServiceRegistration));
services.Remove(serviceDescriptor);
diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj
index d81ff3b4..0f2f27a5 100644
--- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj
+++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj
@@ -24,13 +24,8 @@
-
-
-
+
+
+
-
-
-
-
-
diff --git a/src/Genocs.LoadBalancing.Fabio/IFabioHttpClient.cs b/src/Genocs.LoadBalancing.Fabio/IFabioHttpClient.cs
index 2968e1f4..6e08425b 100644
--- a/src/Genocs.LoadBalancing.Fabio/IFabioHttpClient.cs
+++ b/src/Genocs.LoadBalancing.Fabio/IFabioHttpClient.cs
@@ -2,6 +2,9 @@
namespace Genocs.LoadBalancing.Fabio;
+///
+/// The Fabio HTTP client interface definition.
+///
public interface IFabioHttpClient : IHttpClient
{
}
\ No newline at end of file
diff --git a/src/Genocs.LoadBalancing.Fabio/README_NUGET.md b/src/Genocs.LoadBalancing.Fabio/README_NUGET.md
index 6ffbc96c..f6a7d24a 100644
--- a/src/Genocs.LoadBalancing.Fabio/README_NUGET.md
+++ b/src/Genocs.LoadBalancing.Fabio/README_NUGET.md
@@ -1,11 +1,13 @@
-# .NET query builder library
+# Genocs Load Balancing library
+
+This package contains support for load balancing functionality by means of Fabio.
-This package contains a query builder that is agnostic about the persistence layer. The library is designed by Genocs.
-The libraries are built using .NET standard 2.1.
## Description
-Persistence agnostic query builder service.
+Fabio is a fast, modern, zero-conf load balancing HTTP(S) router for deploying microservices managed by consul.
+
+The libraries are built using .NET Core.
## Support
@@ -14,52 +16,3 @@ Please check the GitHub repository getting more info.
## Release notes
-
-### [2024-01-23] 5.0.6
-- Refactory Settings
-- Updated nuget packages
-
-### [2023-11-25] 5.0.5
-- Moved to NET8
-
-### [yyyy-mm-dd] 5.0.4
--
-
-### [yyyy-mm-dd] 5.0.3
--
-
-### [yyyy-mm-dd] 5.0.2
--
-
-### [yyyy-mm-dd] 5.0.1
--
-
-### [2023-11-25] 5.0.0
-- Moved to NET8
-
-### [2023-10-13] 5.0.0-preview.5.0
-- Added [editorconfig](https://editorconfig.org/)
-- Added StyleCop
-- Updated logo
-- Updated readme
-
-### [2023-03-12] 5.0.0-preview.4.0
-- Implemented MongoDB repository interfaces
-
-### [2023-03-12] 5.0.0
-- New Architecture
-
-### [2023-03-12] 3.1.0
-- Added Builders
-
-### [2023-03-12] 3.0.0
-- Refactory to implement CQRS pattern
-
-### [2023-03-04] 2.4.1
-- Updated System.Text.Json
-
-### [2023-01-23] 1.1.0
-- Refactory enum
-
-### [2023-01-13] 1.0.0
-- First Release
\ No newline at end of file
diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj
index 5412bc16..e2d450af 100644
--- a/src/Genocs.Logging/Genocs.Logging.csproj
+++ b/src/Genocs.Logging/Genocs.Logging.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj
index e06755d9..ce80682a 100644
--- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj
+++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj
@@ -23,8 +23,8 @@
-
-
+
+
diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj
index 606ef8c7..fad347ca 100644
--- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj
+++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Clients/RabbitMqClient.cs b/src/Genocs.MessageBrokers.RabbitMQ/Clients/RabbitMqClient.cs
index 60379a88..72d94f9c 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Clients/RabbitMqClient.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Clients/RabbitMqClient.cs
@@ -6,22 +6,25 @@ namespace Genocs.MessageBrokers.RabbitMQ.Clients;
internal sealed class RabbitMQClient : IRabbitMQClient
{
- private readonly object _lockObject = new();
private const string EmptyContext = "{}";
private readonly IConnection _connection;
private readonly IContextProvider _contextProvider;
- private readonly IRabbitMqSerializer _serializer;
+ private readonly IRabbitMQSerializer _serializer;
private readonly ILogger _logger;
private readonly bool _contextEnabled;
private readonly bool _loggerEnabled;
private readonly string _spanContextHeader;
private readonly bool _persistMessages;
- private int _channelsCount;
- private readonly ConcurrentDictionary _channels = new();
+ private readonly ConcurrentDictionary _channels = new();
private readonly int _maxChannels;
+ private int _channelsCount;
- public RabbitMQClient(ProducerConnection connection, IContextProvider contextProvider, IRabbitMqSerializer serializer,
- RabbitMQOptions options, ILogger logger)
+ public RabbitMQClient(
+ ProducerConnection connection,
+ IContextProvider contextProvider,
+ IRabbitMQSerializer serializer,
+ RabbitMQOptions options,
+ ILogger logger)
{
_connection = connection.Connection;
_contextProvider = contextProvider;
@@ -34,29 +37,34 @@ public RabbitMQClient(ProducerConnection connection, IContextProvider contextPro
_maxChannels = options.MaxProducerChannels <= 0 ? 1000 : options.MaxProducerChannels;
}
- public void Send(object message, IConventions conventions, string messageId = null, string correlationId = null,
- string spanContext = null, object messageContext = null, IDictionary headers = null)
+ public async Task SendAsync(
+ object message,
+ IConventions conventions,
+ string? messageId = null,
+ string? correlationId = null,
+ string? spanContext = null,
+ object? messageContext = null,
+ IDictionary? headers = null)
{
- var threadId = Thread.CurrentThread.ManagedThreadId;
+ int threadId = Thread.CurrentThread.ManagedThreadId;
if (!_channels.TryGetValue(threadId, out var channel))
{
- lock (_lockObject)
+ if (_channelsCount >= _maxChannels)
{
- if (_channelsCount >= _maxChannels)
- {
- throw new InvalidOperationException($"Cannot create RabbitMQ producer channel for thread: {threadId} " +
- $"(reached the limit of {_maxChannels} channels). " +
- "Modify `MaxProducerChannels` setting to allow more channels.");
- }
+ throw new InvalidOperationException($"Cannot create RabbitMQ producer channel for thread: {threadId} " +
+ $"(reached the limit of {_maxChannels} channels). " +
+ "Modify `MaxProducerChannels` setting to allow more channels.");
- channel = _connection.CreateModel();
- _channels.TryAdd(threadId, channel);
- _channelsCount++;
- if (_loggerEnabled)
- {
- _logger.LogTrace($"Created a channel for thread: {threadId}, total channels: {_channelsCount}/{_maxChannels}");
- }
}
+
+ channel = await _connection.CreateChannelAsync();
+ _channels.TryAdd(threadId, channel);
+ _channelsCount++;
+ if (_loggerEnabled)
+ {
+ _logger.LogTrace($"Created a channel for thread: {threadId}, total channels: {_channelsCount}/{_maxChannels}");
+ }
+
}
else
{
@@ -67,16 +75,23 @@ public void Send(object message, IConventions conventions, string messageId = nu
}
var body = _serializer.Serialize(message);
- var properties = channel.CreateBasicProperties();
+
+ BasicProperties properties = new BasicProperties();
+
+ // var properties = channel.BasicProperties();
properties.Persistent = _persistMessages;
+
properties.MessageId = string.IsNullOrWhiteSpace(messageId)
? Guid.NewGuid().ToString("N")
: messageId;
+
properties.CorrelationId = string.IsNullOrWhiteSpace(correlationId)
? Guid.NewGuid().ToString("N")
: correlationId;
+
properties.Timestamp = new AmqpTimestamp(DateTimeOffset.UtcNow.ToUnixTimeSeconds());
- properties.Headers = new Dictionary();
+
+ properties.Headers = new Dictionary();
if (_contextEnabled)
{
@@ -108,11 +123,17 @@ public void Send(object message, IConventions conventions, string messageId = nu
$"[id: '{properties.MessageId}', correlation id: '{properties.CorrelationId}']");
}
- channel.BasicPublish(conventions.Exchange, conventions.RoutingKey, properties, body.ToArray());
+ await channel.BasicPublishAsync(conventions.Exchange, conventions.RoutingKey, true, properties, body.ToArray());
}
- private void IncludeMessageContext(object context, IBasicProperties properties)
+ private void IncludeMessageContext(object? context, IBasicProperties properties)
{
+ if (context is null)
+ return;
+
+ if (properties.Headers is null)
+ return;
+
if (context is not null)
{
properties.Headers.Add(_contextProvider.HeaderName, _serializer.Serialize(context).ToArray());
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Contexts/ContextProvider.cs b/src/Genocs.MessageBrokers.RabbitMQ/Contexts/ContextProvider.cs
index 57ee9060..1cc2fce9 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Contexts/ContextProvider.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Contexts/ContextProvider.cs
@@ -2,10 +2,10 @@ namespace Genocs.MessageBrokers.RabbitMQ.Contexts;
internal sealed class ContextProvider : IContextProvider
{
- private readonly IRabbitMqSerializer _serializer;
+ private readonly IRabbitMQSerializer _serializer;
public string HeaderName { get; }
- public ContextProvider(IRabbitMqSerializer serializer, RabbitMQOptions options)
+ public ContextProvider(IRabbitMQSerializer serializer, RabbitMQOptions options)
{
_serializer = serializer;
HeaderName = string.IsNullOrWhiteSpace(options.Context?.Header)
@@ -13,14 +13,14 @@ public ContextProvider(IRabbitMqSerializer serializer, RabbitMQOptions options)
: options.Context.Header;
}
- public object Get(IDictionary headers)
+ public object? Get(IDictionary? headers)
{
if (headers is null)
{
return null;
}
- if (!headers.TryGetValue(HeaderName, out var context))
+ if (!headers.TryGetValue(HeaderName, out object? context))
{
return null;
}
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs
index 15c93d89..0d47431b 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs
@@ -35,12 +35,12 @@ public static class Extensions
/// The serializer.
///
/// Raised when configuration is incorrect.
- public static IGenocsBuilder AddRabbitMq(
+ public static async Task AddRabbitMQAsync(
this IGenocsBuilder builder,
string sectionName = SectionName,
Func? plugins = null,
Action? connectionFactoryConfigurator = null,
- IRabbitMqSerializer? serializer = null)
+ IRabbitMQSerializer? serializer = null)
{
if (string.IsNullOrWhiteSpace(sectionName))
{
@@ -51,7 +51,7 @@ public static IGenocsBuilder AddRabbitMq(
builder.Services.AddSingleton(options);
if (!builder.TryRegister(RegistryName))
{
- return builder;
+ return await Task.FromResult(builder);
}
if (options.HostNames is null || !options.HostNames.Any())
@@ -72,8 +72,8 @@ public static IGenocsBuilder AddRabbitMq(
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
- builder.Services.AddSingleton();
- builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddTransient();
builder.Services.AddHostedService();
@@ -85,7 +85,7 @@ public static IGenocsBuilder AddRabbitMq(
}
else
{
- builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
}
var pluginsRegistry = new RabbitMqPluginsRegistry();
@@ -105,8 +105,6 @@ public static IGenocsBuilder AddRabbitMq(
SocketWriteTimeout = options.SocketWriteTimeout,
RequestedChannelMax = options.RequestedChannelMax,
RequestedFrameMax = options.RequestedFrameMax,
- UseBackgroundThreadsForIO = options.UseBackgroundThreadsForIO,
- DispatchConsumersAsync = true,
ContinuationTimeout = options.ContinuationTimeout,
HandshakeContinuationTimeout = options.HandshakeContinuationTimeout,
NetworkRecoveryInterval = options.NetworkRecoveryInterval,
@@ -118,8 +116,8 @@ public static IGenocsBuilder AddRabbitMq(
connectionFactoryConfigurator?.Invoke(connectionFactory);
logger.LogDebug($"Connecting to RabbitMQ: '{string.Join(", ", options.HostNames)}'...");
- var consumerConnection = connectionFactory.CreateConnection(options.HostNames.ToList(), $"{options.ConnectionName}_consumer");
- var producerConnection = connectionFactory.CreateConnection(options.HostNames.ToList(), $"{options.ConnectionName}_producer");
+ var consumerConnection = await connectionFactory.CreateConnectionAsync(options.HostNames.ToList(), $"{options.ConnectionName}_consumer");
+ var producerConnection = await connectionFactory.CreateConnectionAsync(options.HostNames.ToList(), $"{options.ConnectionName}_producer");
logger.LogDebug($"Connected to RabbitMQ: '{string.Join(", ", options.HostNames)}'.");
builder.Services.AddSingleton(new ConsumerConnection(consumerConnection));
builder.Services.AddSingleton(new ProducerConnection(producerConnection));
@@ -212,6 +210,6 @@ public static IGenocsBuilder AddExceptionToFailedMessageMapper(this IGenocsBu
return builder;
}
- public static IBusSubscriber UseRabbitMq(this IApplicationBuilder app)
- => new RabbitMqSubscriber(app.ApplicationServices.GetRequiredService());
+ public static IBusSubscriber UseRabbitMQ(this IApplicationBuilder app)
+ => new RabbitMQSubscriber(app.ApplicationServices.GetRequiredService());
}
\ No newline at end of file
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj
index a36b28d6..ef26b78e 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj
@@ -22,13 +22,13 @@
-
+
-
+
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs b/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs
index b7d4e687..dc0be008 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs
@@ -2,12 +2,12 @@ namespace Genocs.MessageBrokers.RabbitMQ;
public interface IRabbitMQClient
{
- void Send(
- object? message,
- IConventions conventions,
- string? messageId = null,
- string? correlationId = null,
- string? spanContext = null,
- object? messageContext = null,
- IDictionary? headers = null);
+ Task SendAsync(
+ object message,
+ IConventions conventions,
+ string? messageId = null,
+ string? correlationId = null,
+ string? spanContext = null,
+ object? messageContext = null,
+ IDictionary? headers = null);
}
\ No newline at end of file
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqSerializer.cs b/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqSerializer.cs
index ce700415..0fbdab94 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqSerializer.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqSerializer.cs
@@ -1,6 +1,6 @@
namespace Genocs.MessageBrokers.RabbitMQ;
-public interface IRabbitMqSerializer
+public interface IRabbitMQSerializer
{
ReadOnlySpan Serialize(object value);
object? Deserialize(ReadOnlySpan value, Type type);
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs b/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs
index d80af9f3..e51c0c35 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs
@@ -1,7 +1,7 @@
+using System.Reflection;
using Genocs.Common.Types;
using Microsoft.Extensions.Logging;
using RabbitMQ.Client;
-using System.Reflection;
namespace Genocs.MessageBrokers.RabbitMQ.Initializers;
@@ -13,8 +13,10 @@ public class RabbitMqExchangeInitializer : IInitializer
private readonly ILogger _logger;
private readonly bool _loggerEnabled;
- public RabbitMqExchangeInitializer(ProducerConnection connection, RabbitMQOptions options,
- ILogger logger)
+ public RabbitMqExchangeInitializer(
+ ProducerConnection connection,
+ RabbitMQOptions options,
+ ILogger logger)
{
_connection = connection.Connection;
_options = options;
@@ -22,7 +24,7 @@ public RabbitMqExchangeInitializer(ProducerConnection connection, RabbitMQOption
_loggerEnabled = _options.Logger?.Enabled == true;
}
- public Task InitializeAsync()
+ public async Task InitializeAsync()
{
var exchanges = AppDomain.CurrentDomain
.GetAssemblies()
@@ -32,41 +34,41 @@ public Task InitializeAsync()
.Distinct()
.ToList();
- using var channel = _connection.CreateModel();
+ using var channel = await _connection.CreateChannelAsync();
if (_options.Exchange?.Declare == true)
{
Log(_options.Exchange.Name, _options.Exchange.Type);
- channel.ExchangeDeclare(
- _options.Exchange.Name,
- _options.Exchange.Type,
- _options.Exchange.Durable,
- _options.Exchange.AutoDelete);
+ await channel.ExchangeDeclareAsync(
+ _options.Exchange.Name,
+ _options.Exchange.Type,
+ _options.Exchange.Durable,
+ _options.Exchange.AutoDelete);
if (_options.DeadLetter?.Enabled is true && _options.DeadLetter?.Declare is true)
{
- channel.ExchangeDeclare(
- $"{_options.DeadLetter.Prefix}{_options.Exchange.Name}{_options.DeadLetter.Suffix}",
- ExchangeType.Direct,
- _options.Exchange.Durable,
- _options.Exchange.AutoDelete);
+ await channel.ExchangeDeclareAsync(
+ $"{_options.DeadLetter.Prefix}{_options.Exchange.Name}{_options.DeadLetter.Suffix}",
+ ExchangeType.Direct,
+ _options.Exchange.Durable,
+ _options.Exchange.AutoDelete);
}
}
foreach (string? exchange in exchanges)
{
+ if (string.IsNullOrWhiteSpace(exchange)) continue;
+
if (exchange.Equals(_options.Exchange?.Name, StringComparison.InvariantCultureIgnoreCase))
{
continue;
}
Log(exchange, DefaultType);
- channel.ExchangeDeclare(exchange, DefaultType, true);
+ await channel.ExchangeDeclareAsync(exchange, DefaultType, true);
}
- channel.Close();
-
- return Task.CompletedTask;
+ await channel.CloseAsync();
}
private void Log(string exchange, string type)
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Internals/RabbitMqBackgroundService.cs b/src/Genocs.MessageBrokers.RabbitMQ/Internals/RabbitMqBackgroundService.cs
index 26d077e8..79068321 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Internals/RabbitMqBackgroundService.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Internals/RabbitMqBackgroundService.cs
@@ -8,6 +8,7 @@
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -24,7 +25,7 @@ internal sealed class RabbitMqBackgroundService : BackgroundService
WriteIndented = true
};
- private readonly ConcurrentDictionary _channels = new();
+ private readonly ConcurrentDictionary _channels = new();
private readonly EmptyExceptionToMessageMapper _exceptionMapper = new();
private readonly EmptyExceptionToFailedMessageMapper _exceptionFailedMapper = new();
private readonly IServiceProvider _serviceProvider;
@@ -32,7 +33,7 @@ internal sealed class RabbitMqBackgroundService : BackgroundService
private readonly IConnection _producerConnection;
private readonly MessageSubscribersChannel _messageSubscribersChannel;
private readonly IBusPublisher _publisher;
- private readonly IRabbitMqSerializer _rabbitMqSerializer;
+ private readonly IRabbitMQSerializer _rabbitMqSerializer;
private readonly IConventionsProvider _conventionsProvider;
private readonly IContextProvider _contextProvider;
private readonly ILogger _logger;
@@ -54,10 +55,10 @@ public RabbitMqBackgroundService(IServiceProvider serviceProvider)
_producerConnection = serviceProvider.GetRequiredService().Connection;
_messageSubscribersChannel = serviceProvider.GetRequiredService();
_publisher = _serviceProvider.GetRequiredService();
- _rabbitMqSerializer = _serviceProvider.GetRequiredService();
+ _rabbitMqSerializer = _serviceProvider.GetRequiredService();
_conventionsProvider = _serviceProvider.GetRequiredService();
_contextProvider = _serviceProvider.GetRequiredService();
- _logger = _serviceProvider.GetRequiredService>();
+ _logger = _serviceProvider.GetRequiredService>();
_exceptionToMessageMapper = _serviceProvider.GetService() ?? _exceptionMapper;
_exceptionToFailedMessageMapper = _serviceProvider.GetService() ?? _exceptionFailedMapper;
_pluginsExecutor = _serviceProvider.GetRequiredService();
@@ -78,15 +79,15 @@ public RabbitMqBackgroundService(IServiceProvider serviceProvider)
return;
}
- _consumerConnection.CallbackException += ConnectionOnCallbackException;
- _consumerConnection.ConnectionShutdown += ConnectionOnConnectionShutdown;
- _consumerConnection.ConnectionBlocked += ConnectionOnConnectionBlocked;
- _consumerConnection.ConnectionUnblocked += ConnectionOnConnectionUnblocked;
+ _consumerConnection.CallbackExceptionAsync += ConnectionOnCallbackExceptionAsync;
+ _consumerConnection.ConnectionShutdownAsync += ConnectionOnConnectionShutdownAsync;
+ _consumerConnection.ConnectionBlockedAsync += ConnectionOnConnectionBlockedAsync;
+ _consumerConnection.ConnectionUnblockedAsync += ConnectionOnConnectionUnblockedAsync;
- _producerConnection.CallbackException += ConnectionOnCallbackException;
- _producerConnection.ConnectionShutdown += ConnectionOnConnectionShutdown;
- _producerConnection.ConnectionBlocked += ConnectionOnConnectionBlocked;
- _producerConnection.ConnectionUnblocked += ConnectionOnConnectionUnblocked;
+ _producerConnection.CallbackExceptionAsync += ConnectionOnCallbackExceptionAsync;
+ _producerConnection.ConnectionShutdownAsync += ConnectionOnConnectionShutdownAsync;
+ _producerConnection.ConnectionBlockedAsync += ConnectionOnConnectionBlockedAsync;
+ _producerConnection.ConnectionUnblockedAsync += ConnectionOnConnectionUnblockedAsync;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
@@ -98,7 +99,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
switch (messageSubscriber.Action)
{
case MessageSubscriberAction.Subscribe:
- Subscribe(messageSubscriber);
+ await SubscribeAsync(messageSubscriber);
break;
case MessageSubscriberAction.Unsubscribe:
Unsubscribe(messageSubscriber);
@@ -115,7 +116,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
}
}
- private void Subscribe(IMessageSubscriber messageSubscriber)
+ private async Task SubscribeAsync(IMessageSubscriber messageSubscriber)
{
var conventions = _conventionsProvider.Get(messageSubscriber.Type);
var channelKey = GetChannelKey(conventions);
@@ -124,7 +125,7 @@ private void Subscribe(IMessageSubscriber messageSubscriber)
return;
}
- var channel = _consumerConnection.CreateModel();
+ var channel = await _consumerConnection.CreateChannelAsync();
var channelInfoLog = $"exchange: '{conventions.Exchange}', queue: '{conventions.Queue}', " +
$"routing key: '{conventions.RoutingKey}'";
@@ -137,7 +138,7 @@ private void Subscribe(IMessageSubscriber messageSubscriber)
_logger.LogTrace($"Added the channel: {channel.ChannelNumber} for {channelInfoLog}.");
- var declare = _options.Queue?.Declare ?? true;
+ bool declare = _options.Queue?.Declare ?? true;
var durable = _options.Queue?.Durable ?? true;
var exclusive = _options.Queue?.Exclusive ?? false;
var autoDelete = _options.Queue?.AutoDelete ?? false;
@@ -165,11 +166,12 @@ private void Subscribe(IMessageSubscriber messageSubscriber)
{"x-dead-letter-routing-key", deadLetterQueue},
}
: new Dictionary();
- channel.QueueDeclare(conventions.Queue, durable, exclusive, autoDelete, queueArguments);
+
+ await channel.QueueDeclareAsync(conventions.Queue, durable, exclusive, autoDelete, queueArguments);
}
- channel.QueueBind(conventions.Queue, conventions.Exchange, conventions.RoutingKey);
- channel.BasicQos(_qosOptions.PrefetchSize, _qosOptions.PrefetchCount, _qosOptions.Global);
+ await channel.QueueBindAsync(conventions.Queue, conventions.Exchange, conventions.RoutingKey);
+ await channel.BasicQosAsync(_qosOptions.PrefetchSize, _qosOptions.PrefetchCount, _qosOptions.Global);
if (_options.DeadLetter?.Enabled is true)
{
@@ -191,15 +193,19 @@ private void Subscribe(IMessageSubscriber messageSubscriber)
_logger.LogInformation($"Declaring a dead letter queue: '{deadLetterQueue}' " +
$"for an exchange: '{deadLetterExchange}'{(ttl.HasValue ? $", message TTL: {ttl} ms." : ".")}");
- channel.QueueDeclare(deadLetterQueue, _options.DeadLetter.Durable, _options.DeadLetter.Exclusive,
- _options.DeadLetter.AutoDelete, deadLetterArgs);
+ await channel.QueueDeclareAsync(
+ deadLetterQueue,
+ _options.DeadLetter.Durable,
+ _options.DeadLetter.Exclusive,
+ _options.DeadLetter.AutoDelete,
+ deadLetterArgs);
}
- channel.QueueBind(deadLetterQueue, deadLetterExchange, deadLetterQueue);
+ await channel.QueueBindAsync(deadLetterQueue, deadLetterExchange, deadLetterQueue);
}
var consumer = new AsyncEventingBasicConsumer(channel);
- consumer.Received += async (_, args) =>
+ consumer.ReceivedAsync += async (_, args) =>
{
try
{
@@ -213,7 +219,8 @@ private void Subscribe(IMessageSubscriber messageSubscriber)
if (_loggerEnabled)
{
var messagePayload = _logMessagePayload ? Encoding.UTF8.GetString(args.Body.Span) : string.Empty;
- _logger.LogInformation("Received a message with ID: '{MessageId}', " +
+ _logger.LogInformation(
+ "Received a message with ID: '{MessageId}', " +
"Correlation ID: '{CorrelationId}', timestamp: {Timestamp}, " +
"queue: {Queue}, routing key: {RoutingKey}, exchange: {Exchange}, payload: {MessagePayload}",
messageId, correlationId, timestamp, conventions.Queue, conventions.RoutingKey, conventions.Exchange, messagePayload);
@@ -230,12 +237,12 @@ Task Next(object m, object ctx, BasicDeliverEventArgs a)
catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
- channel.BasicNack(args.DeliveryTag, false, _requeueFailedMessages);
+ await channel.BasicNackAsync(args.DeliveryTag, false, _requeueFailedMessages);
await Task.Yield();
}
};
- channel.BasicConsume(conventions.Queue, false, consumer);
+ await channel.BasicConsumeAsync(conventions.Queue, false, consumer);
}
private object BuildCorrelationContext(IServiceScope scope, BasicDeliverEventArgs args)
@@ -255,9 +262,15 @@ private object BuildCorrelationContext(IServiceScope scope, BasicDeliverEventArg
return correlationContext;
}
- private async Task TryHandleAsync(IModel channel, object message, string messageId, string correlationId,
- object messageContext, BasicDeliverEventArgs args, Func handle,
- bool deadLetterEnabled)
+ private async Task TryHandleAsync(
+ IChannel channel,
+ object message,
+ string messageId,
+ string correlationId,
+ object messageContext,
+ BasicDeliverEventArgs args,
+ Func handle,
+ bool deadLetterEnabled)
{
var currentRetry = 0;
var messageName = message.GetType().Name.Underscore();
@@ -290,7 +303,7 @@ await retryPolicy.ExecuteAsync(async () =>
await handle(_serviceProvider, message, messageContext);
}
- channel.BasicAck(args.DeliveryTag, false);
+ channel.BasicAckAsync(args.DeliveryTag, false);
await Task.Yield();
if (_loggerEnabled)
@@ -305,7 +318,7 @@ await retryPolicy.ExecuteAsync(async () =>
_logger.LogError(ex, ex.Message);
if (ex is RabbitMqMessageProcessingTimeoutException)
{
- channel.BasicNack(args.DeliveryTag, false, _requeueFailedMessages);
+ channel.BasicNackAsync(args.DeliveryTag, false, _requeueFailedMessages);
await Task.Yield();
return;
}
@@ -340,7 +353,7 @@ await _publisher.PublishAsync(failedMessage.Message, failedMessageId, correlatio
if (!deadLetterEnabled || !failedMessage.MoveToDeadLetter)
{
- channel.BasicAck(args.DeliveryTag, false);
+ channel.BasicAckAsync(args.DeliveryTag, false);
await Task.Yield();
return;
}
@@ -364,7 +377,7 @@ await _publisher.PublishAsync(failedMessage.Message, failedMessageId, correlatio
if (failedMessage is not null && !failedMessage.MoveToDeadLetter)
{
- channel.BasicAck(args.DeliveryTag, false);
+ channel.BasicAckAsync(args.DeliveryTag, false);
await Task.Yield();
return;
}
@@ -375,7 +388,7 @@ await _publisher.PublishAsync(failedMessage.Message, failedMessageId, correlatio
"{CorrelationId} will be moved to DLX", messageName, messageId, correlationId);
}
- channel.BasicNack(args.DeliveryTag, false, _requeueFailedMessages);
+ channel.BasicNackAsync(args.DeliveryTag, false, _requeueFailedMessages);
await Task.Yield();
}
});
@@ -404,15 +417,15 @@ public override void Dispose()
{
if (_loggerEnabled && _options.Logger?.LogConnectionStatus is true)
{
- _consumerConnection.CallbackException -= ConnectionOnCallbackException;
- _consumerConnection.ConnectionShutdown -= ConnectionOnConnectionShutdown;
- _consumerConnection.ConnectionBlocked -= ConnectionOnConnectionBlocked;
- _consumerConnection.ConnectionUnblocked -= ConnectionOnConnectionUnblocked;
-
- _producerConnection.CallbackException -= ConnectionOnCallbackException;
- _producerConnection.ConnectionShutdown -= ConnectionOnConnectionShutdown;
- _producerConnection.ConnectionBlocked -= ConnectionOnConnectionBlocked;
- _producerConnection.ConnectionUnblocked -= ConnectionOnConnectionUnblocked;
+ _consumerConnection.CallbackExceptionAsync -= ConnectionOnCallbackExceptionAsync;
+ _consumerConnection.ConnectionShutdownAsync -= ConnectionOnConnectionShutdownAsync;
+ _consumerConnection.ConnectionBlockedAsync -= ConnectionOnConnectionBlockedAsync;
+ _consumerConnection.ConnectionUnblockedAsync -= ConnectionOnConnectionUnblockedAsync;
+
+ _producerConnection.CallbackExceptionAsync -= ConnectionOnCallbackExceptionAsync;
+ _producerConnection.ConnectionShutdownAsync -= ConnectionOnConnectionShutdownAsync;
+ _producerConnection.ConnectionBlockedAsync -= ConnectionOnConnectionBlockedAsync;
+ _producerConnection.ConnectionUnblockedAsync -= ConnectionOnConnectionUnblockedAsync;
}
foreach (var (key, channel) in _channels)
@@ -423,8 +436,8 @@ public override void Dispose()
try
{
- _consumerConnection.Close();
- _producerConnection.Close();
+ _consumerConnection.CloseAsync();
+ _producerConnection.CloseAsync();
}
catch
{
@@ -444,9 +457,9 @@ private class EmptyExceptionToFailedMessageMapper : IExceptionToFailedMessageMap
public FailedMessage Map(Exception exception, object message) => null;
}
- private void ConnectionOnCallbackException(object sender, CallbackExceptionEventArgs eventArgs)
+ private async Task ConnectionOnCallbackExceptionAsync(object sender, CallbackExceptionEventArgs eventArgs)
{
- _logger.LogError("RabbitMQ callback exception occured.");
+ _logger.LogError("RabbitMQ callback exception occurred.");
if (eventArgs.Exception is not null)
{
_logger.LogError(eventArgs.Exception, eventArgs.Exception.Message);
@@ -456,21 +469,27 @@ private void ConnectionOnCallbackException(object sender, CallbackExceptionEvent
{
_logger.LogError(JsonSerializer.Serialize(eventArgs.Detail, SerializerOptions));
}
+
+ await Task.CompletedTask;
}
- private void ConnectionOnConnectionShutdown(object sender, ShutdownEventArgs eventArgs)
+ private async Task ConnectionOnConnectionShutdownAsync(object sender, ShutdownEventArgs eventArgs)
{
- _logger.LogError($"RabbitMQ connection shutdown occured. Initiator: '{eventArgs.Initiator}', " +
+ _logger.LogError($"RabbitMQ connection shutdown occurred. Initiator: '{eventArgs.Initiator}', " +
$"reply code: '{eventArgs.ReplyCode}', text: '{eventArgs.ReplyText}'.");
+
+ await Task.CompletedTask;
}
- private void ConnectionOnConnectionBlocked(object sender, ConnectionBlockedEventArgs eventArgs)
+ private async Task ConnectionOnConnectionBlockedAsync(object sender, ConnectionBlockedEventArgs eventArgs)
{
_logger.LogError($"RabbitMQ connection has been blocked. {eventArgs.Reason}");
+ await Task.CompletedTask;
}
- private void ConnectionOnConnectionUnblocked(object sender, EventArgs eventArgs)
+ private async Task ConnectionOnConnectionUnblockedAsync(object sender, AsyncEventArgs eventArgs)
{
_logger.LogInformation("RabbitMQ connection has been unblocked.");
+ await Task.CompletedTask;
}
}
\ No newline at end of file
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Publishers/RabbitMqPublisher.cs b/src/Genocs.MessageBrokers.RabbitMQ/Publishers/RabbitMqPublisher.cs
index 143a6607..b1bce4d5 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/Publishers/RabbitMqPublisher.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/Publishers/RabbitMqPublisher.cs
@@ -1,22 +1,33 @@
namespace Genocs.MessageBrokers.RabbitMQ.Publishers;
-internal sealed class RabbitMqPublisher : IBusPublisher
+internal sealed class RabbitMQPublisher : IBusPublisher
{
private readonly IRabbitMQClient _client;
private readonly IConventionsProvider _conventionsProvider;
- public RabbitMqPublisher(IRabbitMQClient client, IConventionsProvider conventionsProvider)
+ public RabbitMQPublisher(IRabbitMQClient client, IConventionsProvider conventionsProvider)
{
_client = client;
_conventionsProvider = conventionsProvider;
}
- public Task PublishAsync(T message, string? messageId = null, string correlationId = null,
- string spanContext = null, object messageContext = null, IDictionary headers = null)
+ public Task PublishAsync(
+ T message,
+ string? messageId = null,
+ string? correlationId = null,
+ string? spanContext = null,
+ object? messageContext = null,
+ IDictionary? headers = null)
where T : class
{
- _client.Send(message, _conventionsProvider.Get(message.GetType()), messageId, correlationId, spanContext,
- messageContext, headers);
+ _client.SendAsync(
+ message,
+ _conventionsProvider.Get(message.GetType()),
+ messageId,
+ correlationId,
+ spanContext,
+ messageContext,
+ headers);
return Task.CompletedTask;
}
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqOptions.cs b/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqOptions.cs
index bd0154b4..cd791f48 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqOptions.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqOptions.cs
@@ -2,12 +2,12 @@ namespace Genocs.MessageBrokers.RabbitMQ;
public class RabbitMQOptions
{
- public string ConnectionName { get; set; }
- public IEnumerable HostNames { get; set; }
+ public string? ConnectionName { get; set; }
+ public IEnumerable? HostNames { get; set; }
public int Port { get; set; }
- public string VirtualHost { get; set; }
- public string Username { get; set; }
- public string Password { get; set; }
+ public string VirtualHost { get; set; } = "/";
+ public string Username { get; set; } = "guest";
+ public string Password { get; set; } = "guest";
public TimeSpan RequestedHeartbeat { get; set; } = TimeSpan.FromSeconds(60);
public TimeSpan RequestedConnectionTimeout { get; set; } = TimeSpan.FromSeconds(30);
public TimeSpan SocketReadTimeout { get; set; } = TimeSpan.FromSeconds(30);
@@ -18,20 +18,19 @@ public class RabbitMQOptions
public TimeSpan? MessageProcessingTimeout { get; set; }
public ushort RequestedChannelMax { get; set; }
public uint RequestedFrameMax { get; set; }
- public bool UseBackgroundThreadsForIO { get; set; }
- public string ConventionsCasing { get; set; }
+ public string? ConventionsCasing { get; set; }
public int Retries { get; set; }
public int RetryInterval { get; set; }
public bool MessagesPersisted { get; set; }
- public ContextOptions Context { get; set; }
- public ExchangeOptions Exchange { get; set; }
- public LoggerOptions Logger { get; set; }
- public SslOptions Ssl { get; set; }
- public QueueOptions Queue { get; set; }
- public DeadLetterOptions DeadLetter { get; set; }
- public QosOptions Qos { get; set; }
- public ConventionsOptions Conventions { get; set; }
- public string SpanContextHeader { get; set; }
+ public ContextOptions? Context { get; set; }
+ public ExchangeOptions? Exchange { get; set; }
+ public LoggerOptions? Logger { get; set; }
+ public SslOptions? Ssl { get; set; }
+ public QueueOptions? Queue { get; set; }
+ public DeadLetterOptions? DeadLetter { get; set; }
+ public QosOptions? Qos { get; set; }
+ public ConventionsOptions? Conventions { get; set; }
+ public string? SpanContextHeader { get; set; }
public int MaxProducerChannels { get; set; }
public bool RequeueFailedMessages { get; set; }
@@ -48,13 +47,13 @@ public class LoggerOptions
public class ContextOptions
{
public bool Enabled { get; set; }
- public string Header { get; set; }
+ public string? Header { get; set; }
}
public class ExchangeOptions
{
- public string Name { get; set; }
- public string Type { get; set; }
+ public string? Name { get; set; }
+ public string? Type { get; set; }
public bool Declare { get; set; }
public bool Durable { get; set; }
public bool AutoDelete { get; set; }
@@ -62,7 +61,7 @@ public class ExchangeOptions
public class QueueOptions
{
- public string Template { get; set; }
+ public string? Template { get; set; }
public bool Declare { get; set; }
public bool Durable { get; set; }
public bool Exclusive { get; set; }
@@ -72,8 +71,8 @@ public class QueueOptions
public class DeadLetterOptions
{
public bool Enabled { get; set; }
- public string Prefix { get; set; }
- public string Suffix { get; set; }
+ public string? Prefix { get; set; }
+ public string? Suffix { get; set; }
public bool Declare { get; set; }
public bool Durable { get; set; }
public bool Exclusive { get; set; }
@@ -84,10 +83,10 @@ public class DeadLetterOptions
public class SslOptions
{
public bool Enabled { get; set; }
- public string ServerName { get; set; }
- public string CertificatePath { get; set; }
- public string CaCertificatePath { get; set; }
- public IEnumerable X509IgnoredStatuses { get; set; }
+ public string? ServerName { get; set; }
+ public string? CertificatePath { get; set; }
+ public string? CaCertificatePath { get; set; }
+ public IEnumerable? X509IgnoredStatuses { get; set; }
}
public class QosOptions
@@ -99,7 +98,7 @@ public class QosOptions
public class ConventionsOptions
{
- public MessageAttributeOptions MessageAttribute { get; set; }
+ public MessageAttributeOptions? MessageAttribute { get; set; }
public class MessageAttributeOptions
{
diff --git a/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqPlugin.cs b/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqPlugin.cs
index 3ffb8fc6..3466f4c7 100644
--- a/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqPlugin.cs
+++ b/src/Genocs.MessageBrokers.RabbitMQ/RabbitMqPlugin.cs
@@ -7,8 +7,7 @@ public abstract class RabbitMQPlugin : IRabbitMqPlugin, IRabbitMqPluginAccessor
{
private Func