feat(causal): instrument the request hot path — five sites and a progress point
RFC 007 causal-site coverage for the Phase 2 bench (and any downstream
profiling): parse (head parsing attempts in read_head), router (dispatch
matching only — the winning handler and the next fall-through run outside
the guard, so the site measures dispatch, not what it dispatches to;
call() restructured match-then-dispatch for that, semantics preserved
incl. first-path+method-match-wins and the 405 two-pass), pipeline (the
plug chain inside catch_unwind; nested sites like router take over
attribution during their span, so this reads as chain overhead + handler
code outside inner sites), serialize (response head+bytes-body
serialisation; chunked stream framing is not covered — it interleaves
with writes in pump_stream and the bench doesn't stream), and
socket-write (all of write_all, writability parks included: a park
inside a site is exactly what the park-gated resume credit attributes).
progress!("responses") fires once per response fully on the wire, at
both completion points (the common path and the HTTP/1.0 EOF-stream
early return).
Site guards are #[cfg(feature = "smarm-causal")]-gated: the macros are
no-ops featureless, but binding the unit expansion would trip clippy's
let_unit_value. progress! is bare — its featureless expansion is an
empty block, free and lint-clean. Featureless build byte-behavior is
unchanged; both configs clippy-clean, full suite green both ways.
This commit is contained in:
+19
-6
@@ -135,16 +135,29 @@ impl Plug for Router {
|
||||
// path matches but a same-path-different-method does, return 405.
|
||||
// Otherwise pass through to `next` so outer pipelines can layer a
|
||||
// 404 handler (or skip and let the connection actor emit a default).
|
||||
//
|
||||
// Matching runs under the `router` causal site (RFC 007); the
|
||||
// winning handler and the `next` fall-through run outside it, so
|
||||
// the site measures dispatch, not what it dispatches to.
|
||||
let mut path_seen = false;
|
||||
for route in &self.routes {
|
||||
if let Some(params) = route.pattern.match_path(&conn.path) {
|
||||
if route.method == conn.method {
|
||||
let conn = conn.put_params(params);
|
||||
return route.handler.call(conn, next);
|
||||
let mut hit = None;
|
||||
{
|
||||
#[cfg(feature = "smarm-causal")]
|
||||
let _g = smarm::causal_site!("router");
|
||||
for (i, route) in self.routes.iter().enumerate() {
|
||||
if let Some(params) = route.pattern.match_path(&conn.path) {
|
||||
if route.method == conn.method {
|
||||
hit = Some((i, params));
|
||||
break;
|
||||
}
|
||||
path_seen = true;
|
||||
}
|
||||
path_seen = true;
|
||||
}
|
||||
}
|
||||
if let Some((i, params)) = hit {
|
||||
let conn = conn.put_params(params);
|
||||
return self.routes[i].handler.call(conn, next);
|
||||
}
|
||||
if path_seen {
|
||||
// Path is known, method isn't — RFC 7231 §6.5.5.
|
||||
conn.put_status(405)
|
||||
|
||||
Reference in New Issue
Block a user