Skip to content

Commit 4f36f3d

Browse files
myieyeclaude
andcommitted
Fix morph-types seed race condition
Bump Harmony submodule to include the in-lock HasCommit check (sillsdev/harmony#66), which closes the TOCTOU race between concurrent AddPredefinedMorphTypes callers on a fresh project (BG sync's CreateProject vs. HTTP middleware's MigrateDb). The MigrateDb pre-check was a small optimization, not a race guard — drop it, let Harmony's in-lock check handle idempotency. Note: won't build on develop until the .NET 10 chore lands (Harmony main is on .NET 10). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 52ae636 commit 4f36f3d

2 files changed

Lines changed: 7 additions & 9 deletions

File tree

backend/FwLite/LcmCrdt/CurrentProjectService.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,13 @@ async Task Execute()
108108
await using var dbContext = await DbContextFactory.CreateDbContextAsync();
109109
await dbContext.Database.MigrateAsync();
110110

111-
// Seed morph-types if missing (for existing projects created before morph-type support).
111+
// Seed morph-types for projects created before morph-type support.
112+
// AddChanges is idempotent on the seed commit-id (Harmony short-circuits in-lock),
113+
// so we call it unconditionally rather than racing a pre-check against concurrent seeders.
112114
// Must happen BEFORE FTS regeneration so headwords include morph-type tokens.
113-
// (querying Commits instead of MorphTypes, because the commit may not be projected yet)
114-
if (!await dbContext.Set<Commit>().AsNoTracking().AnyAsync(c => c.Id == PreDefinedData.MorphTypesSeedCommitId))
115-
{
116-
var dataModel = services.GetRequiredService<DataModel>();
117-
var projectData = await dbContext.ProjectData.AsNoTracking().FirstAsync();
118-
await PreDefinedData.AddPredefinedMorphTypes(dataModel, projectData.ClientId);
119-
}
115+
var dataModel = services.GetRequiredService<DataModel>();
116+
var projectData = await dbContext.ProjectData.AsNoTracking().FirstAsync();
117+
await PreDefinedData.AddPredefinedMorphTypes(dataModel, projectData.ClientId);
120118

121119
if (EntrySearchServiceFactory is not null)
122120
{

0 commit comments

Comments
 (0)