diff --git a/src/SIL.XForge.Scripture/Services/MachineApiService.cs b/src/SIL.XForge.Scripture/Services/MachineApiService.cs index 75b14e7955..88b28b7c0b 100644 --- a/src/SIL.XForge.Scripture/Services/MachineApiService.cs +++ b/src/SIL.XForge.Scripture/Services/MachineApiService.cs @@ -1063,24 +1063,37 @@ CancellationToken cancellationToken try { - // Get the last completed build - TranslationBuild? translationBuild = ( - await translationEnginesClient.GetAllBuildsAsync(translationEngineId, cancellationToken) - ) + // Get the last build and the last completed build + IList translationBuilds = await translationEnginesClient.GetAllBuildsAsync( + translationEngineId, + cancellationToken + ); + TranslationBuild? lastTranslationBuild = translationBuilds.LastOrDefault(); + TranslationBuild? lastCompletedTranslationBuild = translationBuilds .Where(b => b.State == JobState.Completed) .MaxBy(b => b.DateFinished); - if (translationBuild is not null) + + // See if the very last build has completed + if (lastTranslationBuild?.State == JobState.Completed) { // See if the current scripture range has changed - string currentScriptureRange = GetDraftedScriptureRange(translationBuild); - if (project.TranslateConfig.DraftConfig.CurrentScriptureRange != currentScriptureRange) + string currentScriptureRange = GetDraftedScriptureRange(lastTranslationBuild); + if ( + !string.IsNullOrWhiteSpace(currentScriptureRange) + && project.TranslateConfig.DraftConfig.CurrentScriptureRange != currentScriptureRange + ) { backgroundJobClient.Enqueue(r => r.RetrievePreTranslationStatusAsync(sfProjectId, CancellationToken.None) ); } - buildDto = CreateDto(translationBuild); + buildDto = CreateDto(lastTranslationBuild); + } + else if (lastCompletedTranslationBuild is not null) + { + // The very last build is active, so return the last completed build + buildDto = CreateDto(lastCompletedTranslationBuild); } } catch (ServalApiException e) diff --git a/test/SIL.XForge.Scripture.Tests/Services/MachineApiServiceTests.cs b/test/SIL.XForge.Scripture.Tests/Services/MachineApiServiceTests.cs index 286f57a65d..6fb9e430d2 100644 --- a/test/SIL.XForge.Scripture.Tests/Services/MachineApiServiceTests.cs +++ b/test/SIL.XForge.Scripture.Tests/Services/MachineApiServiceTests.cs @@ -1938,7 +1938,7 @@ public async Task GetLastCompletedPreTranslationBuildAsync_RetrievePreTranslatio } [Test] - public async Task GetLastCompletedPreTranslationBuildAsync_NoRetrievePreTranslationStatusAsyncCall_Success() + public async Task GetLastCompletedPreTranslationBuildAsync_NoRetrievePreTranslationStatusAsyncCallWhenActiveBuild_Success() { // Set up test environment var env = new TestEnvironment(); @@ -1974,6 +1974,73 @@ public async Task GetLastCompletedPreTranslationBuildAsync_NoRetrievePreTranslat }, ], }, + new TranslationBuild + { + Url = "https://example.com", + Id = Build02, + Engine = new ResourceLink { Id = "engineId", Url = "https://example.com" }, + State = JobState.Active, + }, + ] + ) + ); + + // SUT + ServalBuildDto? actual = await env.Service.GetLastCompletedPreTranslationBuildAsync( + User01, + Project01, + false, + CancellationToken.None + ); + + // RetrievePreTranslationStatusAsync is run via a background job, so we verify that no new job was scheduled + env.BackgroundJobClient.DidNotReceive().Create(Arg.Any(), Arg.Any()); + + TestEnvironment.AssertCoreBuildProperties(CompletedTranslationBuild, actual); + } + + [Test] + public async Task GetLastCompletedPreTranslationBuildAsync_NoRetrievePreTranslationStatusAsyncCallWhenAlreadyRun_Success() + { + // Set up test environment + var env = new TestEnvironment(); + const string scriptureRange = "GEN"; + await env.Projects.UpdateAsync( + Project01, + u => u.Set(p => p.TranslateConfig.DraftConfig.CurrentScriptureRange, scriptureRange) + ); + const double percentCompleted = 0; + const int revision = 43; + const JobState state = JobState.Completed; + env.TranslationEnginesClient.GetAllBuildsAsync(TranslationEngine01, CancellationToken.None) + .Returns( + Task.FromResult>( + [ + new TranslationBuild + { + Url = "https://example.com", + Id = Build01, + Engine = new ResourceLink { Id = "engineId", Url = "https://example.com" }, + Message = MachineApiService.BuildStateCompleted, + Progress = percentCompleted, + Revision = revision, + State = state, + DateFinished = DateTimeOffset.UtcNow, + Pretranslate = + [ + new PretranslateCorpus + { + SourceFilters = + [ + new ParallelCorpusFilter + { + Corpus = new ResourceLink { Id = "corpusId", Url = "https://example.com" }, + ScriptureRange = scriptureRange, + }, + ], + }, + ], + }, ] ) ); @@ -1986,7 +2053,8 @@ public async Task GetLastCompletedPreTranslationBuildAsync_NoRetrievePreTranslat CancellationToken.None ); - await env.Service.DidNotReceive().RetrievePreTranslationStatusAsync(Project01, CancellationToken.None); + // RetrievePreTranslationStatusAsync is run via a background job, so we verify that no new job was scheduled + env.BackgroundJobClient.DidNotReceive().Create(Arg.Any(), Arg.Any()); TestEnvironment.AssertCoreBuildProperties(CompletedTranslationBuild, actual); } @@ -2040,7 +2108,8 @@ public async Task GetLastCompletedPreTranslationBuildAsync_NullScriptureRange_Su CancellationToken.None ); - await env.Service.DidNotReceive().RetrievePreTranslationStatusAsync(Project01, CancellationToken.None); + // RetrievePreTranslationStatusAsync is run via a background job, so we verify that no new job was scheduled + env.BackgroundJobClient.DidNotReceive().Create(Arg.Any(), Arg.Any()); TestEnvironment.AssertCoreBuildProperties(CompletedTranslationBuild, actual); }