fix: cache terminal local content misses - #8080
Conversation
Maven benchmarkCompared baseline
The first candidate request returned For invalidation, I added the missing Maven artifact, created a new repository version, and moved the distribution to it. The next request immediately returned
Assisted-by: GPT 5.6 Luna |
|
Thanks for the suggestion. I agree that broader 404 caching deserves discussion, including:
The current design caches only terminal local misses because they are the safest, incident-relevant case. Separate string keys provide independent TTLs and avoid changing positive-cache expiry. A simpler option is to remove generation invalidation and accept that newly available content may remain cached as 404 until the TTL expires. That reduces implementation complexity but does not meet the immediate-availability requirement. The main points for discussion are:
Assisted-by: GPT 5.6 Luna/Terra |
37e3e8e to
75c507c
Compare
Load testIsolated 200 parallel
The first request was All agents and synthetic data were removed. Assisted-by: GPT 5.6 Luna/Terra |
b4b4fb9 to
b7acc76
Compare
gerrod3
left a comment
There was a problem hiding this comment.
Pretty sure this isn't working the way you expect it to. The HTTPNotFound shouldn't even be placed in the cache because there is no elif isinstance(response, HTTPNotFound) check in make_entry. So I'm not sure how your unit test is passing -- it is making me sus of our other cached unit tests...
b7acc76 to
1c86b52
Compare
|
@decko You didn't finish adding my changes, please do so before requesting another review. |
66cceae to
9307275
Compare
My bad. Few things went missing, and the agent got stuck with oci-env. Can you take another look? |
Maven load testCompared the PR with its direct parent ( The PR agent Redis cache was cleared, then primed with
PR result: 200/200 responses were |
gerrod3
left a comment
There was a problem hiding this comment.
Figured out why the code was working before, tests were correct, just my understanding was wrong.
| else: | ||
| entry["text"] = getattr(body, "_value", body).decode("utf-8") | ||
| entry["type"] = "HTTPNotFound" | ||
| elif isinstance(response, (Response, HTTPSuccessful)): |
There was a problem hiding this comment.
After examining this code I have come to the realization that Response is the base class of all HttpException classes, therefore the elif isinstance(response, HTTPFound) is dead code. Now the code still works since we store all the information to create the redirect and HTTPFound is ultimately just a fancy constructor to make a Response.
So now my thinking is that instead of creating a new block for HTTPNotFound we just move it into the Response block. Add an inside check that the response is cacheable and fall through to the reset of the code.
There was a problem hiding this comment.
So now my thinking is that instead of creating a new block for HTTPNotFound we just move it into the Response block. Add an inside check that the response is cacheable and fall through to the reset of the code.
It's possible, but IMO, it will make the code less clear about its intentions. I would keep the HTTPNotFound where it is, move the HTTPFound block up in the tree, and leave the elif isinstance(response, (Response, HTTPSuccessful) as a fallback option before returning what is non-treatable anyway.
It's up to you.
There was a problem hiding this comment.
That's also fine, being clear is always good. Just note that The HTTPFound will also need to pop the status.
The previous test was definitely wrong. Mocked a handler and forced a raise. The current functional test is testing the real code flow now. |
9307275 to
6c91850
Compare
Closes: PULP-2367 Closes pulp#8078 Assisted-by: GPT 5.6 Luna Assisted-by: GPT 5.6 Terra Assisted-by: Claude Opus 4.6 Assisted-by: GPT 5 Mini Assisted-by: OpenAI GPT-5.6-terra
6c91850 to
bbf26d9
Compare
| first = get_from_url(url) | ||
| second = get_from_url(url) | ||
| assert first.status == second.status == 404 | ||
| assert "X-PULP-CACHE" not in first.headers | ||
| assert "X-PULP-CACHE" not in second.headers |
There was a problem hiding this comment.
Can't we use the helper method assert_cache_status(url, [(404, None), (404, None)])
| remote = file_remote_factory(manifest_path=basic_manifest_path, policy="immediate") | ||
| body = FileRepositorySyncURL(remote=remote.pulp_href) | ||
| monitor_task( | ||
| file_bindings.RepositoriesFileApi.sync(file_repo_with_auto_publish.pulp_href, body).task | ||
| ) |
There was a problem hiding this comment.
This remote and sync are not used, remove them.
Summary
Cache eligible terminal local 404s in the existing content cache to avoid repeated content-resolution work. Fixes the repeated-miss latency described in #8078.
Changes
PathNotResolvedfailures after authorization.Testing
Closes #8078