Skip to content

Commit b654faa

Browse files
committed
Merge TASK-053: cut dispatch over to lookup_v2 and retire v1 resolver
Retires the v1 registered_resources* HTTP dispatch path. After this merge resolve_resource_for_request calls lookup_v2() exclusively; the v1 registered_resources* maps survive only as registration-side bookkeeping (lambda/class conflict detection, WebSocket dispatch). Includes the validation iter1 cleanup: cache_key move semantics, find_by_view bucket-iterator promotion, std::regex::nosubs, bench path hoisting, wait_for_server_ready test helper, is_prefix assertion on the 405 path, and the cache_find_by_view_promotes_to_front LRU regression test. Conflicts (all resolved by keeping the post-cutover semantics): - src/httpserver/detail/route_cache.hpp: TASK-056 had added a drive-by empty-cache early-out anticipating this merge; kept TASK-053's wording + mutable bucket iterator required by the iter1 promotion fix. - src/detail/webserver_dispatch.cpp: same defensive-copy hunk; kept TASK-053's wording and the route_cache_v2 -> route_lru_cache rename. - specs/architecture/04-components/route-table.md: combined TASK-053 implementation status with TASK-056's CWE-407 note. - specs/tasks/v2-deferred-backlog-plan.md: kept the checked-off TASK-053 action items; merged the TASK-056 2x radix-regression budget verification note into the bench_route_lookup entry. - test/Makefile.am: kept TASK-053's v2_dispatch_contract entry plus the auth_handler_* entries that landed after the branch was cut.
2 parents 371b7bc + 719d4c3 commit b654faa

15 files changed

Lines changed: 1115 additions & 318 deletions

specs/architecture/04-components/route-table.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ A `route_entry` carries:
2727

2828
**Related requirements:** PRD-HDL-REQ-002, PRD-HDL-REQ-004, PRD-HDL-REQ-006.
2929

30-
**Implementation status:** TASK-025 introduced `detail::route_entry` and the `lambda_resource` shim into the existing v1 three-map storage shape. TASK-027 wired `route_entry` into the full 3-tier table described above (hash map for exact paths, radix tree for parameterized/prefix paths, regex chain for regex routes). As of TASK-027 all three tiers are operational and the v1 three-map shape is maintained in parallel for backward-compatible dispatch until the v1 path is fully retired. TASK-056 swapped the radix-node child container from `std::unordered_map` to `std::map<…, std::less<>>` for CWE-407 immunity and added registration-time detection of prefix-vs-exact terminus collisions (`reject_terminus_collision`).
30+
**Implementation status:** TASK-025 introduced `detail::route_entry` and the `lambda_resource` shim into the existing v1 three-map storage shape. TASK-027 wired `route_entry` into the full 3-tier table described above (hash map for exact paths, radix tree for parameterized/prefix paths, regex chain for regex routes). TASK-053 retired the v1 dispatch path: `webserver_impl::resolve_resource_for_request` now consults `lookup_v2()` (cache → exact → radix → regex) directly, the v1 LRU cache and the four v1 lookup helpers (`lookup_route_cache`, `scan_regex_routes`, `store_route_cache`, `apply_extracted_params`) are deleted, and the LRU cache field is renamed `route_lru_cache`. The v1 registration-side maps (`registered_resources`, `registered_resources_str`, `registered_resources_regex`) survive *only* as registration-time bookkeeping for `prepare_or_create_lambda_shim` (lambda/class conflict detection) and the WebSocket dispatch path, both of which are non-HTTP-dispatch concerns; their removal is its own follow-up task. TASK-056 swapped the radix-node child container from `std::unordered_map` to `std::map<…, std::less<>>` for CWE-407 immunity and added registration-time detection of prefix-vs-exact terminus collisions (`reject_terminus_collision`).
3131

3232
---

specs/tasks/v2-deferred-backlog-plan.md

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ on `canonicalize_lookup_path`) can ride along with TASK-053.
4242
**Milestone:** M5 - Routing, Lifecycle, Builder & Features
4343
**Component:** `webserver_impl` dispatch
4444
**Estimate:** L
45+
**Status:** Done
4546

4647
**Goal:**
4748
Make TASK-027's 3-tier route table (`exact_routes_`, radix tree, regex
@@ -52,30 +53,48 @@ the v1 vector. The architectural goal of TASK-027 (O(1) exact lookup +
5253
LRU cache + radix scan) is not realised end-to-end.
5354

