From fbc6f267f01e6492cb647b385690cc117cf049aa Mon Sep 17 00:00:00 2001 From: "jack.lewis" Date: Mon, 13 Jan 2025 15:30:55 +0000 Subject: [PATCH] Use the batch named query to retrieve asset details --- .../BatchCompletionMessageHandlerTests.cs | 8 +- .../BatchCompletionMessageHandler.cs | 4 +- .../API/DlcsOrchestratorClientTests.cs | 77 +++++++++++++++++++ .../DLCS/API/DlcsOrchestratorClient.cs | 19 +++-- src/IIIFPresentation/DLCS/DlcsSettings.cs | 2 +- 5 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 src/IIIFPresentation/DLCS.Tests/API/DlcsOrchestratorClientTests.cs diff --git a/src/IIIFPresentation/BackgroundHandler.Tests/BatchCompletion/BatchCompletionMessageHandlerTests.cs b/src/IIIFPresentation/BackgroundHandler.Tests/BatchCompletion/BatchCompletionMessageHandlerTests.cs index 69eabef..a745ebc 100644 --- a/src/IIIFPresentation/BackgroundHandler.Tests/BatchCompletion/BatchCompletionMessageHandlerTests.cs +++ b/src/IIIFPresentation/BackgroundHandler.Tests/BatchCompletion/BatchCompletionMessageHandlerTests.cs @@ -64,7 +64,7 @@ public async Task HandleMessage_DoesNotUpdateAnything_WhenBatchNotTracked() // Act and Assert (await sut.HandleMessage(message, CancellationToken.None)).Should().BeTrue(); - A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A._, A._)) + A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A>._, A._)) .MustNotHaveHappened(); } @@ -106,7 +106,7 @@ public async Task HandleMessage_UpdatesBatchedImages_WhenBatchTracked() var message = GetMessage(batchMessage); - A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A._, A._)) + A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A>._, A._)) .Returns(new IIIF.Presentation.V3.Manifest { Items = new List @@ -149,7 +149,7 @@ public async Task HandleMessage_UpdatesBatchedImages_WhenBatchTracked() // Assert handleMessage.Should().BeTrue(); - A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A._, A._)) + A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A>._, A._)) .MustHaveHappened(); var batch = dbContext.Batches.Single(b => b.Id == batchId); batch.Status.Should().Be(BatchStatus.Completed); @@ -201,7 +201,7 @@ public async Task HandleMessage_DoesNotUpdateBatchedImages_WhenAnotherBatchWaiti // Act and Assert (await sut.HandleMessage(message, CancellationToken.None)).Should().BeTrue(); - A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A._, A._)) + A.CallTo(() => dlcsClient.RetrieveImagesForManifest(A._, A>._, A._)) .MustNotHaveHappened(); } diff --git a/src/IIIFPresentation/BackgroundHandler/BatchCompletion/BatchCompletionMessageHandler.cs b/src/IIIFPresentation/BackgroundHandler/BatchCompletion/BatchCompletionMessageHandler.cs index 03cdafb..804c237 100644 --- a/src/IIIFPresentation/BackgroundHandler/BatchCompletion/BatchCompletionMessageHandler.cs +++ b/src/IIIFPresentation/BackgroundHandler/BatchCompletion/BatchCompletionMessageHandler.cs @@ -68,8 +68,10 @@ private async Task UpdateAssetsIfRequired(BatchCompletionMessage batchCompletion "Attempting to complete assets in batch {BatchId} for customer {CustomerId} with the manifest {ManifestId}", batch.Id, batch.CustomerId, batch.ManifestId); + var batches = dbContext.Batches.Where(b => b.ManifestId == batch.ManifestId).Select(b => b.Id).ToList(); + var generatedManifest = - await dlcsOrchestratorClient.RetrieveImagesForManifest(batch.CustomerId, batch.ManifestId!, + await dlcsOrchestratorClient.RetrieveImagesForManifest(batch.CustomerId, batches, cancellationToken); UpdateCanvasPaintings(generatedManifest, batch); diff --git a/src/IIIFPresentation/DLCS.Tests/API/DlcsOrchestratorClientTests.cs b/src/IIIFPresentation/DLCS.Tests/API/DlcsOrchestratorClientTests.cs new file mode 100644 index 0000000..27765f4 --- /dev/null +++ b/src/IIIFPresentation/DLCS.Tests/API/DlcsOrchestratorClientTests.cs @@ -0,0 +1,77 @@ +using System.Net; +using DLCS.API; +using DLCS.Exceptions; +using IIIF.Presentation.V3; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Stubbery; + +namespace DLCS.Tests.API; + +public class DlcsOrchestratorClientTests +{ + [Theory] + [InlineData(HttpStatusCode.Forbidden)] + [InlineData(HttpStatusCode.Conflict)] + [InlineData(HttpStatusCode.BadRequest)] + public async Task RetrieveImagesForManifest_Throws_IfDownstreamNon200_NoReturnedError(HttpStatusCode httpStatusCode) + { + using var stub = new ApiStub(); + const int customerId = 3; + stub.Get($"/iiif-resource/{customerId}/batch-query/1,2", (_, _) => string.Empty).StatusCode((int)httpStatusCode); + var sut = GetClient(stub); + + Func action = () => sut.RetrieveImagesForManifest(customerId, [1, 2], CancellationToken.None); + await action.Should().ThrowAsync().WithMessage("Could not find a DlcsError in response"); + } + + [Theory] + [InlineData(HttpStatusCode.Forbidden)] + [InlineData(HttpStatusCode.Conflict)] + [InlineData(HttpStatusCode.BadRequest)] + public async Task RetrieveImagesForManifest_Throws_IfDownstreamNon200_WithReturnedError(HttpStatusCode httpStatusCode) + { + using var stub = new ApiStub(); + const int customerId = 4; + stub.Get($"/iiif-resource/{customerId}/batch-query/1,2", (_, _) => "{\"description\":\"I am broken\"}") + .StatusCode((int)httpStatusCode); + var sut = GetClient(stub); + + Func action = () => sut.RetrieveImagesForManifest(customerId, [1, 2], CancellationToken.None); + await action.Should().ThrowAsync().WithMessage("I am broken"); + } + + [Fact] + public async Task RetrieveImagesForManifest_ReturnsManifest() + { + using var stub = new ApiStub(); + const int customerId = 5; + stub.Get($"/iiif-resource/{customerId}/batch-query/1", + (_, _) => "{\"id\":\"some/id\", \"type\": \"Manifest\" }") + .StatusCode(200); + var sut = GetClient(stub); + var expected = new Manifest() { Id = "some/id" }; + + var retrievedImages = await sut.RetrieveImagesForManifest(customerId, [1], CancellationToken.None); + + retrievedImages.Should().BeEquivalentTo(expected); + } + + private static DlcsOrchestratorClient GetClient(ApiStub stub) + { + stub.EnsureStarted(); + + var httpClient = new HttpClient + { + BaseAddress = new Uri(stub.Address) + }; + + var options = Options.Create(new DlcsSettings() + { + ApiUri = new Uri("https://localhost"), + MaxBatchSize = 1 + }); + + return new DlcsOrchestratorClient(httpClient, options, new NullLogger()); + } +} diff --git a/src/IIIFPresentation/DLCS/API/DlcsOrchestratorClient.cs b/src/IIIFPresentation/DLCS/API/DlcsOrchestratorClient.cs index f2760fe..72341aa 100644 --- a/src/IIIFPresentation/DLCS/API/DlcsOrchestratorClient.cs +++ b/src/IIIFPresentation/DLCS/API/DlcsOrchestratorClient.cs @@ -9,7 +9,7 @@ public interface IDlcsOrchestratorClient /// /// Retrieves a DLCS generated manifest of images for a given presentation manifest id /// - public Task RetrieveImagesForManifest(int customerId, string manifestId, + public Task RetrieveImagesForManifest(int customerId, List batches, CancellationToken cancellationToken = default); } @@ -18,18 +18,21 @@ public class DlcsOrchestratorClient( IOptions dlcsOptions, ILogger logger) : IDlcsOrchestratorClient { - DlcsSettings settings = dlcsOptions.Value; + private readonly DlcsSettings settings = dlcsOptions.Value; - public async Task RetrieveImagesForManifest(int customerId, string manifestId, + public async Task RetrieveImagesForManifest(int customerId, List batches, CancellationToken cancellationToken = default) { + var batchString = string.Join(',', batches); + logger.LogTrace( - "performing a call to retrieve images for customer {CustomerId} using the manifest {ManifestId}", - customerId, manifestId); - + "performing a call to retrieve images for customer {CustomerId} for the batches '{Batches}'", + customerId, batchString); + var response = - await httpClient.GetAsync($"/iiif-resource/{customerId}/{settings.ManifestNamedQueryName}/{manifestId}", + await httpClient.GetAsync($"/iiif-resource/{customerId}/{settings.ManifestNamedQueryName}/{batchString}", cancellationToken); - return await response.ReadAsIIIFResponse(cancellationToken); + + return await response.ReadAsIIIFResponse(cancellationToken); } } diff --git a/src/IIIFPresentation/DLCS/DlcsSettings.cs b/src/IIIFPresentation/DLCS/DlcsSettings.cs index 27ae55e..d9fceba 100644 --- a/src/IIIFPresentation/DLCS/DlcsSettings.cs +++ b/src/IIIFPresentation/DLCS/DlcsSettings.cs @@ -27,5 +27,5 @@ public class DlcsSettings /// /// The name of the query used for retrieving images /// - public string ManifestNamedQueryName { get; set; } = "interim-presentation"; + public string ManifestNamedQueryName { get; set; } = "batch-query"; }