Container Registry: Separate legacy filesystem and database code paths in HTTP handlers
### Summary The Container Registry HTTP handlers use if/else branches throughout their methods to switch between two metadata backends: the database and the legacy filesystem. This effort will separate these code paths to improve maintainability and reduce regression risk. ### Problem The current branching pattern creates several challenges: * **Cognitive overhead**: Developers must track which code executes under which conditions while reading handler logic * **Intermingled code**: Database code sits alongside filesystem code, often in multiple sections within the same method * **Maintenance risk**: Changes to database functionality can inadvertently affect legacy behavior * **Unnecessary complexity**: Backend selection happens at startup and never changes, yet branching logic is repeated throughout request handling ### Proposed Solution Refactor HTTP handlers to separate the two code paths: 1. **Extract legacy code**: Move filesystem logic into `Legacy*` methods (e.g., `LegacyStartBlobUpload`, `LegacyHandleGetTags`) 2. **Isolate in dedicated files**: Put legacy methods in `legacy_*.go` files (e.g., `legacy_blobupload.go`, `legacy_tags.go`) 3. **Simplify main handlers**: Main handler methods contain only database logic 4. **Dispatcher-level selection**: The dispatcher chooses the appropriate handler method once per request ### Scope | Package | Conditional Checks | Handlers Affected | |---------|--------------------|-------------------| | `registry/handlers/` | \~27 | manifests, blobs, tags, catalog, blob uploads, repositories | | `notifications/` | 3 | flag propagation | | `registry/storage/` | 3 | filesystem linking | **Out of scope**: Legacy conditional logic in `app.go` and `registry/storage` is harder to isolate and occurs less often. ### Rollout Strategy Follow the incremental approach from the Database Load Balancing (DLB) rollout: 1. Refactor handlers from most to least traffic on GitLab.com 2. Merge one handler refactor per release cycle 3. Validate change on .com and self-managed ### Benefits * Each code path is self-contained and easier to follow * Changes to one backend can't accidentally affect the other * `legacy_*.go` naming makes deprecated code obvious * No new tests required—conformance tests already cover both paths ### Trade-offs * Code duplication until legacy filesystem support is retired (potentially years) * One-refactor-per-release cadence means this spans multiple milestones * Legacy logic in `app.go` and `registry/storage` stays out of scope ### Success Criteria * All handler methods in `registry/handlers/*.go` contain only database logic * All legacy filesystem logic lives in `legacy_*.go` files * Backend selection occurs at the dispatcher level, not within handler methods * API conformance tests pass for both database and legacy configurations ### Related * Parent initiative: &9857 (Refactoring Opportunities) * Proof of concept: [!2766](https://gitlab.com/gitlab-org/container-registry/-/merge_requests/2766) (demonstrates pattern with tags and blob upload handlers) * Prior art: [!699](https://gitlab.com/gitlab-org/container-registry/-/merge_requests/699) (earlier manifest handler refactor attempt)
epic