Skip to content

Commit 2a3a245

Browse files
authored
make MigrateDb threadsafe (#1613)
1 parent 7ebe8dc commit 2a3a245

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

backend/FwLite/LcmCrdt/CurrentProjectService.cs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.EntityFrameworkCore;
1+
using System.Collections.Concurrent;
2+
using Microsoft.EntityFrameworkCore;
23
using Microsoft.Extensions.Caching.Memory;
34
using Microsoft.Extensions.DependencyInjection;
45
using Microsoft.Extensions.Logging;
@@ -82,18 +83,27 @@ public async ValueTask<ProjectData> RefreshProjectData()
8283
return projectData;
8384
}
8485

85-
private async Task MigrateDb()
86+
private static readonly ConcurrentDictionary<string, Lazy<Task>> MigrationTasks = [];
87+
private Task MigrateDb()
8688
{
87-
try
89+
//ensure we only execute once, otherwise we'll have a conflict as Migrate is not thread safe.
90+
//design based on https://andrewlock.net/making-getoradd-on-concurrentdictionary-thread-safe-using-lazy/
91+
#pragma warning disable VSTHRD011
92+
return MigrationTasks.GetOrAdd(Project.DbPath, _ => new Lazy<Task>(Execute)).Value;
93+
#pragma warning restore VSTHRD011
94+
async Task Execute()
8895
{
89-
90-
await DbContext.Database.MigrateAsync();
91-
}
92-
catch (Exception e)
93-
{
94-
logger.LogError(e, "Failed to migrate database for project '{Project}'", Project.Name);
95-
throw;
96+
try
97+
{
98+
await DbContext.Database.MigrateAsync();
99+
}
100+
catch (Exception e)
101+
{
102+
logger.LogError(e, "Failed to migrate database for project '{Project}'", Project.Name);
103+
throw;
104+
}
96105
}
106+
97107
}
98108

99109
public async Task SetProjectSyncOrigin(Uri? domain, Guid? id)

0 commit comments

Comments
 (0)