-
Notifications
You must be signed in to change notification settings - Fork 309
/
AspireMongoDBDriverExtensions.cs
230 lines (197 loc) · 9.09 KB
/
AspireMongoDBDriverExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire;
using Aspire.MongoDB.Driver;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
using MongoDB.Driver.Core.Configuration;
using MongoDB.Driver.Core.Extensions.DiagnosticSources;
namespace Microsoft.Extensions.Hosting;
/// <summary>
/// Extension methods for connecting MongoDB database with MongoDB.Driver client.
/// </summary>
public static class AspireMongoDBDriverExtensions
{
private const string DefaultConfigSectionName = "Aspire:MongoDB:Driver";
private const string ActivityNameSource = "MongoDB.Driver.Core.Extensions.DiagnosticSources";
/// <summary>
/// Registers <see cref="IMongoClient"/> and <see cref="IMongoDatabase"/> instances for connecting MongoDB database with MongoDB.Driver client.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder" /> to read config from and add services to.</param>
/// <param name="connectionName">A name used to retrieve the connection string from the ConnectionStrings configuration section.</param>
/// <param name="configureSettings">An optional delegate that can be used for customizing options. It's invoked after the settings are read from the configuration.</param>
/// <remarks>Reads the configuration from "Aspire:MongoDB:Driver" section.</remarks>
/// <param name="configureClientSettings">An optional delegate that can be used for customizing MongoClientSettings.</param>
/// <exception cref="InvalidOperationException">Thrown when mandatory <see cref="MongoDBSettings.ConnectionString"/> is not provided.</exception>
public static void AddMongoDBClient(
this IHostApplicationBuilder builder,
string connectionName,
Action<MongoDBSettings>? configureSettings = null,
Action<MongoClientSettings>? configureClientSettings = null)
=> builder.AddMongoDBClient(DefaultConfigSectionName, configureSettings, configureClientSettings, connectionName, serviceKey: null);
/// <summary>
/// Registers <see cref="IMongoClient"/> and <see cref="IMongoDatabase"/> instances for connecting MongoDB database with MongoDB.Driver client.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder" /> to read config from and add services to.</param>
/// <param name="name">The name of the component, which is used as the <see cref="ServiceDescriptor.ServiceKey"/> of the service and also to retrieve the connection string from the ConnectionStrings configuration section.</param>
/// <param name="configureSettings">An optional delegate that can be used for customizing options. It's invoked after the settings are read from the configuration.</param>
/// <remarks>Reads the configuration from "Aspire:MongoDB:Driver:{name}" section.</remarks>
/// <param name="configureClientSettings">An optional delegate that can be used for customizing MongoClientSettings.</param>
/// <exception cref="ArgumentNullException">Thrown if mandatory <paramref name="builder"/> is null.</exception>
/// <exception cref="InvalidOperationException">Thrown when mandatory <see cref="MongoDBSettings.ConnectionString"/> is not provided.</exception>
public static void AddKeyedMongoDBClient(
this IHostApplicationBuilder builder,
string name,
Action<MongoDBSettings>? configureSettings = null,
Action<MongoClientSettings>? configureClientSettings = null)
{
ArgumentException.ThrowIfNullOrEmpty(name);
builder.AddMongoDBClient(
$"{DefaultConfigSectionName}:{name}",
configureSettings,
configureClientSettings,
connectionName: name,
serviceKey: name);
}
private static void AddMongoDBClient(
this IHostApplicationBuilder builder,
string configurationSectionName,
Action<MongoDBSettings>? configureSettings,
Action<MongoClientSettings>? configureClientSettings,
string connectionName,
object? serviceKey)
{
ArgumentNullException.ThrowIfNull(builder);
var settings = builder.GetMongoDBSettings(
connectionName,
configurationSectionName,
configureSettings);
builder.AddMongoClient(
settings,
connectionName,
configurationSectionName,
configureClientSettings,
serviceKey);
if (!settings.DisableTracing)
{
builder.Services
.AddOpenTelemetry()
.WithTracing(tracer => tracer.AddSource(ActivityNameSource));
}
builder.AddMongoDatabase(settings.ConnectionString, serviceKey);
builder.AddHealthCheck(
serviceKey is null ? "MongoDB.Driver" : $"MongoDB.Driver_{connectionName}",
settings);
}
private static void AddMongoClient(
this IHostApplicationBuilder builder,
MongoDBSettings mongoDbSettings,
string connectionName,
string configurationSectionName,
Action<MongoClientSettings>? configureClientSettings,
object? serviceKey)
{
if (serviceKey is null)
{
builder
.Services
.AddSingleton<IMongoClient>(sp => sp.CreateMongoClient(connectionName, configurationSectionName, mongoDbSettings, configureClientSettings));
return;
}
builder
.Services
.AddKeyedSingleton<IMongoClient>(serviceKey, (sp, _) => sp.CreateMongoClient(connectionName, configurationSectionName, mongoDbSettings, configureClientSettings));
}
private static void AddMongoDatabase(
this IHostApplicationBuilder builder,
string? connectionString,
object? serviceKey = null)
{
if (string.IsNullOrWhiteSpace(connectionString))
{
return;
}
var mongoUrl = MongoUrl.Create(connectionString);
if (string.IsNullOrWhiteSpace(mongoUrl.DatabaseName))
{
return;
}
if (serviceKey is null)
{
builder.Services.AddSingleton<IMongoDatabase>(provider =>
{
return provider
.GetRequiredService<IMongoClient>()
.GetDatabase(mongoUrl.DatabaseName);
});
return;
}
builder.Services.AddKeyedSingleton<IMongoDatabase>(serviceKey, (provider, _) =>
{
return provider
.GetRequiredKeyedService<IMongoClient>(serviceKey)
.GetDatabase(mongoUrl.DatabaseName);
});
}
private static void AddHealthCheck(
this IHostApplicationBuilder builder,
string healthCheckName,
MongoDBSettings settings)
{
if (settings.DisableHealthChecks || string.IsNullOrWhiteSpace(settings.ConnectionString))
{
return;
}
builder.TryAddHealthCheck(
healthCheckName,
healthCheck => healthCheck.AddMongoDb(
settings.ConnectionString,
healthCheckName,
null,
null,
settings.HealthCheckTimeout > 0 ? TimeSpan.FromMilliseconds(settings.HealthCheckTimeout.Value) : null));
}
private static MongoClient CreateMongoClient(
this IServiceProvider serviceProvider,
string connectionName,
string configurationSectionName,
MongoDBSettings mongoDbSettings,
Action<MongoClientSettings>? configureClientSettings)
{
mongoDbSettings.ValidateSettings(connectionName, configurationSectionName);
var clientSettings = MongoClientSettings.FromConnectionString(mongoDbSettings.ConnectionString);
if (!mongoDbSettings.DisableTracing)
{
clientSettings.ClusterConfigurator = cb => cb.Subscribe(new DiagnosticsActivityEventSubscriber());
}
configureClientSettings?.Invoke(clientSettings);
clientSettings.LoggingSettings ??= new LoggingSettings(serviceProvider.GetService<ILoggerFactory>());
return new MongoClient(clientSettings);
}
private static MongoDBSettings GetMongoDBSettings(
this IHostApplicationBuilder builder,
string connectionName,
string configurationSectionName,
Action<MongoDBSettings>? configureSettings)
{
var settings = new MongoDBSettings();
builder.Configuration
.GetSection(configurationSectionName)
.Bind(settings);
if (builder.Configuration.GetConnectionString(connectionName) is string connectionString)
{
settings.ConnectionString = connectionString;
}
configureSettings?.Invoke(settings);
return settings;
}
private static void ValidateSettings(
this MongoDBSettings settings,
string connectionName,
string configurationSectionName)
{
ConnectionStringValidation.ValidateConnectionString(settings.ConnectionString, connectionName, configurationSectionName);
}
}