5455
**Action Items:**
55-
- [ ] Locate the v1 lookup site (`webserver_impl::find_route_for_request`
56-
or equivalent in `src/detail/webserver_dispatch.cpp`) and add a feature
57-
flag (`use_lookup_v2_`, default `true`) that selects `lookup_v2` over
58-
the legacy walk.
59-
- [ ] Wire the `lookup_result` shape (tier_hit, captured_params) into the
60-
existing dispatch contract so the call site doesn't need a parallel
61-
`route_entry*` path.
62-
- [ ] Remove the v1 fallback walk once `make check` and
63-
`routing_regression_test` pass under the v2 path.
64-
- [ ] Delete the legacy linear `route_table_v1_` field when no caller
65-
remains. (May require a follow-up grep sweep of `webserver_register.cpp`
66-
/ `webserver_routes.cpp`.)
67-
- [ ] Run `test/bench_hook_overhead.cpp` and a new
68-
`test/bench_route_lookup.cpp` to confirm the cache-hit path is in the
69-
expected 100ns ballpark and the radix tier is in the µs range. When
70-
creating `bench_route_lookup.cpp` also verify the TASK-056 acceptance
71-
criterion: the `std::map`-based radix node container introduced by
72-
TASK-056 must show no regression worse than 2× on the cache-miss radix
73-
path compared to the former `std::unordered_map` baseline (the 2× budget
74-
was formally deferred from TASK-056 to this task because `lookup_v2` was
75-
not yet wired into dispatch when TASK-056 landed).
76-
- [ ] Drop the "TODO(Cycle K): rename route_cache_v2 → route_lru_cache"
77-
comment in `webserver_impl.hpp:202` and do the rename now that v1 is
78-
gone.
56+
- [x] Locate the v1 lookup site (`webserver_impl::resolve_resource_for_request`)
57+
and add the safety net first: a unit-level contract test
58+
(`test/unit/v2_dispatch_contract_test.cpp`) pinning the
59+
end-to-end (method, path) → entry shape against `lookup_v2`
60+
parity so step-2 cutover cannot regress silently. Committed
61+
as TASK-053 step 1.
62+
- [x] Wire the `lookup_result` shape (tier_hit, captured_params) into
63+
the dispatch contract: `resolve_resource_for_request` now
64+
consults `lookup_v2()` directly behind the same `bool found,
65+
route_entry entry` shape the v1 path expected, gated by the
66+
`use_lookup_v2_` flag (default `true`). Committed as TASK-053
67+
step 2.
68+
- [x] Remove the v1 fallback walk and rename `route_cache_v2`
69+
`route_lru_cache` in one commit so the dispatch path has a
70+
single, named cache field. The four v1 lookup helpers
71+
(`lookup_route_cache`, `scan_regex_routes`, `store_route_cache`,
72+
`apply_extracted_params`) are deleted; the v1 registration
73+
maps (`registered_resources*`) survive only as registration-
74+
time bookkeeping for `prepare_or_create_lambda_shim` and the
75+
WebSocket path, flagged in comments and the architecture doc
76+
as non-dispatch state with their removal as its own follow-
77+
up. Committed as TASK-053 step 3.
78+
- [x] Flip basic-suite integration tests whose v1 expectations no
79+
longer match v2 semantics (`overlapping_endpoints`,
80+
`regex_matching_arg_custom`, `regex_url_exact_match`) and
81+
point them at `test/REGRESSION.md` §3/§4 plus the pinned
82+
unit-level routing_regression tests. Committed as TASK-053
83+
step 4.
84+
- [x] Add `test/bench_route_lookup.cpp`: pins cache-hit median ≤ 200
85+
ns and 8-segment radix tier median ≤ 5 µs via
86+
`webserver_test_access::impl(...)->lookup_v2(...)` (no MHD
87+
daemon). Wired into `make bench` via `bench_targets`, NOT
88+
`make check`. Sanitizer builds skip with exit 0. Committed
89+
as TASK-053 step 5. The TASK-056 2× radix-regression budget
90+
was also verified here per the acceptance-criterion deferral
91+
from TASK-056.
92+
- [x] The "TODO(Cycle K): rename route_cache_v2 → route_lru_cache"
93+
comment was removed when the rename landed in step 3; the
94+
field is now `route_lru_cache` and the only surviving
95+
`route_cache_v2` token in the headers is the historical
96+
pointer comment ("Renamed from route_cache_v2 in TASK-053
97+
step 3...") on the field declaration.
7998

8099
**Dependencies:**
81100
- Blocked by: TASK-027 (Done), TASK-028 (Done)

0 commit comments

Comments
 (0)