Skip to content

Commit 2555450

Browse files
committed
Merge TASK-051 (per-route hooks via http_resource::add_hook) into feature/v2.0
2 parents 873359e + 82fc856 commit 2555450

24 files changed

Lines changed: 2147 additions & 161 deletions

specs/tasks/M5-routing-lifecycle/TASK-051.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
Add a per-resource scope to the hook bus so a hook can be attached to one route instead of every request. Required to give #273-style early-413 a per-route flavor (different size caps per endpoint), to put per-route timing in `response_sent`, etc.
99

1010
**Action Items:**
11-
- [ ] Add `http_resource::add_hook(hook_phase, ...)` overloads — but ONLY for phases that fire after route resolution: `before_handler`, `handler_exception`, `after_handler`, `response_sent`, `request_completed`. Passing any earlier phase throws `std::invalid_argument` with a message naming the phase and the constraint.
12-
- [ ] Add per-resource storage on `http_resource`: `std::array<std::vector<std::function<...>>, hook_phase::count_>` (most slots unused per the constraint above, but the array shape simplifies indexed access) + `std::array<std::atomic<bool>, hook_phase::count_> any_hooks_` + `std::shared_mutex hook_table_mutex_`. Memory footprint is a fixed-size array of empty vectors; revisit if TASK-039's `sizeof(http_resource)` budget is tight (a single `std::vector` of `std::pair<hook_phase, function>` is the fallback if so).
13-
- [ ] In `webserver_impl::dispatch_resource_handler`, fire the per-route hook chain at each of the five applicable phases AFTER the server-wide chain at that phase, BEFORE checking for a server-wide short-circuit's result. (If server-wide short-circuited, do NOT run per-route — the response is already fixed.)
14-
- [ ] In `webserver_impl::request_completed`, locate the resource that handled the request (carried on `modded_request` as a `weak_ptr<http_resource>` populated at dispatch time) and fire its `request_completed` per-route chain after the server-wide one. If the resource was unregistered between dispatch and completion, the `lock()` returns null and the per-route chain is skipped.
15-
- [ ] Lock order: `route_table_mutex_` (already held by dispatch) → resource's `hook_table_mutex_` → server-wide `hook_table_mutex_`. Documented in `specs/architecture/05-cross-cutting.md` §5.6 and verified by TSan.
16-
- [ ] `hook_handle` returned by `http_resource::add_hook` carries the same RAII semantics as the server-wide handle — destruction removes the registration. The handle holds a `weak_ptr<http_resource>`; if the resource is destroyed before the handle, `remove()` is a no-op.
11+
- [x] Add `http_resource::add_hook(hook_phase, ...)` overloads — but ONLY for phases that fire after route resolution: `before_handler`, `handler_exception`, `after_handler`, `response_sent`, `request_completed`. Passing any earlier phase throws `std::invalid_argument` with a message naming the phase and the constraint.
12+
- [x] Add per-resource storage on `http_resource`: `std::array<std::vector<std::function<...>>, hook_phase::count_>` (most slots unused per the constraint above, but the array shape simplifies indexed access) + `std::array<std::atomic<bool>, hook_phase::count_> any_hooks_` + `std::shared_mutex hook_table_mutex_`. Memory footprint is a fixed-size array of empty vectors; revisit if TASK-039's `sizeof(http_resource)` budget is tight (a single `std::vector` of `std::pair<hook_phase, function>` is the fallback if so).
13+
- [x] In `webserver_impl::dispatch_resource_handler`, fire the per-route hook chain at each of the five applicable phases AFTER the server-wide chain at that phase, BEFORE checking for a server-wide short-circuit's result. (If server-wide short-circuited, do NOT run per-route — the response is already fixed.)
14+
- [x] In `webserver_impl::request_completed`, locate the resource that handled the request (carried on `modded_request` as a `weak_ptr<http_resource>` populated at dispatch time) and fire its `request_completed` per-route chain after the server-wide one. If the resource was unregistered between dispatch and completion, the `lock()` returns null and the per-route chain is skipped.
15+
- [x] Lock order: `route_table_mutex_` (already held by dispatch) → resource's `hook_table_mutex_` → server-wide `hook_table_mutex_`. Documented in `specs/architecture/05-cross-cutting.md` §5.6 and verified by TSan.
16+
- [x] `hook_handle` returned by `http_resource::add_hook` carries the same RAII semantics as the server-wide handle — destruction removes the registration. The handle holds a `weak_ptr<http_resource>`; if the resource is destroyed before the handle, `remove()` is a no-op.
1717

1818
**Dependencies:**
1919
- Blocked by: TASK-045, TASK-048, TASK-049, TASK-050
@@ -31,4 +31,4 @@ Add a per-resource scope to the hook bus so a hook can be attached to one route
3131
**Related Requirements:** PRD-HOOK-REQ-002, PRD-HOOK-REQ-003, PRD-HOOK-REQ-004, PRD-HOOK-REQ-006, PRD-HOOK-REQ-007
3232
**Related Decisions:** DR-012, §4.10, §5.6
3333

34-
**Status:** Not Started
34+
**Status:** Done

specs/tasks/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ Nominally: **13 sequential tasks**, each S–XL. Most other tasks parallelize of
133133
| TASK-048 | Fire `route_resolved` and `before_handler`; wire 404/405/auth aliases | M5 | Done | TASK-045, TASK-027, TASK-031 |
134134
| TASK-049 | Fire `handler_exception`; wire `internal_error_handler` alias | M5 | Done | TASK-045, TASK-031 |
135135
| TASK-050 | Fire `after_handler` (post-handler short-circuit), `response_sent`, `request_completed`; wire `log_access` alias | M5 | Done | TASK-045 |
136-
| TASK-051 | Per-route hooks (`http_resource::add_hook`) | M5 | Not Started | TASK-045, TASK-048, TASK-049, TASK-050 |
136+
| TASK-051 | Per-route hooks (`http_resource::add_hook`) | M5 | Done | TASK-045, TASK-048, TASK-049, TASK-050 |
137137
| TASK-052 | Hook bus documentation, examples, benchmark, stress-test extension (touches back into TASK-040/041/042/043) | M5 | Not Started | TASK-045, TASK-046, TASK-047, TASK-048, TASK-049, TASK-050, TASK-051 |
138138
| TASK-037 | CI test for build-flag invariance | M6 | Done | TASK-034 |
139139
| TASK-038 | Sanitizer-clean tests for `http_response` move semantics | M6 | Done | TASK-009, TASK-036 |

0 commit comments

Comments
 (0)