Bust stale critical source image caches
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -49,10 +49,18 @@ api.MapGet("/tables/critical/{slug}/cells/{resultId:int}", async (string slug, i
|
|||||||
var result = await lookupService.GetCriticalCellEditorAsync(slug, resultId, cancellationToken);
|
var result = await lookupService.GetCriticalCellEditorAsync(slug, resultId, cancellationToken);
|
||||||
return result is null ? Results.NotFound() : Results.Ok(result);
|
return result is null ? Results.NotFound() : Results.Ok(result);
|
||||||
});
|
});
|
||||||
api.MapGet("/tables/critical/{slug}/cells/{resultId:int}/source-image", async (string slug, int resultId, LookupService lookupService, CancellationToken cancellationToken) =>
|
api.MapGet("/tables/critical/{slug}/cells/{resultId:int}/source-image", async (string slug, int resultId, LookupService lookupService, HttpContext httpContext, CancellationToken cancellationToken) =>
|
||||||
{
|
{
|
||||||
var filePath = await lookupService.GetCriticalSourceImagePathAsync(slug, resultId, cancellationToken);
|
var filePath = await lookupService.GetCriticalSourceImagePathAsync(slug, resultId, cancellationToken);
|
||||||
return filePath is null ? Results.NotFound() : Results.File(filePath, "image/png");
|
if (filePath is null)
|
||||||
|
{
|
||||||
|
return Results.NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
httpContext.Response.Headers.CacheControl = "no-store, no-cache, max-age=0";
|
||||||
|
httpContext.Response.Headers.Pragma = "no-cache";
|
||||||
|
httpContext.Response.Headers.Expires = "0";
|
||||||
|
return Results.File(filePath, "image/png");
|
||||||
});
|
});
|
||||||
api.MapPost("/tables/critical/{slug}/cells/{resultId:int}/reparse", async (string slug, int resultId, CriticalCellReparseRequest request, LookupService lookupService, CancellationToken cancellationToken) =>
|
api.MapPost("/tables/critical/{slug}/cells/{resultId:int}/reparse", async (string slug, int resultId, CriticalCellReparseRequest request, LookupService lookupService, CancellationToken cancellationToken) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
using RolemasterDb.App.Data;
|
using RolemasterDb.App.Data;
|
||||||
using RolemasterDb.App.Domain;
|
using RolemasterDb.App.Domain;
|
||||||
using RolemasterDb.App.Features;
|
using RolemasterDb.App.Features;
|
||||||
@@ -25,22 +24,9 @@ public sealed class LookupServiceCurationIntegrationTests
|
|||||||
Assert.NotNull(initialResponse);
|
Assert.NotNull(initialResponse);
|
||||||
Assert.False(initialResponse!.IsCurated);
|
Assert.False(initialResponse!.IsCurated);
|
||||||
Assert.Equal(2, initialResponse.SourcePageNumber);
|
Assert.Equal(2, initialResponse.SourcePageNumber);
|
||||||
Assert.Equal($"/api/tables/critical/slash/cells/{resultId}/source-image", initialResponse.SourceImageUrl);
|
Assert.StartsWith($"/api/tables/critical/slash/cells/{resultId}/source-image?v=", initialResponse.SourceImageUrl, StringComparison.Ordinal);
|
||||||
|
|
||||||
var updateRequest = new CriticalCellUpdateRequest(
|
var updateRequest = new CriticalCellUpdateRequest(initialResponse.RawCellText, initialResponse.QuickParseInput, initialResponse.DescriptionText, initialResponse.RawAffixText, initialResponse.ParseStatus, initialResponse.ParsedJson, true, initialResponse.IsDescriptionOverridden, initialResponse.IsRawAffixTextOverridden, initialResponse.AreEffectsOverridden, initialResponse.AreBranchesOverridden, initialResponse.Effects, initialResponse.Branches);
|
||||||
initialResponse.RawCellText,
|
|
||||||
initialResponse.QuickParseInput,
|
|
||||||
initialResponse.DescriptionText,
|
|
||||||
initialResponse.RawAffixText,
|
|
||||||
initialResponse.ParseStatus,
|
|
||||||
initialResponse.ParsedJson,
|
|
||||||
true,
|
|
||||||
initialResponse.IsDescriptionOverridden,
|
|
||||||
initialResponse.IsRawAffixTextOverridden,
|
|
||||||
initialResponse.AreEffectsOverridden,
|
|
||||||
initialResponse.AreBranchesOverridden,
|
|
||||||
initialResponse.Effects,
|
|
||||||
initialResponse.Branches);
|
|
||||||
|
|
||||||
var updatedResponse = await lookupService.UpdateCriticalCellAsync("slash", resultId, updateRequest);
|
var updatedResponse = await lookupService.UpdateCriticalCellAsync("slash", resultId, updateRequest);
|
||||||
Assert.NotNull(updatedResponse);
|
Assert.NotNull(updatedResponse);
|
||||||
@@ -56,6 +42,32 @@ public sealed class LookupServiceCurationIntegrationTests
|
|||||||
Assert.Equal(initialResponse.SourceImageUrl, reopenedResponse.SourceImageUrl);
|
Assert.Equal(initialResponse.SourceImageUrl, reopenedResponse.SourceImageUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Lookup_service_changes_source_image_url_when_source_provenance_changes()
|
||||||
|
{
|
||||||
|
var databasePath = CreateEmptyDatabasePath();
|
||||||
|
var repositoryRoot = CreateTemporaryRepositoryRoot();
|
||||||
|
var locator = new CriticalImportArtifactLocator(new TestHostEnvironment(Path.Combine(repositoryRoot, "src", "RolemasterDb.App")));
|
||||||
|
|
||||||
|
await SeedCriticalResultAsync(databasePath, "slash/cells/source-cell.png", 2);
|
||||||
|
WriteSourceImage(repositoryRoot, "slash/cells/source-cell.png");
|
||||||
|
WriteSourceImage(repositoryRoot, "slash/cells/source-cell-v2.png");
|
||||||
|
|
||||||
|
var lookupService = new LookupService(CreateDbContextFactory(databasePath), locator);
|
||||||
|
var resultId = await GetResultIdAsync(databasePath);
|
||||||
|
|
||||||
|
var initialResponse = await lookupService.GetCriticalCellEditorAsync("slash", resultId);
|
||||||
|
Assert.NotNull(initialResponse);
|
||||||
|
Assert.StartsWith($"/api/tables/critical/slash/cells/{resultId}/source-image?v=", initialResponse!.SourceImageUrl, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
await UpdateSourceMetadataAsync(databasePath, resultId, sourcePageNumber: 4, sourceImagePath: "slash/cells/source-cell-v2.png", sourceImageCropJson: "{\"pageNumber\":4,\"boundsLeft\":12}");
|
||||||
|
|
||||||
|
var reopenedResponse = await lookupService.GetCriticalCellEditorAsync("slash", resultId);
|
||||||
|
Assert.NotNull(reopenedResponse);
|
||||||
|
Assert.StartsWith($"/api/tables/critical/slash/cells/{resultId}/source-image?v=", reopenedResponse!.SourceImageUrl, StringComparison.Ordinal);
|
||||||
|
Assert.NotEqual(initialResponse.SourceImageUrl, reopenedResponse.SourceImageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Lookup_service_clears_curated_state_when_any_content_is_edited()
|
public async Task Lookup_service_clears_curated_state_when_any_content_is_edited()
|
||||||
{
|
{
|
||||||
@@ -72,29 +84,13 @@ public sealed class LookupServiceCurationIntegrationTests
|
|||||||
var initialResponse = await lookupService.GetCriticalCellEditorAsync("slash", resultId);
|
var initialResponse = await lookupService.GetCriticalCellEditorAsync("slash", resultId);
|
||||||
Assert.NotNull(initialResponse);
|
Assert.NotNull(initialResponse);
|
||||||
|
|
||||||
var markCuratedRequest = new CriticalCellUpdateRequest(
|
var markCuratedRequest = new CriticalCellUpdateRequest(initialResponse!.RawCellText, initialResponse.QuickParseInput, initialResponse.DescriptionText, initialResponse.RawAffixText, initialResponse.ParseStatus, initialResponse.ParsedJson, true, initialResponse.IsDescriptionOverridden, initialResponse.IsRawAffixTextOverridden, initialResponse.AreEffectsOverridden, initialResponse.AreBranchesOverridden, initialResponse.Effects, initialResponse.Branches);
|
||||||
initialResponse!.RawCellText,
|
|
||||||
initialResponse.QuickParseInput,
|
|
||||||
initialResponse.DescriptionText,
|
|
||||||
initialResponse.RawAffixText,
|
|
||||||
initialResponse.ParseStatus,
|
|
||||||
initialResponse.ParsedJson,
|
|
||||||
true,
|
|
||||||
initialResponse.IsDescriptionOverridden,
|
|
||||||
initialResponse.IsRawAffixTextOverridden,
|
|
||||||
initialResponse.AreEffectsOverridden,
|
|
||||||
initialResponse.AreBranchesOverridden,
|
|
||||||
initialResponse.Effects,
|
|
||||||
initialResponse.Branches);
|
|
||||||
|
|
||||||
var curatedResponse = await lookupService.UpdateCriticalCellAsync("slash", resultId, markCuratedRequest);
|
var curatedResponse = await lookupService.UpdateCriticalCellAsync("slash", resultId, markCuratedRequest);
|
||||||
Assert.NotNull(curatedResponse);
|
Assert.NotNull(curatedResponse);
|
||||||
Assert.True(curatedResponse!.IsCurated);
|
Assert.True(curatedResponse!.IsCurated);
|
||||||
|
|
||||||
var editedRequest = markCuratedRequest with
|
var editedRequest = markCuratedRequest with { DescriptionText = "Edited description after curation." };
|
||||||
{
|
|
||||||
DescriptionText = "Edited description after curation."
|
|
||||||
};
|
|
||||||
|
|
||||||
var editedResponse = await lookupService.UpdateCriticalCellAsync("slash", resultId, editedRequest);
|
var editedResponse = await lookupService.UpdateCriticalCellAsync("slash", resultId, editedRequest);
|
||||||
Assert.NotNull(editedResponse);
|
Assert.NotNull(editedResponse);
|
||||||
@@ -123,44 +119,12 @@ public sealed class LookupServiceCurationIntegrationTests
|
|||||||
Assert.NotNull(initialResponse);
|
Assert.NotNull(initialResponse);
|
||||||
Assert.False(initialResponse!.IsCurated);
|
Assert.False(initialResponse!.IsCurated);
|
||||||
|
|
||||||
var reparsedResponse = await lookupService.ReparseCriticalCellAsync(
|
var reparsedResponse = await lookupService.ReparseCriticalCellAsync("slash", resultId, new CriticalCellUpdateRequest(initialResponse.RawCellText, "Edited quick parse input.", initialResponse.DescriptionText, initialResponse.RawAffixText, initialResponse.ParseStatus, initialResponse.ParsedJson, initialResponse.IsCurated, initialResponse.IsDescriptionOverridden, initialResponse.IsRawAffixTextOverridden, initialResponse.AreEffectsOverridden, initialResponse.AreBranchesOverridden, initialResponse.Effects, initialResponse.Branches));
|
||||||
"slash",
|
|
||||||
resultId,
|
|
||||||
new CriticalCellUpdateRequest(
|
|
||||||
initialResponse.RawCellText,
|
|
||||||
"Edited quick parse input.",
|
|
||||||
initialResponse.DescriptionText,
|
|
||||||
initialResponse.RawAffixText,
|
|
||||||
initialResponse.ParseStatus,
|
|
||||||
initialResponse.ParsedJson,
|
|
||||||
initialResponse.IsCurated,
|
|
||||||
initialResponse.IsDescriptionOverridden,
|
|
||||||
initialResponse.IsRawAffixTextOverridden,
|
|
||||||
initialResponse.AreEffectsOverridden,
|
|
||||||
initialResponse.AreBranchesOverridden,
|
|
||||||
initialResponse.Effects,
|
|
||||||
initialResponse.Branches));
|
|
||||||
|
|
||||||
Assert.NotNull(reparsedResponse);
|
Assert.NotNull(reparsedResponse);
|
||||||
Assert.False(reparsedResponse!.IsCurated);
|
Assert.False(reparsedResponse!.IsCurated);
|
||||||
|
|
||||||
var curatedResponse = await lookupService.UpdateCriticalCellAsync(
|
var curatedResponse = await lookupService.UpdateCriticalCellAsync("slash", resultId, new CriticalCellUpdateRequest(reparsedResponse.RawCellText, reparsedResponse.QuickParseInput, reparsedResponse.DescriptionText, reparsedResponse.RawAffixText, reparsedResponse.ParseStatus, reparsedResponse.ParsedJson, true, reparsedResponse.IsDescriptionOverridden, reparsedResponse.IsRawAffixTextOverridden, reparsedResponse.AreEffectsOverridden, reparsedResponse.AreBranchesOverridden, reparsedResponse.Effects, reparsedResponse.Branches));
|
||||||
"slash",
|
|
||||||
resultId,
|
|
||||||
new CriticalCellUpdateRequest(
|
|
||||||
reparsedResponse.RawCellText,
|
|
||||||
reparsedResponse.QuickParseInput,
|
|
||||||
reparsedResponse.DescriptionText,
|
|
||||||
reparsedResponse.RawAffixText,
|
|
||||||
reparsedResponse.ParseStatus,
|
|
||||||
reparsedResponse.ParsedJson,
|
|
||||||
true,
|
|
||||||
reparsedResponse.IsDescriptionOverridden,
|
|
||||||
reparsedResponse.IsRawAffixTextOverridden,
|
|
||||||
reparsedResponse.AreEffectsOverridden,
|
|
||||||
reparsedResponse.AreBranchesOverridden,
|
|
||||||
reparsedResponse.Effects,
|
|
||||||
reparsedResponse.Branches));
|
|
||||||
|
|
||||||
Assert.NotNull(curatedResponse);
|
Assert.NotNull(curatedResponse);
|
||||||
Assert.True(curatedResponse!.IsCurated);
|
Assert.True(curatedResponse!.IsCurated);
|
||||||
@@ -263,26 +227,29 @@ public sealed class LookupServiceCurationIntegrationTests
|
|||||||
private static async Task<int> GetResultIdAsync(string databasePath)
|
private static async Task<int> GetResultIdAsync(string databasePath)
|
||||||
{
|
{
|
||||||
await using var dbContext = CreateDbContext(databasePath);
|
await using var dbContext = CreateDbContext(databasePath);
|
||||||
return await dbContext.CriticalResults
|
return await dbContext.CriticalResults.Where(item => item.CriticalTable.Slug == "slash").Select(item => item.Id).SingleAsync();
|
||||||
.Where(item => item.CriticalTable.Slug == "slash")
|
}
|
||||||
.Select(item => item.Id)
|
|
||||||
.SingleAsync();
|
private static async Task UpdateSourceMetadataAsync(string databasePath, int resultId, int sourcePageNumber, string sourceImagePath, string sourceImageCropJson)
|
||||||
|
{
|
||||||
|
await using var dbContext = CreateDbContext(databasePath);
|
||||||
|
var result = await dbContext.CriticalResults.SingleAsync(item => item.Id == resultId);
|
||||||
|
result.SourcePageNumber = sourcePageNumber;
|
||||||
|
result.SourceImagePath = sourceImagePath;
|
||||||
|
result.SourceImageCropJson = sourceImageCropJson;
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RolemasterDbContext CreateDbContext(string databasePath)
|
private static RolemasterDbContext CreateDbContext(string databasePath)
|
||||||
{
|
{
|
||||||
var options = new DbContextOptionsBuilder<RolemasterDbContext>()
|
var options = new DbContextOptionsBuilder<RolemasterDbContext>().UseSqlite($"Data Source={databasePath}").Options;
|
||||||
.UseSqlite($"Data Source={databasePath}")
|
|
||||||
.Options;
|
|
||||||
|
|
||||||
return new RolemasterDbContext(options);
|
return new RolemasterDbContext(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IDbContextFactory<RolemasterDbContext> CreateDbContextFactory(string databasePath)
|
private static IDbContextFactory<RolemasterDbContext> CreateDbContextFactory(string databasePath)
|
||||||
{
|
{
|
||||||
var options = new DbContextOptionsBuilder<RolemasterDbContext>()
|
var options = new DbContextOptionsBuilder<RolemasterDbContext>().UseSqlite($"Data Source={databasePath}").Options;
|
||||||
.UseSqlite($"Data Source={databasePath}")
|
|
||||||
.Options;
|
|
||||||
|
|
||||||
return new TestRolemasterDbContextFactory(options);
|
return new TestRolemasterDbContextFactory(options);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user