From c89ff84de83f34d8810d2de0c5fb23c75b4475cc Mon Sep 17 00:00:00 2001 From: Tim Haasdyk Date: Wed, 22 Oct 2025 17:11:16 +0200 Subject: [PATCH 1/2] Only regenerate snapshot if Send/Receive works --- backend/FwHeadless/Services/SyncHostedService.cs | 16 ++++++++++++++++ .../FwLiteProjectSync.Tests/CrdtRepairTests.cs | 2 ++ .../FwLiteProjectSync.Tests/Sena3SyncTests.cs | 1 + .../CrdtFwdataProjectSyncService.cs | 8 -------- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/backend/FwHeadless/Services/SyncHostedService.cs b/backend/FwHeadless/Services/SyncHostedService.cs index 036644914e..8c2117dad4 100644 --- a/backend/FwHeadless/Services/SyncHostedService.cs +++ b/backend/FwHeadless/Services/SyncHostedService.cs @@ -208,6 +208,22 @@ public async Task ExecuteSync(CancellationToken stoppingToken, bo logger.LogInformation("Send/Receive result after CRDT sync: {Output}", srResult2.Output); } } + + //We only want to regenerate the snapshot if we know the changes applied to fwdata were successfully pushed. + //Otherwise, the changes might have been rolled back. + if (result.CrdtChanges > 0) + { + logger.LogInformation("Regenerating project snapshot to include crdt changes"); + //note we are now using the crdt API, this avoids issues where some data isn't synced yet + //later when we add the ability to sync that data we need the snapshot to reflect the synced state, not what was in the FW project + //related to https://github.com/sillsdev/languageforge-lexbox/issues/1912 + await syncService.RegenerateProjectSnapshot(miniLcmApi, fwdataApi.Project); + } + else + { + logger.LogInformation("Skipping regenerating project snapshot, because there were no crdt changes"): + } + activity?.SetStatus(ActivityStatusCode.Ok, "Sync finished"); return new SyncJobResult(result); } diff --git a/backend/FwLite/FwLiteProjectSync.Tests/CrdtRepairTests.cs b/backend/FwLite/FwLiteProjectSync.Tests/CrdtRepairTests.cs index acb72a9934..c0d0b74221 100644 --- a/backend/FwLite/FwLiteProjectSync.Tests/CrdtRepairTests.cs +++ b/backend/FwLite/FwLiteProjectSync.Tests/CrdtRepairTests.cs @@ -90,6 +90,7 @@ public async Task CrdtEntryMissingTranslationId_NoChanges_FullSync() // act await SyncService.Sync(CrdtApi, FwDataApi); + await SyncService.RegenerateProjectSnapshot(CrdtApi, FwDataApi.Project); // assert - the fwdata ID is now used everywhere var updatedFwEntry = await FwDataApi.GetEntry(crdtEntry.Id); @@ -156,6 +157,7 @@ public async Task CrdtEntryMissingTranslationId_MultipleFwTranslations_FullSync( // act await SyncService.Sync(CrdtApi, FwDataApi); + await SyncService.RegenerateProjectSnapshot(CrdtApi, FwDataApi.Project); // assert - the fwdata ID is now used everywhere var updatedFwEntry = await FwDataApi.GetEntry(crdtEntry.Id); diff --git a/backend/FwLite/FwLiteProjectSync.Tests/Sena3SyncTests.cs b/backend/FwLite/FwLiteProjectSync.Tests/Sena3SyncTests.cs index 219a6af763..191a8a691e 100644 --- a/backend/FwLite/FwLiteProjectSync.Tests/Sena3SyncTests.cs +++ b/backend/FwLite/FwLiteProjectSync.Tests/Sena3SyncTests.cs @@ -225,6 +225,7 @@ public async Task LiveSena3Sync() // act var result = await _syncService.Sync(liveCrdtApi, _fwDataApi); + await _syncService.RegenerateProjectSnapshot(liveCrdtApi, _fwDataApi.Project); // assert var fwHeadlessSnapshot = await _syncService.GetProjectSnapshot(_project.FwDataProject); diff --git a/backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs b/backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs index 01fe941680..864fc71421 100644 --- a/backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs +++ b/backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs @@ -47,14 +47,6 @@ public async Task Sync(IMiniLcmApi crdtApi, FwDataMiniLcmApi fwdataA SyncResult result = await Sync(crdtApi, fwdataApi, dryRun, fwdataApi.EntryCount, projectSnapshot); fwdataApi.Save(); - - if (!dryRun) - { - //note we are now using the crdt API, this avoids issues where some data isn't synced yet - //later when we add the ability to sync that data we need the snapshot to reflect the synced state, not what was in the FW project - //related to https://github.com/sillsdev/languageforge-lexbox/issues/1912 - await RegenerateProjectSnapshot(crdtApi, fwdataApi.Project); - } return result; } From 1437481a5d39981b87fcf508e6baf2bdda429e25 Mon Sep 17 00:00:00 2001 From: Tim Haasdyk Date: Wed, 22 Oct 2025 17:13:50 +0200 Subject: [PATCH 2/2] Only sync harmony after regenerating snapshot --- backend/FwHeadless/Services/SyncHostedService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/FwHeadless/Services/SyncHostedService.cs b/backend/FwHeadless/Services/SyncHostedService.cs index 8c2117dad4..24e5d3ba44 100644 --- a/backend/FwHeadless/Services/SyncHostedService.cs +++ b/backend/FwHeadless/Services/SyncHostedService.cs @@ -189,7 +189,6 @@ public async Task ExecuteSync(CancellationToken stoppingToken, bo result.CrdtChanges, result.FwdataChanges); - await crdtSyncService.SyncHarmonyProject(); if (result.FwdataChanges == 0) { logger.LogInformation("No Send/Receive needed after CRDT sync as no FW changes were made by the sync"); @@ -224,6 +223,8 @@ public async Task ExecuteSync(CancellationToken stoppingToken, bo logger.LogInformation("Skipping regenerating project snapshot, because there were no crdt changes"): } + await crdtSyncService.SyncHarmonyProject(); + activity?.SetStatus(ActivityStatusCode.Ok, "Sync finished"); return new SyncJobResult(result); }