Skip to content

Commit

Permalink
Merge pull request #2 from PandaTechAM/development
Browse files Browse the repository at this point in the history
Added redis and signalR utils
  • Loading branch information
HaikAsatryan authored Nov 21, 2024
2 parents ca6fc01 + a00fe41 commit f79b677
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 28 deletions.
22 changes: 16 additions & 6 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This package currently supports:
- **Cors Configuration** with easy configuration options.
- **Resilience Pipelines** for `HttpClient` operations.
- **Controller Extensions** for mapping old-style MVC controllers.
- **SignalR Extensions** for adding simple SignalR or distributed SignalR backed with Redis.
- **OpenTelemetry Integration** for tracking metrics, traces, and logging.
- **Health Checks** with default endpoints and startup validation.
- Various **Extensions and Utilities**, including enumerable, string, and queryable extensions.
Expand Down Expand Up @@ -121,6 +122,7 @@ Follow this example to set up your project with all the features provided by thi
},
"RepositoryName": "be-lib-sharedkernel",
"ConnectionStrings": {
"Redis": "localhost:6379",
"PersistentStorage": "/persistence"
},
"Security": {
Expand All @@ -143,14 +145,15 @@ builder
.AddResponseCrafter(NamingConvention.ToSnakeCase)
.AddOpenApi()
.AddOpenTelemetry()
.AddEndpoints(AssemblyRegistry.ToArray())
.AddMapMinimalApis(AssemblyRegistry.ToArray())
.AddControllers(AssemblyRegistry.ToArray())
.AddMediatrWithBehaviors(AssemblyRegistry.ToArray())
.AddResilienceDefaultPipeline()
.MapDefaultTimeZone()
.AddCors();

builder.Services.AddHealthChecks();
.AddRedis(KeyPrefix.AssemblyNamePrefix)
.AddDistributedSignalR("DistributedSignalR") // or .AddSignalR()
.AddCors()
.AddHealthChecks();


var app = builder.Build();
Expand All @@ -159,11 +162,12 @@ app
.UseRequestResponseLogging()
.UseResponseCrafter()
.UseCors()
.MapEndpoints()
.MapMinimalApis()
.MapDefaultEndpoints()
.EnsureHealthy()
.ClearAssemblyRegistry()
.UseOpenApi();
.UseOpenApi()
.MapControllers();

app.LogStartSuccess();
app.Run();
Expand Down Expand Up @@ -531,11 +535,16 @@ The default resilience pipeline includes the following policies:

For mapping old style MVC controllers, use `builder.AddControllers()`.
The `AddControllers()` method can also accept assembly names as parameters to scan for controllers.
The `MapControllers()` method maps the controllers to the application.

Example:

```csharp
var builder = WebApplication.CreateBuilder(args);
builder.AddControllers([typeof(Program).Assembly]);
var app = builder.Build();
app.MapControllers();
app.Run();
```

## OpenTelemetry
Expand Down Expand Up @@ -598,6 +607,7 @@ This package includes various extensions and utilities to aid development:
- **Pandatech.FluentMinimalApiMapper:** Simplifies mapping in minimal APIs.
- **Pandatech.RegexBox:** A collection of useful regular expressions.
- **Pandatech.ResponseCrafter:** A utility for crafting consistent API responses.
- **Pandatech.DistributedCache:** A distributed cache provider for Redis.

## License

Expand Down
12 changes: 12 additions & 0 deletions src/SharedKernel/Extensions/ConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ internal static class ConfigurationExtensions
private const string PersistentConfigurationPath = "PersistentStorage";
private const string RepositoryNameConfigurationPath = "RepositoryName";
private const string TimeZoneConfigurationPath = "DefaultTimeZone";
private const string RedisConfigurationPath = "Redis";

internal static string GetAllowedCorsOrigins(this IConfiguration configuration)
{
Expand Down Expand Up @@ -52,4 +53,15 @@ public static string GetDefaultTimeZone(this IConfiguration configuration)

return timeZone;
}

public static string GetRedisUrl(this IConfiguration configuration)
{
var redisConnectionString = configuration.GetConnectionString(RedisConfigurationPath);
if (redisConnectionString is null)
{
throw new InvalidOperationException("Redis connection string is not configured.");
}

return redisConnectionString;
}
}
19 changes: 19 additions & 0 deletions src/SharedKernel/Extensions/DistributedCacheExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using DistributedCache.Extensions;
using DistributedCache.Options;
using Microsoft.AspNetCore.Builder;

