perf: round 22 — hot-GET HeaderMap borrow, native-WebDAV/CalDAV etag borrowed quotes, FileDto content_hash move, CalendarEvent stamp, ShareItemType case-fold

Benchmark-gated, same rule as ROUND2-21: every change ships with a
BEFORE/AFTER counting-allocator benchmark and a byte/-value equivalence
gate; an AFTER that fails to reduce allocations exits non-zero (rollback).
See benches/ROUND22.md and examples/bench_round22_micro.rs. All arms
no-Postgres.

- H1: the hot GET handlers (get_thumbnail, download_file, list_files_query,
  list_photos, NextCloud preview, public-share download/access) take
  `req: Request` last and read `req.headers()` by borrow instead of axum's
  HeaderMap extractor, whose FromRequestParts impl clones the whole request
  header table just to read 1-3 headers (the ROUND14 §A4 middleware pattern,
  finally propagated to the handlers). 2 -> 0 allocs/req · 9.95x wall.
- W1: native WebDAV write_etag_quoted — the etag emitter for every /webdav/
  PROPFIND row (per file AND per folder, up to 500/page) — emits the quotes
  as borrowed pre-escaped " text events instead of escaping a "{etag}"
  String (the ROUND20 §C1 / ROUND21 §R4 pattern). 3 -> 0 allocs/row.
- C1: CalDAV getetag routed through a shared write_quoted_etag helper across
  all 5 sites (3 per-event + 2 per-calendar); the now-dead etag: &mut String
  buffer threaded through write_event_response/standard/requested props + the
  two per-page buffers removed. 2 -> 0 allocs/row.
- D1: FileDto::from reuses the moved parts.blob_hash instead of cloning it
  via the content_hash() getter (the ROUND19/20 move-not-clone sweep missed
  it — hash/etag are read before into_parts()). Per file row of every
  listing. 1 -> 0 allocs/row.
- E1: CalendarEvent::update_time_range/update_all_day stamp timed
  DTSTART/DTEND via fmt::compact_ical_utc stack render (chrono fallback out
  of range) instead of the %Y%m%dT%H%M%SZ strftime interpreter. 4 -> 0.
- S1: ShareItemType::try_from uses eq_ignore_ascii_case instead of a
  throwaway to_lowercase() String. 1 -> 0 allocs/parse.

Verified: cargo clippy --features bench --all-targets -D warnings clean,
cargo fmt --all --check clean, cargo test --lib --features bench = 529
passed / 0 failed (incl. the OpenAPI-spec-validity test guarding the H1
utoipa-handler signature change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DKyQ4AnYtgp1JtjzweyMeo
This commit is contained in:
Claude
2026-07-20 13:48:47 +00:00
parent 4663b06f37
commit 992bdae898
12 changed files with 918 additions and 99 deletions
+10 -5
View File
@@ -230,10 +230,12 @@ pub async fn delete_shared_link(
pub async fn access_shared_item(
State(share_use_case): State<Arc<ShareService>>,
Path(token): Path<String>,
headers: HeaderMap,
req: axum::extract::Request,
) -> impl IntoResponse {
// Honour an unlock cookie if one was issued by a prior `/verify` call.
let unlock_jwt = unlock_jwt_from_headers(&headers, &token);
// Borrow the headers (`req.headers()`) instead of the `HeaderMap` extractor's
// full clone to read the unlock cookie (benches/ROUND22.md §H1).
let unlock_jwt = unlock_jwt_from_headers(req.headers(), &token);
// The access-count increment doesn't gate the fetch — run both
// round-trips concurrently instead of serially (one RTT saved on
@@ -333,8 +335,11 @@ pub async fn verify_shared_item_password(
pub async fn download_shared_file(
State(state): State<Arc<AppState>>,
Path(token): Path<String>,
headers: HeaderMap,
req: axum::extract::Request,
) -> impl IntoResponse {
// Borrow the headers (`req.headers()`) instead of the `HeaderMap` extractor's
// full clone — the public-share download + Range path (benches/ROUND22.md §H1).
let headers = req.headers();
// 1. Resolve share service
let share_service = match &state.share_service {
Some(s) => s.clone(),
@@ -349,7 +354,7 @@ pub async fn download_shared_file(
};
// 2. Validate the share token (handles expiry + password checks)
let unlock_jwt = unlock_jwt_from_headers(&headers, &token);
let unlock_jwt = unlock_jwt_from_headers(headers, &token);
let share_dto = match share_service
.get_shared_link_with_unlock(&token, unlock_jwt.as_deref())
.await
@@ -385,7 +390,7 @@ pub async fn download_shared_file(
&state,
&share_dto.item_id,
share_dto.item_name.as_deref(),
&headers,
headers,
)
.await
}