Skip to content

Commit 40a56d2

Browse files
Invoke consumer-defined action when exceptions raised during consumption Redis streams (#1618)
* #1611 Enhanced logging and error handling in RedisConsumer Added new unit tests for various functionalities and configurations. Improved code formatting and consistency across the project. * update summary * OnConsumeError Updates update CapRedisOptions with OnConsumeError option
1 parent c29e8d6 commit 40a56d2

31 files changed

+664
-265
lines changed

CAP.sln

+6
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Dashboard.Jwt", "sam
9191
EndProject
9292
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCore.CAP.Dashboard.K8s", "src\DotNetCore.CAP.Dashboard.K8s\DotNetCore.CAP.Dashboard.K8s.csproj", "{48655118-CEC3-4BD9-B510-64C1195C2729}"
9393
EndProject
94+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetCore.CAP.RedisStreams.Test", "test\DotNetCore.CAP.RedisStreams.Test\DotNetCore.CAP.RedisStreams.Test.csproj", "{789E851F-37B4-49D6-B405-7EC9AA1D2CF8}"
95+
EndProject
9496
Global
9597
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9698
Debug|Any CPU = Debug|Any CPU
@@ -225,6 +227,9 @@ Global
225227
{48655118-CEC3-4BD9-B510-64C1195C2729}.Debug|Any CPU.Build.0 = Debug|Any CPU
226228
{48655118-CEC3-4BD9-B510-64C1195C2729}.Release|Any CPU.ActiveCfg = Release|Any CPU
227229
{48655118-CEC3-4BD9-B510-64C1195C2729}.Release|Any CPU.Build.0 = Release|Any CPU
230+
{789E851F-37B4-49D6-B405-7EC9AA1D2CF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
231+
{789E851F-37B4-49D6-B405-7EC9AA1D2CF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
232+
{789E851F-37B4-49D6-B405-7EC9AA1D2CF8}.Release|Any CPU.Build.0 = Release|Any CPU
228233
EndGlobalSection
229234
GlobalSection(SolutionProperties) = preSolution
230235
HideSolutionNode = FALSE
@@ -262,6 +267,7 @@ Global
262267
{D9681967-DAC2-43EF-999F-3727F1046711} = {C09CDAB0-6DD4-46E9-B7F3-3EF2A4741EA0}
263268
{F739A8C9-565F-4B1D-8F91-FEE056C03FBD} = {3A6B6931-A123-477A-9469-8B468B5385AF}
264269
{48655118-CEC3-4BD9-B510-64C1195C2729} = {9B2AE124-6636-4DE9-83A3-70360DABD0C4}
270+
{789E851F-37B4-49D6-B405-7EC9AA1D2CF8} = {C09CDAB0-6DD4-46E9-B7F3-3EF2A4741EA0}
265271
EndGlobalSection
266272
GlobalSection(ExtensibilityGlobals) = postSolution
267273
SolutionGuid = {2E70565D-94CF-40B4-BFE1-AC18D5F736AB}

docs/content/user-guide/en/transport/redis-streams.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ NAME | DESCRIPTION | TYPE | DEFAULT
4040
Configuration | redis connection configuration (StackExchange.Redis) | ConfigurationOptions | ConfigurationOptions
4141
StreamEntriesCount | number of entries returned from a stream while reading | uint | 10
4242
ConnectionPoolSize | number of connections pool | uint | 10
43-
43+
OnConsumeError | callback function that will be invoked when an error occurred during message consumption. | Func<ConsumeErrorContext, Task> | null
4444
#### Redis Configuration Options
4545

4646
If you need **more** native Redis related configuration options, you can set them in the `Configuration` option:
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,51 @@
11
using DotNetCore.CAP;
22
using DotNetCore.CAP.Messages;
33
using Microsoft.AspNetCore.Mvc;
4-
using Microsoft.Extensions.Logging;
54
using Microsoft.Extensions.Options;
6-
using System.Threading.Tasks;
75

8-
namespace Samples.Redis.SqlServer.Controllers
6+
namespace Samples.Redis.SqlServer.Controllers;
7+
8+
[ApiController]
9+
[Route("[controller]/[action]")]
10+
public class HomeController : ControllerBase
911
{
10-
[ApiController]
11-
[Route("[controller]/[action]")]
12-
public class HomeController : ControllerBase
12+
private readonly ILogger<HomeController> _logger;
13+
private readonly ICapPublisher _publisher;
14+
private readonly IOptions<CapOptions> _options;
15+
16+
public HomeController(ILogger<HomeController> logger, ICapPublisher publisher, IOptions<CapOptions> options)
1317
{
14-
private readonly ILogger<HomeController> _logger;
15-
private readonly ICapPublisher _publisher;
16-
private readonly IOptions<CapOptions> _options;
17-
18-
public HomeController(ILogger<HomeController> logger, ICapPublisher publisher, IOptions<CapOptions> options)
19-
{
20-
_logger = logger;
21-
_publisher = publisher;
22-
this._options = options;
23-
}
24-
25-
[HttpGet]
26-
public async Task Publish([FromQuery] string message = "test-message")
27-
{
28-
await _publisher.PublishAsync(message, new Person() { Age = 11, Name = "James" });
29-
}
30-
31-
[CapSubscribe("test-message")]
32-
[CapSubscribe("test-message-1")]
33-
[CapSubscribe("test-message-2")]
34-
[CapSubscribe("test-message-3")]
35-
[NonAction]
36-
public void Subscribe(Person p, [FromCap] CapHeader header)
37-
{
38-
_logger.LogInformation($"{header[Headers.MessageName]} subscribed with value --> " + p);
39-
}
18+
_logger = logger;
19+
_publisher = publisher;
20+
this._options = options;
21+
}
4022

23+
[HttpGet]
24+
public async Task Publish([FromQuery] string message = "test-message")
25+
{
26+
await _publisher.PublishAsync(message, new Person() { Age = 11, Name = "James" });
4127
}
4228

43-
public class Person
29+
[CapSubscribe("test-message")]
30+
[CapSubscribe("test-message-1")]
31+
[CapSubscribe("test-message-2")]
32+
[CapSubscribe("test-message-3")]
33+
[NonAction]
34+
public void Subscribe(Person p, [FromCap] CapHeader header)
4435
{
45-
public string Name { get; set; }
36+
_logger.LogInformation($"{header[Headers.MessageName]} subscribed with value --> " + p);
37+
}
4638

47-
public int Age { get; set; }
39+
}
40+
41+
public class Person
42+
{
43+
public string Name { get; set; }
4844

49-
public override string ToString()
50-
{
51-
return "Name:" + Name + ", Age:" + Age;
52-
}
45+
public int Age { get; set; }
46+
47+
public override string ToString()
48+
{
49+
return "Name:" + Name + ", Age:" + Age;
5350
}
5451
}

samples/Samples.Redis.SqlServer/Dockerfile

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
1-
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
1+
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
22

3-
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
3+
# This stage is used when running from VS in fast mode (Default for Debug configuration)
4+
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
5+
USER $APP_UID
46
WORKDIR /app
57
EXPOSE 80
6-
EXPOSE 443
78

8-
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
9+
# This stage is used to build the service project
10+
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
11+
ARG BUILD_CONFIGURATION=Release
912
WORKDIR /src
13+
COPY ["src/Directory.Build.props", "src/"]
1014
COPY ["samples/Samples.Redis.SqlServer/Samples.Redis.SqlServer.csproj", "samples/Samples.Redis.SqlServer/"]
1115
COPY ["src/DotNetCore.CAP.RedisStreams/DotNetCore.CAP.RedisStreams.csproj", "src/DotNetCore.CAP.RedisStreams/"]
1216
COPY ["src/DotNetCore.CAP/DotNetCore.CAP.csproj", "src/DotNetCore.CAP/"]
1317
COPY ["src/DotNetCore.CAP.SqlServer/DotNetCore.CAP.SqlServer.csproj", "src/DotNetCore.CAP.SqlServer/"]
14-
RUN dotnet restore "samples/Samples.Redis.SqlServer/Samples.Redis.SqlServer.csproj"
18+
RUN dotnet restore "./samples/Samples.Redis.SqlServer/Samples.Redis.SqlServer.csproj"
1519
COPY . .
1620
WORKDIR "/src/samples/Samples.Redis.SqlServer"
17-
RUN dotnet build "Samples.Redis.SqlServer.csproj" -c Release -o /app/build
21+
RUN dotnet build "./Samples.Redis.SqlServer.csproj" -c $BUILD_CONFIGURATION -o /app/build
1822

23+
# This stage is used to publish the service project to be copied to the final stage
1924
FROM build AS publish
20-
RUN dotnet publish "Samples.Redis.SqlServer.csproj" -c Release -o /app/publish
25+
ARG BUILD_CONFIGURATION=Release
26+
RUN dotnet publish "./Samples.Redis.SqlServer.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
2127

28+
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
2229
FROM base AS final
2330
WORKDIR /app
2431
COPY --from=publish /app/publish .
+42-16
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,46 @@
1-
using Microsoft.AspNetCore.Hosting;
2-
using Microsoft.Extensions.Hosting;
31

4-
namespace Samples.Redis.SqlServer
5-
{
6-
public class Program
2+
using StackExchange.Redis;
3+
4+
var builder = WebApplication.CreateBuilder(args);
5+
6+
builder.Services
7+
.AddControllers();
8+
9+
builder.Services
10+
.AddEndpointsApiExplorer();
11+
builder.Services
12+
.AddSwaggerGen();
13+
14+
builder.Services
15+
.AddCap(options =>
716
{
8-
public static void Main(string[] args)
17+
options.UseRedis(redis =>
918
{
10-
CreateHostBuilder(args).Build().Run();
11-
}
12-
13-
public static IHostBuilder CreateHostBuilder(string[] args) =>
14-
Host.CreateDefaultBuilder(args)
15-
.ConfigureWebHostDefaults(webBuilder =>
16-
{
17-
webBuilder.UseStartup<Startup>();
18-
});
19-
}
19+
redis.Configuration = ConfigurationOptions.Parse("redis-node-0:6379,password=cap");
20+
redis.OnConsumeError = context =>
21+
{
22+
throw new InvalidOperationException("");
23+
};
24+
});
25+
26+
options.UseSqlServer("Server=db;Database=master;User=sa;Password=P@ssw0rd;Encrypt=False");
27+
28+
options.UseDashboard();
29+
30+
});
31+
32+
var app = builder.Build();
33+
34+
if (app.Environment.IsDevelopment())
35+
{
36+
app.UseSwagger();
37+
app.UseSwaggerUI();
2038
}
39+
40+
app.UseHttpsRedirection();
41+
42+
app.UseAuthorization();
43+
44+
app.MapControllers();
45+
46+
app.Run();
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
2-
3-
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
5-
<UserSecretsId>eb622624-fbc4-46d0-b006-dfe8e66df5bb</UserSecretsId>
6-
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
7-
<DockerfileContext>..\..</DockerfileContext>
8-
<DockerComposeProjectPath>..\..\docker-compose.dcproj</DockerComposeProjectPath>
9-
</PropertyGroup>
10-
11-
<ItemGroup>
12-
<ProjectReference Include="..\..\src\DotNetCore.CAP.RedisStreams\DotNetCore.CAP.RedisStreams.csproj" />
13-
<ProjectReference Include="..\..\src\DotNetCore.CAP.SqlServer\DotNetCore.CAP.SqlServer.csproj" />
14-
</ItemGroup>
15-
16-
</Project>
2+
<PropertyGroup>
3+
<TargetFramework>net8.0</TargetFramework>
4+
<UserSecretsId>eb622624-fbc4-46d0-b006-dfe8e66df5bb</UserSecretsId>
5+
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<DockerfileContext>..\..</DockerfileContext>
8+
<DockerComposeProjectPath>..\..\docker-compose.dcproj</DockerComposeProjectPath>
9+
</PropertyGroup>
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
12+
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
13+
</ItemGroup>
14+
<ItemGroup>
15+
<ProjectReference Include="..\..\src\DotNetCore.CAP.Dashboard\DotNetCore.CAP.Dashboard.csproj" />
16+
<ProjectReference Include="..\..\src\DotNetCore.CAP.RedisStreams\DotNetCore.CAP.RedisStreams.csproj" />
17+
<ProjectReference Include="..\..\src\DotNetCore.CAP.SqlServer\DotNetCore.CAP.SqlServer.csproj" />
18+
</ItemGroup>
19+
</Project>

samples/Samples.Redis.SqlServer/Startup.cs

-37
This file was deleted.

samples/Samples.Redis.SqlServer/appsettings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
"Microsoft.Hosting.Lifetime": "Information"
77
}
88
},
9-
"AllowedHosts": "*"
9+
"AllowedHosts": "*"
1010
}