namespace SharedKernel.Extensions;

public static class DistributedCacheExtension
{
public static WebApplicationBuilder AddRedis(this WebApplicationBuilder builder, KeyPrefix keyPrefix)
{
builder.AddDistributedCache(options =>
{
options.RedisConnectionString = builder.Configuration.GetRedisUrl();
options.KeyPrefixForIsolation = keyPrefix;
});

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace SharedKernel.Extensions;

public static class HealthCheckRunnerExtension
public static class HealthCheckExtensions
{
public static WebApplication EnsureHealthy(this WebApplication app)
{
Expand Down Expand Up @@ -42,4 +42,10 @@ public static WebApplication EnsureHealthy(this WebApplication app)
var message = $"Unhealthy services detected: {string.Join(", ", unhealthyChecks)}";
throw new ServiceUnavailableException(message);
}

public static WebApplicationBuilder AddHealthChecks(this WebApplicationBuilder builder)
{
builder.Services.AddHealthChecks();
return builder;
}
}
35 changes: 35 additions & 0 deletions src/SharedKernel/Extensions/SignalRExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;

namespace SharedKernel.Extensions;

public static class SignalRExtensions
{

public static WebApplicationBuilder AddSignalR(this WebApplicationBuilder builder)
{
builder
.Services
.AddSignalR()
.AddMessagePackProtocol();

return builder;
}

public static WebApplicationBuilder AddDistributedSignalR(this WebApplicationBuilder builder, string redisChannelName)
{
builder
.Services
.AddSignalR()
.AddMessagePackProtocol()
.AddStackExchangeRedis(builder.Configuration.GetRedisUrl(),
options =>
{
options.Configuration.ChannelPrefix = RedisChannel.Literal("FinHub:SignalR:");
});


return builder;
}
}
12 changes: 6 additions & 6 deletions src/SharedKernel/Logging/StartupLoggerExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Globalization;
using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Newtonsoft.Json;

namespace SharedKernel.Logging;

Expand All @@ -11,7 +11,7 @@ public static class StartupLoggerExtensions
public static WebApplicationBuilder LogStartAttempt(this WebApplicationBuilder builder)
{
var now = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
Console.WriteLine(JsonConvert.SerializeObject(new
Console.WriteLine(JsonSerializer.Serialize(new
{
Timestamp = now,
Event = "ApplicationStartAttempt",
Expand All @@ -27,7 +27,7 @@ public static WebApplication LogStartSuccess(this WebApplication app)
.TotalMilliseconds;
var deltaInSeconds = Math.Round(delta / 1000, 2);
var now = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
Console.WriteLine(JsonConvert.SerializeObject(new
Console.WriteLine(JsonSerializer.Serialize(new
{
Timestamp = now,
Event = "ApplicationStartSuccess",
Expand All @@ -40,7 +40,7 @@ public static WebApplicationBuilder LogModuleRegistrationSuccess(this WebApplica
string moduleName)
{
var now = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
Console.WriteLine(JsonConvert.SerializeObject(new
Console.WriteLine(JsonSerializer.Serialize(new
{
Timestamp = now,
Event = "ModuleRegistrationSuccess",
Expand All @@ -52,12 +52,12 @@ public static WebApplicationBuilder LogModuleRegistrationSuccess(this WebApplica
public static WebApplication LogModuleUseSuccess(this WebApplication app, string moduleName)
{
var now = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
Console.WriteLine(JsonConvert.SerializeObject(new
Console.WriteLine(JsonSerializer.Serialize(new
{
Timestamp = now,
Event = "ModuleUseSuccess",
Module = moduleName
}));
return app;
}
}
}
18 changes: 9 additions & 9 deletions src/SharedKernel/SharedKernel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
<PackageReadmeFile>Readme.md</PackageReadmeFile>
<Authors>Pandatech</Authors>
<Copyright>MIT</Copyright>
<Version>1.0.1</Version>
<Version>1.0.2</Version>
<PackageId>Pandatech.SharedKernel</PackageId>
<Title>Pandatech Shared Kernel Library</Title>
<PackageTags>Pandatech, shared kernel, library, OpenAPI, Swagger, utilities, scalar</PackageTags>
<Description>Pandatech.SharedKernel provides centralized configurations, utilities, and extensions for ASP.NET Core projects. For more information refere to readme.md document.</Description>
<RepositoryUrl>https://github.com/PandaTechAM/be-lib-sharedkernel</RepositoryUrl>
<PackageReleaseNotes>Nuget updates</PackageReleaseNotes>
<PackageReleaseNotes>Added redis and signalR utils</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
Expand All @@ -26,10 +26,14 @@
<PackageReference Include="AspNetCore.HealthChecks.Prometheus.Metrics" Version="8.0.1" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="8.0.1" />
<PackageReference Include="Elastic.CommonSchema.Serilog" Version="8.12.2" />
<PackageReference Include="FluentDateTime" Version="3.0.0" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageReference Include="HtmlSanitizer" Version="8.1.870" />
<PackageReference Include="MediatR" Version="12.4.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="9.0.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.10.0" />
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.8.0-rc.1"/>
Expand All @@ -38,18 +42,14 @@
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0"/>
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.9.0"/>
<PackageReference Include="Pandatech.Crypto" Version="4.0.0" />
<PackageReference Include="Pandatech.FluentMinimalApiMapper" Version="2.0.0" />
<PackageReference Include="Pandatech.DistributedCache" Version="3.0.0" />
<PackageReference Include="Pandatech.FluentMinimalApiMapper" Version="2.0.1" />
<PackageReference Include="Pandatech.PandaVaultClient" Version="4.0.0" />
<PackageReference Include="Pandatech.RegexBox" Version="3.0.0" />
<PackageReference Include="Pandatech.ResponseCrafter" Version="4.0.1" />
<PackageReference Include="Pandatech.ResponseCrafter" Version="5.0.1" />
<PackageReference Include="Scalar.AspNetCore" Version="1.2.42" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="7.0.0" />
</ItemGroup>

<ItemGroup>
<Content Include="wwwroot\**" CopyToOutputDirectory="PreserveNewest" Pack="true" PackagePath="contentFiles\any\any" />
</ItemGroup>


</Project>
16 changes: 10 additions & 6 deletions test/SharedKernel.Demo/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using DistributedCache.Extensions;
using DistributedCache.Options;
using FluentMinimalApiMapper;
using Microsoft.AspNetCore.Mvc;
using SharedKernel.Demo;
Expand All @@ -21,14 +23,15 @@
.AddResponseCrafter(NamingConvention.ToSnakeCase)
.AddOpenApi()
.AddOpenTelemetry()
.AddEndpoints(AssemblyRegistry.ToArray())
.AddMinimalApis(AssemblyRegistry.ToArray())
.AddControllers(AssemblyRegistry.ToArray())
.AddMediatrWithBehaviors(AssemblyRegistry.ToArray())
.AddResilienceDefaultPipeline()
.AddRedis(KeyPrefix.AssemblyNamePrefix)
.AddDistributedSignalR("DistributedSignalR") // or .AddSignalR()
.MapDefaultTimeZone()
.AddCors();

builder.Services.AddHealthChecks();
.AddCors()
.AddHealthChecks();


var app = builder.Build();
Expand All @@ -37,11 +40,12 @@
.UseRequestResponseLogging()
.UseResponseCrafter()
.UseCors()
.MapEndpoints()
.MapMinimalApis()
.MapDefaultEndpoints()
.EnsureHealthy()
.ClearAssemblyRegistry()
.UseOpenApi();
.UseOpenApi()
.MapControllers();

app.MapPost("/params", ([AsParameters] TestTypes testTypes) => TypedResults.Ok(testTypes));
app.MapPost("/body", ([FromBody] TestTypes testTypes) => TypedResults.Ok(testTypes));
Expand Down
1 change: 1 addition & 0 deletions test/SharedKernel.Demo/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"DefaultTimeZone": "Caucasus Standard Time",
"RepositoryName": "be-lib-sharedkernel",
"ConnectionStrings": {
"Redis": "localhost:6379",
"PersistentStorage": "/persistence"
}
}

0 comments on commit f79b677

Please sign in to comment.