Skip to content

Commit e9f8cf8

Browse files
committed
Small improvements
1 parent 33b787a commit e9f8cf8

19 files changed

+119
-2701
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace ServiceControl.Persistence.Sql.Core.Abstractions;
2+
3+
using Microsoft.Extensions.DependencyInjection;
4+
using ServiceControl.Persistence;
5+
using ServiceControl.Persistence.MessageRedirects;
6+
using Implementation;
7+
8+
public abstract class BasePersistence
9+
{
10+
protected static void RegisterDataStores(IServiceCollection services, bool maintenanceMode)
11+
{
12+
if (maintenanceMode)
13+
{
14+
return;
15+
}
16+
17+
services.AddSingleton<ITrialLicenseDataProvider, TrialLicenseDataProvider>();
18+
services.AddSingleton<IEndpointSettingsStore, EndpointSettingsStore>();
19+
services.AddSingleton<IEventLogDataStore, EventLogDataStore>();
20+
services.AddSingleton<IMessageRedirectsDataStore, MessageRedirectsDataStore>();
21+
services.AddSingleton<IServiceControlSubscriptionStorage, ServiceControlSubscriptionStorage>();
22+
services.AddSingleton<IQueueAddressStore, QueueAddressStore>();
23+
services.AddSingleton<IMonitoringDataStore, MonitoringDataStore>();
24+
services.AddSingleton<ICustomChecksDataStore, CustomChecksDataStore>();
25+
services.AddSingleton<Operations.BodyStorage.IBodyStorage, BodyStorage>();
26+
services.AddSingleton<IRetryHistoryDataStore, RetryHistoryDataStore>();
27+
services.AddSingleton<IFailedErrorImportDataStore, FailedErrorImportDataStore>();
28+
services.AddSingleton<IExternalIntegrationRequestsDataStore, ExternalIntegrationRequestsDataStore>();
29+
services.AddSingleton<IFailedMessageViewIndexNotifications, FailedMessageViewIndexNotifications>();
30+
services.AddSingleton<Recoverability.IArchiveMessages, ArchiveMessages>();
31+
services.AddSingleton<IGroupsDataStore, GroupsDataStore>();
32+
services.AddSingleton<IRetryDocumentDataStore, RetryDocumentDataStore>();
33+
services.AddSingleton<IRetryBatchesDataStore, RetryBatchesDataStore>();
34+
// TODO: Implement IErrorMessageDataStore
35+
// services.AddSingleton<IErrorMessageDataStore, ErrorMessageDataStore>();
36+
}
37+
}