samples/Samples.Redis.SqlServer/docker-compose.yml

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,48 @@
1-
version: '2'
21
services:
32
redis-node-0:
4-
image: docker.io/bitnami/redis-cluster:6.2
3+
image: docker.io/bitnami/redis-cluster:7.0
54
volumes:
65
- redis-cluster_data-0:/bitnami/redis/data
76
environment:
87
- 'REDIS_PASSWORD=cap'
98
- 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5'
109

1110
redis-node-1:
12-
image: docker.io/bitnami/redis-cluster:6.2
11+
image: docker.io/bitnami/redis-cluster:7.0
1312
volumes:
1413
- redis-cluster_data-1:/bitnami/redis/data
1514
environment:
1615
- 'REDIS_PASSWORD=cap'
1716
- 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5'
1817

1918
redis-node-2:
20-
image: docker.io/bitnami/redis-cluster:6.2
19+
image: docker.io/bitnami/redis-cluster:7.0
2120
volumes:
2221
- redis-cluster_data-2:/bitnami/redis/data
2322
environment:
2423
- 'REDIS_PASSWORD=cap'
2524
- 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5'
2625

2726
redis-node-3:
28-
image: docker.io/bitnami/redis-cluster:6.2
27+
image: docker.io/bitnami/redis-cluster:7.0
2928
volumes:
3029
- redis-cluster_data-3:/bitnami/redis/data
3130
environment:
3231
- 'REDIS_PASSWORD=cap'
3332
- 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5'
3433

