refactor: split the lock routes into their own handler - #34
Merged
Merged
Conversation
GitLfsCacheHandler took 14 constructor parameters against SonarQube's allowed 7. The handler was built around a preamble the object routes genuinely share -- resolve the upstream, validate the token, decide whether bytes come from the store or upstream -- but it had since taken on lock listing, snapshot invalidation and lock fan-out, which share none of it. The shared preamble (route parsing, upstream resolution, the allow-list check) stays in GitLfsCacheHandler, which now only dispatches. Past that point the routes divide into two groups with their own handlers: - LockRouteHandler holds LockListService, ILockSnapshotStore and LockFanOut, and nothing about tokens or the object store. - ObjectRouteHandler keeps batch, transfer and verify together, which is the grouping the original design argued for. - UpstreamRelay carries the verbatim relay and response copy that both groups fall back to, rather than duplicating it. No behaviour change: every route reaches the same code by the same conditions, and the existing 321 tests pass untouched. The dependencies were not bundled into an options object, which would have satisfied the analyzer while leaving one class doing two jobs. GitLfsCacheHandler is now internal, matching AssemblyInfo's statement that the endpoint handlers are internal. It is referenced only from MapGitLfsCache inside this assembly, so nothing in the supported surface (AddGitLfsCache, MapGitLfsCache) changes. Adds HandlerCompositionTests, which fails against the previous shape: it holds the dispatcher to the 7-parameter budget and asserts the lock dependencies reach it through LockRouteHandler rather than directly. Fixes #4 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BQfgoVAD3B5hEqPbSUHVUB
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.



Fixes #4
What changed
GitLfsCacheHandlertook 14 constructor parameters against SonarQube's allowed 7. It was built around a preamble the object routes genuinely share — resolve the upstream, validate the token, decide whether bytes come from the store or upstream — but had since taken on lock listing, snapshot invalidation and lock fan-out, which share none of it.The shared preamble (route parsing, upstream resolution, the allow-list check) stays in
GitLfsCacheHandler, which now only dispatches. Past that point the routes divide into two groups, each with its own handler:GitLfsCacheHandlerLockRouteHandler(new)LockListService,ILockSnapshotStore,LockFanOutObjectRouteHandler(new)UpstreamRelay(new)No behaviour change: every route reaches the same code under the same conditions. The dependencies were not bundled into an options object — the issue calls that out as the wrong fix, and it would have left one class doing two jobs.
Two things worth a reviewer's eye
ObjectRouteHandlersits at 9 parameters, not 7. Batch, transfer and verify stay together because that is the grouping the original design comment argued for, and the issue endorses it ("that argument held when it handled batch, transfers and verify"). Splitting batch out would land every class at ≤7, but it goes against that reasoning, so I left it. Say the word if you'd rather have it. The reported class is fixed either way, and the worst class drops from 14 to 9.GitLfsCacheHandleris nowinternal. It has to be, since its constructor takes the new internal collaborators — and it matchesAssemblyInfo's own statement that "the endpoint handlers, store internals, and token codec details are internal". It is referenced only fromMapGitLfsCacheinside this assembly, so the supported surface (AddGitLfsCache,MapGitLfsCache) is unchanged. If you'd rather not touch visibility at all, the alternative is making the three new types public instead.Tagged
[patch]on the basis that the supported surface is unchanged; happy to re-tag if you read the visibility change differently.Testing
dotnet test GitLfsCache.slnx).LockListCachingTestsandLockFanOutTests— including snapshot invalidation on create, the disabled-subsystem paths, pagination and fan-out partial failure — so they verify both handlers post-split.HandlerCompositionTests(5 tests) guards the boundary. Verified it fails against the previous shape by temporarily putting the lock dependencies back on the dispatcher:Both pass after the split. The tests assert the dependency boundary rather than behaviour, since the behaviour either side is already covered — the point is to notice the next time an unrelated dependency lands on the dispatcher, which is exactly how it reached 14.
🤖 Generated with Claude Code
https://claude.ai/code/session_01BQfgoVAD3B5hEqPbSUHVUB
Generated by Claude Code