src/ServiceControl.Persistence.Sql.Core/Implementation/CustomChecksDataStore.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public async Task<QueryResult<IList<CustomCheck>>> GetStats(PagingInfo paging, s
8282
.OrderByDescending(c => c.ReportedAt)
8383
.Skip(paging.Offset)
8484
.Take(paging.Next)
85+
.AsNoTracking()
8586
.ToListAsync();
8687

8788
var customChecks = results.Select(e => new CustomCheck

src/ServiceControl.Persistence.Sql.Core/Implementation/GroupsDataStore.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public async Task<IList<FailureGroupView>> GetFailureGroupsByClassifier(string c
2828

2929
// Query failed messages with unresolved status to build failure group views
3030
var failedMessages = await dbContext.FailedMessages
31+
.AsNoTracking()
3132
.Where(m => m.Status == FailedMessageStatus.Unresolved)
3233
.Select(m => new
3334
{
@@ -69,6 +70,7 @@ public async Task<IList<FailureGroupView>> GetFailureGroupsByClassifier(string c
6970
// Load comments for these groups
7071
var groupIds = groupViews.Select(g => g.Group.Id).ToList();
7172
var commentLookup = await dbContext.GroupComments
73+
.AsNoTracking()
7274
.Where(c => groupIds.Contains(c.GroupId))
7375
.ToDictionaryAsync(c => c.GroupId, c => c.Comment);
7476

@@ -93,6 +95,7 @@ public async Task<IList<FailureGroupView>> GetFailureGroupsByClassifier(string c
9395
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
9496

9597
var nowForwarding = await dbContext.RetryBatchNowForwarding
98+
.AsNoTracking()
9699
.FirstOrDefaultAsync(r => r.Id == RetryBatchNowForwarding.Id);
97100

98101
if (nowForwarding == null || string.IsNullOrEmpty(nowForwarding.RetryBatchId))
@@ -101,6 +104,7 @@ public async Task<IList<FailureGroupView>> GetFailureGroupsByClassifier(string c
101104
}
102105

103106
var batchEntity = await dbContext.RetryBatches
107+
.AsNoTracking()
104108
.FirstOrDefaultAsync(b => b.Id == nowForwarding.RetryBatchId);
105109

106110
if (batchEntity == null)

src/ServiceControl.Persistence.Sql.Core/Implementation/MonitoringDataStore.cs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,21 +84,17 @@ public async Task UpdateEndpointMonitoring(EndpointDetails endpoint, bool isMoni
8484
using var scope = serviceProvider.CreateScope();
8585
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
8686

87-
var knownEndpoint = await dbContext.KnownEndpoints.FirstOrDefaultAsync(e => e.Id == id);
88-
89-
if (knownEndpoint != null)
90-
{
91-
knownEndpoint.Monitored = isMonitored;
92-
await dbContext.SaveChangesAsync();
93-
}
87+
await dbContext.KnownEndpoints
88+
.Where(e => e.Id == id)
89+
.ExecuteUpdateAsync(setters => setters.SetProperty(e => e.Monitored, isMonitored));
9490
}
9591

9692
public async Task WarmupMonitoringFromPersistence(IEndpointInstanceMonitoring endpointInstanceMonitoring)
9793
{
9894
using var scope = serviceProvider.CreateScope();
9995
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
10096

101-
var endpoints = await dbContext.KnownEndpoints.ToListAsync();
97+
var endpoints = await dbContext.KnownEndpoints.AsNoTracking().ToListAsync();
10298

10399
foreach (var endpoint in endpoints)
104100
{
@@ -118,20 +114,17 @@ public async Task Delete(Guid endpointId)
118114
using var scope = serviceProvider.CreateScope();
119115
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
120116

121-
var knownEndpoint = await dbContext.KnownEndpoints.FirstOrDefaultAsync(e => e.Id == endpointId);
122-
if (knownEndpoint != null)
123-
{
124-
dbContext.KnownEndpoints.Remove(knownEndpoint);
125-
await dbContext.SaveChangesAsync();
126-
}
117+
await dbContext.KnownEndpoints
118+
.Where(e => e.Id == endpointId)
119+
.ExecuteDeleteAsync();
127120
}
128121

129122
public async Task<IReadOnlyList<KnownEndpoint>> GetAllKnownEndpoints()
130123
{
131124
using var scope = serviceProvider.CreateScope();
132125
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
133126

134-
var entities = await dbContext.KnownEndpoints.ToListAsync();
127+
var entities = await dbContext.KnownEndpoints.AsNoTracking().ToListAsync();
135128

136129
return entities.Select(e => new KnownEndpoint
137130
{

src/ServiceControl.Persistence.Sql.Core/Implementation/QueueAddressStore.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public async Task<QueryResult<IList<QueueAddress>>> GetAddresses(PagingInfo pagi
3030
.OrderBy(q => q.PhysicalAddress)
3131
.Skip(pagingInfo.Offset)
3232
.Take(pagingInfo.Next)
33+
.AsNoTracking()
3334
.Select(q => new QueueAddress
3435
{
3536
PhysicalAddress = q.PhysicalAddress,
@@ -55,6 +56,7 @@ public async Task<QueryResult<IList<QueueAddress>>> GetAddressesBySearchTerm(str
5556
.OrderBy(q => q.PhysicalAddress)
5657
.Skip(pagingInfo.Offset)
5758
.Take(pagingInfo.Next)
59+
.AsNoTracking()
5860
.Select(q => new QueueAddress
5961
{
6062
PhysicalAddress = q.PhysicalAddress,

src/ServiceControl.Persistence.Sql.Core/Implementation/RetryBatchesDataStore.cs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,9 @@ public async Task IncrementAttemptCounter(FailedMessageRetry message)
6868

6969
try
7070
{
71-
var entity = await dbContext.FailedMessageRetries
72-
.FirstOrDefaultAsync(f => f.Id == message.Id);
73-
74-
if (entity != null)
75-
{
76-
entity.StageAttempts++;
77-
await dbContext.SaveChangesAsync();
78-
}
71+
await dbContext.FailedMessageRetries
72+
.Where(f => f.Id == message.Id)
73+
.ExecuteUpdateAsync(setters => setters.SetProperty(f => f.StageAttempts, f => f.StageAttempts + 1));
7974
}
8075
catch (DbUpdateConcurrencyException)
8176
{
@@ -90,13 +85,9 @@ public async Task DeleteFailedMessageRetry(string uniqueMessageId)
9085
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
9186

9287
var documentId = FailedMessageRetry.MakeDocumentId(uniqueMessageId);
93-
var entity = await dbContext.FailedMessageRetries
94-
.FirstOrDefaultAsync(f => f.Id == documentId);
9588

96-
if (entity != null)
97-
{
98-
dbContext.FailedMessageRetries.Remove(entity);
99-
await dbContext.SaveChangesAsync();
100-
}
89+
await dbContext.FailedMessageRetries
90+
.Where(f => f.Id == documentId)
91+
.ExecuteDeleteAsync();
10192
}
10293
}

src/ServiceControl.Persistence.Sql.Core/Implementation/RetryDocumentDataStore.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public async Task<QueryResult<IList<RetryBatch>>> QueryOrphanedBatches(string re
123123

124124
var orphanedBatches = await dbContext.RetryBatches
125125
.Where(b => b.Status == RetryBatchStatus.MarkingDocuments && b.RetrySessionId != retrySessionId)
126+
.AsNoTracking()
126127
.ToListAsync();
127128

128129
var result = orphanedBatches.Select(entity => new RetryBatch
@@ -152,6 +153,7 @@ public async Task<IList<RetryBatchGroup>> QueryAvailableBatches()
152153

153154
// Query all batches that are either Staging or Forwarding
154155
var results = await dbContext.RetryBatches
156+
.AsNoTracking()
155157
.Where(b => b.Status == RetryBatchStatus.Staging || b.Status == RetryBatchStatus.Forwarding)
156158
.GroupBy(b => new { b.RequestId, b.RetryType, b.Originator, b.Classifier })
157159
.Select(g => new RetryBatchGroup
@@ -177,6 +179,7 @@ public async Task GetBatchesForAll(DateTime cutoff, Func<string, DateTime, Task>
177179
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
178180

179181
var messages = dbContext.FailedMessages
182+
.AsNoTracking()
180183
.Where(m => m.Status == FailedMessageStatus.Unresolved)
181184
.Select(m => new
182185
{
@@ -198,6 +201,7 @@ public async Task GetBatchesForEndpoint(DateTime cutoff, string endpoint, Func<s
198201
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
199202

200203
var messages = dbContext.FailedMessages
204+
.AsNoTracking()
201205
.Where(m => m.Status == FailedMessageStatus.Unresolved && m.ReceivingEndpoint == endpoint)
202206
.Select(m => new
203207
{
@@ -219,6 +223,7 @@ public async Task GetBatchesForFailedQueueAddress(DateTime cutoff, string failed
219223
var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContextBase>();
220224

221225
var messages = dbContext.FailedMessages
226+
.AsNoTracking()
222227
.Where(m => m.Status == FailedMessageStatus.Unresolved && m.QueueAddress == failedQueueAddress && m.Status == status)
223228
.Select(m => new
224229
{
@@ -241,6 +246,7 @@ public async Task GetBatchesForFailureGroup(string groupId, string groupTitle, s
241246

242247
// Query all unresolved messages and filter by group in memory (since groups are in JSON)
243248
var messages = await dbContext.FailedMessages
249+
.AsNoTracking()
244250
.Where(m => m.Status == FailedMessageStatus.Unresolved)
245251
.Select(m => new
246252
{
@@ -268,6 +274,7 @@ public async Task GetBatchesForFailureGroup(string groupId, string groupTitle, s
268274

269275
// Query all unresolved messages and find those with this group
270276
var messages = await dbContext.FailedMessages
277+
.AsNoTracking()
271278
.Where(m => m.Status == FailedMessageStatus.Unresolved)
272279
.Select(m => new
273280
{

src/ServiceControl.Persistence.Sql.MySQL/Migrations/20251209025347_InitialCreate.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,21 @@ protected override void Up(MigrationBuilder migrationBuilder)
253253
})
254254
.Annotation("MySql:CharSet", "utf8mb4");
255255

256+
migrationBuilder.CreateTable(
257+
name: "NotificationsSettings",
258+
columns: table => new
259+
{
260+
Id = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false)
261+
.Annotation("MySql:CharSet", "utf8mb4"),
262+
EmailSettingsJson = table.Column<string>(type: "longtext", nullable: false)
263+
.Annotation("MySql:CharSet", "utf8mb4")
264+
},
265+
constraints: table =>
266+
{
267+
table.PrimaryKey("PK_NotificationsSettings", x => x.Id);
268+
})
269+
.Annotation("MySql:CharSet", "utf8mb4");
270+
256271
migrationBuilder.CreateIndex(
257272
name: "IX_ArchiveOperations_ArchiveState",
258273
table: "ArchiveOperations",
@@ -320,6 +335,9 @@ protected override void Down(MigrationBuilder migrationBuilder)
320335

321336
migrationBuilder.DropTable(
322337
name: "TrialLicense");
338+
339+
migrationBuilder.DropTable(
340+
name: "NotificationsSettings");
323341
}
324342
}
325343
}

0 commit comments

Comments
 (0)