3534
redis-node-4:
36-
image: docker.io/bitnami/redis-cluster:6.2
35+
image: docker.io/bitnami/redis-cluster:7.0
3736
volumes:
3837
- redis-cluster_data-4:/bitnami/redis/data
3938
environment:
4039
- 'REDIS_PASSWORD=cap'
4140
- 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5'
4241

4342
redis-node-5:
44-
image: docker.io/bitnami/redis-cluster:6.2
43+
image: docker.io/bitnami/redis-cluster:7.0
44+
ports:
45+
- 6379:6379
4546
volumes:
4647
- redis-cluster_data-5:/bitnami/redis/data
4748
depends_on:
@@ -63,14 +64,17 @@ services:
6364
- 1433:1433
6465
environment:
6566
SA_PASSWORD: "P@ssw0rd"
66-
ACCEPT_EULA: "Y"
67+
ACCEPT_EULA: "Y"
6768

6869
redis-sample:
6970
build:
7071
context: ../..
7172
dockerfile: samples/Samples.Redis.SqlServer/Dockerfile
73+
environment:
74+
- ASPNETCORE_URLS:http://*:8080
75+
- ASPNETCORE_ENVIRONMENT=Development
7276
ports:
73-
- 5000:80
77+
- 8080:8080
7478
depends_on:
7579
- db
7680
- redis-node-5
@@ -87,4 +91,4 @@ volumes:
8791
redis-cluster_data-4:
8892
driver: local
8993
redis-cluster_data-5:
90-
driver: local
94+
driver: local

0 commit comments

Comments
 (0)