Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
Since #2682, CKAN has performed a
HEAD
request to get the ETag of each repo before retrieving the full data, to avoid re-downloading the same large metadata archive over and over. This makes the Refresh button finish very quickly if there haven't been any metadata changes since the last time you refreshed (it's basically the same as a browser cache). This was implemented withWebRequest
, which is now obsolete according to this compiler warning:https://learn.microsoft.com/en-us/dotnet/fundamentals/syslib-diagnostics/syslib0014
Problem
After the release of CKAN v1.34.0, a few users reported that repo updates were sometimes hanging with the almost provocatively unhelpful message, "One or more errors occurred" (it turned out to be just one error 😵💫):
Reported by @dandoesgithub and confirmed by @Falki-git, both of whom were very patient and generous with their time in helping to track down the cause. Thank you both!
Cause
In #3932, I allowed myself to be seduced by the siren song of warning SYSLIB0014:
Seeing this as low-hanging fruit in my ongoing effort to modernize our code, I translated our
WebRequest
code for fetching ETags to useHttpClient
instead, tested it, and it worked. Great, right? Apparently not.That exception turned out to be an
AggregateException
with an.InnerExceptions
property containing aTaskCanceledException
with aMessage
ofA task was canceled
, which was extremely confusing because nothing was actually being cancelled (and becauseAggregateException
's documentation suggested that it's probably related to PLINQ, which it wasn't in this case). It turns out thatHttpClient
throws this when it times out a request, even thoughTimeoutException
exists and would be a vastly superior way to indicate a timeout! 🤦 A little more tracing determined thatHttpClient
was indeed throwing this in our ETag fetching code. Given a test build that usedWebRequest
instead, the same users reported no timeouts.To recap, switching to
HttpClient
gave us two problems that we never had in the previous 4 years ofNet.CurrentETag
's existence:WebRequest
still works fine for these usersNeedless to say, this has not given us a great first impression of
HttpClient
. Upon looking deeper, it seems likeHttpClient
is not well designed or maintained. If you want to laugh until you cry and then cry until you laugh again, go watch its maintainers spend thirty screens and 29 months trying to figure out how to throw the right exception instead of the wrong exception in dotnet/runtime#21965. If something that simple takes them that much arguing and delaying (with a disappointing ultimate conclusion that still doesn't really address how confusing this is, as far as I can tell), then I'm not optimistic about the present or future ofHttpClient
. Any improvements that they do make will only be for current .NET versions, so as long as we still need to support .NET Framework (which will be until we figure out how to run WinForms on .NET7+ on Linux), we'd be stuck with the old, unimprovedHttpClient
.Changes
HttpClient
is rolled back to the previous state, usingWebRequest
andWebClient
, with#pragma warning disable SYSLIB0014
added to prevent that warning from appearing.If Microsoft ever forcibly sunsets their pre-
HttpClient
HTTP modules, we can consider migrating to a third party library.static
care of VSCode suggestionsNU1701
build warning is now suppressed because it doesn't seem to be reporting an actual problemFixes #3950.
Considered and not done
At this point, we do not know why
HttpClient
is timing out. Might it be possible for us to make it work properly through some currently unknown magic dance of setting properties differently, passing different parameters, etc.? Maybe. But debugging Microsoft's code is not a good use of (more) time that we could spend on fixes and enhancements when there is a perfectly viable fallback option that has already proven itself long-term stable in the wild.