• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mehdihadeli / food-delivery-microservices / 28675368858

03 Jul 2026 05:34PM UTC coverage: 16.207% (-46.9%) from 63.071%
28675368858

push

github

web-flow
feat: replace masstransit with wolverine (#253)

337 of 3348 branches covered (10.07%)

Branch coverage included in aggregate %.

125 of 258 new or added lines in 26 files covered. (48.45%)

1396 of 7345 relevant lines covered (19.01%)

0.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.32
/src/BuildingBlocks/BuildingBlocks.Caching/Extensions/DependencyInjectionExtensions.cs
1
using BuildingBlocks.Abstractions.Caching;
2
using BuildingBlocks.Caching.Serializers.MessagePack;
3
using BuildingBlocks.Core.Extensions;
4
using BuildingBlocks.Core.Extensions.HostApplicationBuilderExtensions;
5
using BuildingBlocks.Core.Extensions.ServiceCollectionExtensions;
6
using Medallion.Threading;
7
using Medallion.Threading.Redis;
8
using Microsoft.Extensions.Caching.Hybrid;
9
using Microsoft.Extensions.Configuration;
10
using Microsoft.Extensions.Hosting;
11
using OpenTelemetry.Instrumentation.StackExchangeRedis;
12
using OpenTelemetry.Trace;
13
using StackExchange.Redis;
14

15
namespace BuildingBlocks.Caching.Extensions;
16

17
#pragma warning disable EXTEXP0018
18

19
public static class DependencyInjectionExtensions
20
{
21
    public static IHostApplicationBuilder AddCustomCaching(
22
        this IHostApplicationBuilder builder,
23
        string? redisConnectionStringName = null
24
    )
25
    {
26
        ArgumentNullException.ThrowIfNull(builder);
2✔
27

28
        builder.Services.AddConfigurationOptions<CacheOptions>(nameof(CacheOptions));
2✔
29
        var cacheOptions = builder.Configuration.BindOptions<CacheOptions>(nameof(CacheOptions));
2✔
30

31
        AddRedis(builder, redisConnectionStringName, cacheOptions.RedisDistributedCacheOptions);
2✔
32

33
        builder.Services.AddSingleton<ICacheService, CacheService>();
2✔
34

35
        var hybridCacheBuilder = builder.Services.AddHybridCache(options =>
2✔
36
        {
2✔
37
            options.MaximumPayloadBytes = cacheOptions.MaximumPayloadBytes;
2✔
38
            options.MaximumKeyLength = cacheOptions.MaximumKeyLength;
2✔
39
            options.DefaultEntryOptions = new HybridCacheEntryOptions
2✔
40
            {
2✔
41
                Expiration = TimeSpan.FromMinutes(cacheOptions.ExpirationTimeInMinute),
2✔
42
                LocalCacheExpiration = TimeSpan.FromMinutes(cacheOptions.ExpirationTimeInMinute),
2✔
43
            };
2✔
44
        });
2✔
45

46
        switch (cacheOptions.SerializationType)
2✔
47
        {
48
            case CacheSerializationType.MessagePack:
49
                {
50
                    hybridCacheBuilder.AddSerializerFactory<MessagePackHybridCacheSerializerFactory>();
×
51
                }
52

53
                break;
54
        }
55

56
        return builder;
2✔
57
    }
58

59
    private static void AddRedis(
60
        IHostApplicationBuilder builder,
61
        string? redisConnectionStringName,
62
        RedisDistributedCacheOptions redisDistributedCacheOptions
63
    )
64
    {
65
        ArgumentNullException.ThrowIfNull(builder);
2✔
66

67
        string redisConnectionString;
68

69
        // ConnectionString is not injected by aspire
70
        if (
2!
71
            redisConnectionStringName is null
2✔
72
            || string.IsNullOrWhiteSpace(builder.Configuration.GetConnectionString(redisConnectionStringName))
2✔
73
        )
2✔
74
        {
75
            redisConnectionString =
2!
76
                redisDistributedCacheOptions.ConnectionString
2✔
77
                ?? throw new InvalidOperationException(
2✔
78
                    "`RedisDistributedCacheOptions.ConnectionString` can't be null."
2✔
79
                );
2✔
80

81
            // https://learn.microsoft.com/en-us/aspnet/core/performance/caching/hybrid
82
            // https://learn.microsoft.com/en-us/aspnet/core/performance/caching/overview
83
            // If the app has an IDistributedCache implementation, the HybridCache service uses it for secondary caching. This two-level caching strategy allows HybridCache to provide the speed of an in-memory cache and the durability of a distributed or persistent cache.
84
            builder.Services.AddSingleton<IConnectionMultiplexer>(sp => CreateConnection(sp, redisConnectionString));
×
85

86
            ConfigureRedisInstrumentation(builder, redisDistributedCacheOptions);
2✔
87
        }
88
        else
89
        {
90
            // - EnvironmentVariablesConfigurationProvider is injected by aspire and use to read configuration values from environment variables with `ConnectionStrings:redis` key on configuration.
91
            // The configuration provider handles these conversions automatically, and `__ (double underscore)` becomes `:` for nested sections, so environment configuration reads its data from the ` ConnectionStrings__redis ` environment. all envs are available in `Environment.GetEnvironmentVariables()`.
92
            // - For setting none sensitive configuration, we can use Aspire named configuration `Aspire:StackExchange:Redis:DisableHealthChecks` which is of type ConfigurationProvider and should be set in appsetting.json
93
            redisConnectionString =
×
94
                builder.Configuration.GetConnectionString(redisConnectionStringName)
×
95
                ?? throw new InvalidOperationException(
×
96
                    $"Redis connection string '{redisConnectionStringName}' not found."
×
97
                );
×
98

99
            // ConnectionString is injected by aspire
100
            // https://learn.microsoft.com/en-us/dotnet/aspire/caching/stackexchange-redis-integration?tabs=dotnet-cli&pivots=redis#client-integration
101
            builder.AddRedisClient(redisConnectionStringName);
×
102
        }
103

104
        builder.Services.AddSingleton<IRedisPubSubService, RedisPubSubService>();
2✔
105
        // add redis distributed lock
106
        builder.Services.AddSingleton<IDistributedLockProvider>(sp =>
2✔
107
        {
2✔
NEW
108
            var multiplexer = sp.GetRequiredService<IConnectionMultiplexer>();
×
109

2✔
NEW
110
            return new RedisDistributedSynchronizationProvider(multiplexer.GetDatabase());
×
111
        });
2✔
112
    }
2✔
113

114
    private static void ConfigureRedisInstrumentation(
115
        IHostApplicationBuilder builder,
116
        RedisDistributedCacheOptions redisDistributedCacheOptions
117
    )
118
    {
119
        if (!redisDistributedCacheOptions.DisableTracing)
2✔
120
        {
121
            builder
2✔
122
                .Services.AddOpenTelemetry()
2✔
123
                .WithTracing(t =>
2✔
124
                {
2✔
125
                    t.AddSource("OpenTelemetry.Instrumentation.StackExchangeRedis");
2✔
126
                    // This ensures the core Redis instrumentation services from OpenTelemetry.Instrumentation.StackExchangeRedis are added
2✔
127
                    t.ConfigureRedisInstrumentation(_ => { });
2✔
128
                    // This ensures that any logic performed by the AddInstrumentation method is executed (this is usually called by AddRedisInstrumentation())
2✔
129
                    t.AddInstrumentation(sp => sp.GetRequiredService<StackExchangeRedisInstrumentation>());
2✔
130
                });
2✔
131
        }
132

133
        if (!redisDistributedCacheOptions.DisableHealthChecks)
2✔
134
        {
135
            builder.TryAddHealthCheck(
2✔
136
                name: "StackExchange.Redis",
2✔
137
                healthCheckRegistration =>
2✔
138
                    healthCheckRegistration.AddRedis(
2✔
139
                        connectionMultiplexerFactory: sp => sp.GetRequiredService<IConnectionMultiplexer>(),
×
140
                        name: "StackExchange.Redis",
2✔
141
                        tags: ["live"]
2✔
142
                    )
2✔
143
            );
2✔
144
        }
145
    }
2✔
146

147
    private static ConnectionMultiplexer CreateConnection(IServiceProvider serviceProvider, string connectionString)
148
    {
149
        var configurationOptions = ConfigurationOptions.Parse(connectionString);
×
150

151
        var connection = ConnectionMultiplexer.Connect(configurationOptions);
×
152

153
        // Add the connection to instrumentation
154
        var instrumentation = serviceProvider.GetService<StackExchangeRedisInstrumentation>();
×
155
        instrumentation?.AddConnection(connection);
×
156

157
        return connection;
×
158
    }
159
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc