Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix retry loop on exception #257

Conversation

ronaldbarendse
Copy link
Contributor

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following matches the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

PR #240 added a retry in case reading the cached file caused an exception (e.g. when the file got deleted while still in the internal LRU cache). I tested whether that PR fixed the issue, but didn't spot the retry loop: if reading the cached file keeps throwing exceptions, it will go into an infinite loop.

You can test this by getting an exclusive lock on a cached file and requesting that respective URL. You can do this with PowerShell by executing $fileStream = [System.IO.File]::Open("1f85.jpg", "Open", "Write") (where 1f85.jpg is the cached file name). The request will only finish after executing $fileStream.Dispose(); to release the exclusive lock...

I've also removed allocating a new list to strip unknown commands (AFAIK Dictionary.Keys uses an existing collection to return the keys) and ensured the middleware first tries to get a valid provider before parsing commands/capturing the HMAC token, removing additional allocations (for invalid requests).

}
}
}
public IEnumerable<string> Keys => this.Dictionary.Keys; // TODO Change return type to ICollection<string> in next major release
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong and unrelated. Please revert.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also noticed the failing test and reverted this change, but using Dictionary.Keys does prevent allocating a new list.

I've updated my branch to fix this, expose it as an internal AllKeys property and added benchmarks:

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
Intel Core i7-10750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK=6.0.202
    [Host]     : .NET 5.0.16 (5.0.1622.16705), X64 RyuJIT
    DefaultJob : .NET 5.0.16 (5.0.1622.16705), X64 RyuJIT


|   Method |      Mean |    Error |   StdDev | Ratio | RatioSD |  Gen 0 | Allocated |
|--------- |----------:|---------:|---------:|------:|--------:|-------:|----------:|
|     Keys |  87.77 ns | 1.560 ns | 2.136 ns |  1.00 |    0.00 | 0.0153 |      96 B |
| KeysList | 152.28 ns | 1.699 ns | 1.589 ns |  1.73 |    0.04 | 0.0355 |     224 B |
|  AllKeys |  37.82 ns | 0.637 ns | 0.806 ns |  0.43 |    0.02 | 0.0063 |      40 B |

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have an improvement it is welcome but it must be part of a separate PR.

@JimBobSquarePants
Copy link
Member

@ronaldbarendse i appreciate any assistance here but you have to stop bundling random unrelated changes into PRs.

If you’ve found an issue please raise one in the tracker and I’ll deal with it.

{
// The image has failed to be returned from the cache.
// This can happen if the cached image has been physically deleted but the item is still in the LRU cache.
// We'll retry running the request again in it's entirety. This ensures any changes to the source are tracked also.
CacheResolverLru.TryRemove(key);
await this.Invoke(httpContext);
await this.Invoke(httpContext, false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to revisit/rereview this and it's proving impossible with the additional unrelated changes.

The logic here doesn't seem to make sense. You've reversed the condition but are calling the same method (since Invoke calls Invoke(false)).

As I see it the fix should be to pass true as the second parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also changed the initial value of retry to true (see above), as I was assuming this boolean indicates whether it should retry the request.

But I now understand this indicates whether it is the retried request (and shouldn't retry again), so the change in #264 is indeed enough to fix it 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants