Improve proxy cache behavior and diagnostics
This commit is contained in:
@@ -68,6 +68,30 @@ public sealed class ItemsProxyRequestBuilderTests
|
||||
Assert.Contains("|SortName|Descending|L|20|10|fi-FI|", result.CacheKey);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUsesOneUpstreamKeyForDifferentLocalPagingControls()
|
||||
{
|
||||
var request = HttpRequest();
|
||||
|
||||
var first = ItemsProxyRequestBuilder.Build(
|
||||
request,
|
||||
"/Items?SortBy=SortName&StartIndex=0&Limit=100",
|
||||
"token",
|
||||
UserId,
|
||||
multilangEnabled: true);
|
||||
var second = ItemsProxyRequestBuilder.Build(
|
||||
request,
|
||||
"/Items?SortBy=SortName&StartIndex=100&Limit=100",
|
||||
"token",
|
||||
UserId,
|
||||
multilangEnabled: true);
|
||||
|
||||
Assert.NotNull(first);
|
||||
Assert.NotNull(second);
|
||||
Assert.Equal(first.NormalizedUrlForCache, second.NormalizedUrlForCache);
|
||||
Assert.NotEqual(first.CacheKey, second.CacheKey);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildLeavesSortAndPagingUpstreamWhenMultilangDisabled()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using Jellyfin.Plugin.Multilang.Services;
|
||||
|
||||
namespace Jellyfin.Plugin.Multilang.Tests;
|
||||
|
||||
public sealed class ItemsProxyRequestCoalescerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task MatchingRequestsShareOneInFlightFetch()
|
||||
{
|
||||
var coalescer = new ItemsProxyRequestCoalescer();
|
||||
var response = new TaskCompletionSource<ItemsProxyUpstreamResponse>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var fetches = 0;
|
||||
|
||||
Task<ItemsProxyUpstreamResponse> Fetch(CancellationToken _)
|
||||
{
|
||||
fetches++;
|
||||
return response.Task;
|
||||
}
|
||||
|
||||
var first = coalescer.GetOrFetchAsync("user|/Items", Fetch, CancellationToken.None);
|
||||
var second = coalescer.GetOrFetchAsync("user|/Items", Fetch, CancellationToken.None);
|
||||
|
||||
Assert.Equal(1, fetches);
|
||||
response.SetResult(new ItemsProxyUpstreamResponse(200, "{}", "application/json"));
|
||||
|
||||
var firstResult = await first;
|
||||
var secondResult = await second;
|
||||
Assert.False(firstResult.JoinedExistingRequest);
|
||||
Assert.True(secondResult.JoinedExistingRequest);
|
||||
Assert.Equal("{}", firstResult.Response.Body);
|
||||
Assert.Equal(firstResult.Response, secondResult.Response);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CancellingOneWaiterDoesNotCancelTheSharedFetch()
|
||||
{
|
||||
var coalescer = new ItemsProxyRequestCoalescer();
|
||||
var response = new TaskCompletionSource<ItemsProxyUpstreamResponse>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
using var cancellation = new CancellationTokenSource();
|
||||
|
||||
var cancelledWaiter = coalescer.GetOrFetchAsync("user|/Items", _ => response.Task, cancellation.Token);
|
||||
var activeWaiter = coalescer.GetOrFetchAsync("user|/Items", _ => response.Task, CancellationToken.None);
|
||||
cancellation.Cancel();
|
||||
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(() => cancelledWaiter);
|
||||
response.SetResult(new ItemsProxyUpstreamResponse(200, "{}", "application/json"));
|
||||
|
||||
var result = await activeWaiter;
|
||||
Assert.True(result.JoinedExistingRequest);
|
||||
Assert.Equal(200, result.Response.StatusCode);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user