perf: round 13 — grouped-view virtualization, notification/login query narrowing, HTTP dedup, locale precompute

Benchmark-gated (BEFORE/AFTER + equivalence/safety gate per change), same
discipline as rounds 2-12. Full write-up in benches/ROUND13.md.

Shipped:
- V1 Grouped views windowed (files route + ResourceList). The grid arm was
  the last unwindowed path (trash is grouped-by-default in grid): each
  swimlane now feeds its own VirtualList, outer container a flex stack.
  vitest gate: 800-item grouped grid mounts <120 .file-item (was 800).
- Q1 get_users_by_ids drops the <=512 KiB avatar image + ui_preferences
  JSONB (notification path never reads them). 30-member fan-out 8.60 ->
  0.25 ms (34.3x), ~7.7 MB off the wire.
- Q2 Login provisioning is_empty() -> SELECT EXISTS for calendar + address
  book (every login). 0.193 -> 0.170 ms, widens with owned-row count.
- Q3 Recent-access prunes only when the upsert inserted (RETURNING xmax=0)
  — a re-access can't grow the set. 0.567 -> 0.324 ms (1.75x).
- L1 Locale supported-codes precomputed once vs rebuilt per anonymous
  request. 616 -> 17.3 ns (35.7x), 18 -> 1 allocs.
- H1 Duplicate /api TraceLayer removed (global stack already wraps it).
  1.86 -> 1.42 us/request, -6 allocs.
- H2 client_ip span field: borrow-only ClientIpDisplay vs owned String.
  187 -> 173 ns, -1 alloc.

Not shipped (discipline): the "media hooks read the blob 3x" lead was a
correctness bug, not a perf dup — the raw-path metadata/faces readers
resolve only for local+unencrypted+single-chunk blobs and silently produce
nothing otherwise. Flagged for maintainers; routing through read_blob_bytes
is a correctness fix (perf-neutral-to-negative), not a benchmark-gated
perf change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BfidAJD5AHw23jtvBUNamB
This commit is contained in:
Claude
2026-07-19 08:17:48 +00:00
parent 50eca0627f
commit f58d72a780
22 changed files with 1411 additions and 61 deletions
@@ -39,6 +39,14 @@ impl CalendarStorageAdapter {
event_repository,
}
}
/// Delegates to [`CalendarPgRepository::has_owned_calendar`] — the
/// `EXISTS` short-circuit used by the login provisioning hook instead
/// of hydrating every owned calendar to test emptiness
/// (benches/ROUND13.md §Q2).
pub async fn has_owned_calendar(&self, owner_id: Uuid) -> Result<bool, DomainError> {
self.calendar_repository.has_owned_calendar(owner_id).await
}
}
impl CalendarStoragePort for CalendarStorageAdapter {
@@ -16,6 +16,23 @@ impl AddressBookPgRepository {
pub fn new(pool: Arc<PgPool>) -> Self {
Self { pool }
}
/// `EXISTS` short-circuit for the login provisioning hook — the old
/// `get_address_books_by_owner(..).is_empty()` hydrated every owned
/// `AddressBook` row on EVERY login just to test emptiness (the ROUND9
/// §7 COUNT→EXISTS pattern; benches/ROUND13.md §Q2).
pub async fn has_owned_address_book(&self, owner_id: Uuid) -> Result<bool, DomainError> {
let exists: bool = sqlx::query_scalar(
"SELECT EXISTS(SELECT 1 FROM carddav.address_books WHERE owner_id = $1)",
)
.bind(owner_id)
.fetch_one(&*self.pool)
.await
.map_err(|e| {
DomainError::database_error(format!("Failed to probe owned address books: {}", e))
})?;
Ok(exists)
}
}
impl AddressBookRepository for AddressBookPgRepository {
@@ -16,6 +16,24 @@ impl CalendarPgRepository {
pub fn new(pool: Arc<PgPool>) -> Self {
Self { pool }
}
/// `EXISTS` short-circuit for the login provisioning hook, which only
/// needs to know whether the user owns ANY calendar. The old
/// `list_calendars_by_owner(..).is_empty()` hydrated every owned
/// `Calendar` row (8 cols incl. description/color TEXT) on EVERY login
/// just to test emptiness — the ROUND9 §7 `Drive::is_empty` COUNT→EXISTS
/// pattern (benches/ROUND13.md §Q2).
pub async fn has_owned_calendar(&self, owner_id: Uuid) -> CalendarRepositoryResult<bool> {
let exists: bool =
sqlx::query_scalar("SELECT EXISTS(SELECT 1 FROM caldav.calendars WHERE owner_id = $1)")
.bind(owner_id)
.fetch_one(&*self.pool)
.await
.map_err(|e| {
DomainError::database_error(format!("Failed to probe owned calendars: {}", e))
})?;
Ok(exists)
}
}
impl CalendarRepository for CalendarPgRepository {
@@ -96,19 +96,24 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
Ok(items)
}
async fn upsert_access(&self, user_id: Uuid, item_id: &str, item_type: &str) -> Result<()> {
sqlx::query(
async fn upsert_access(&self, user_id: Uuid, item_id: &str, item_type: &str) -> Result<bool> {
// `xmax = 0` on the affected row is the canonical upsert idiom for
// "this was an INSERT, not a DO UPDATE" — lets the caller skip the
// prune round-trip on the common re-access (UPDATE) path
// (benches/ROUND13.md §Q3).
let inserted: bool = sqlx::query_scalar(
r#"
INSERT INTO auth.user_recent_files (user_id, item_id, item_type, accessed_at)
VALUES ($1, $2, $3, CURRENT_TIMESTAMP)
ON CONFLICT (user_id, item_id, item_type)
DO UPDATE SET accessed_at = CURRENT_TIMESTAMP
RETURNING (xmax = 0)
"#,
)
.bind(user_id)
.bind(item_id)
.bind(item_type)
.execute(&*self.db_pool)
.fetch_one(&*self.db_pool)
.await
.map_err(|e| {
error!("Database error upserting recent item access: {}", e);
@@ -119,7 +124,7 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
)
})?;
Ok(())
Ok(inserted)
}
async fn remove_item(&self, user_id: Uuid, item_id: &str, item_type: &str) -> Result<bool> {
@@ -414,6 +414,16 @@ impl UserRepository for UserPgRepository {
/// recipient expansion). Missing ids are silently skipped — the
/// caller treats absent rows as "no such recipient", same as
/// `get_user_by_id` returning `NotFound` for a single lookup.
///
/// Notification-recipient projection: the up-to-512 KiB avatar `image`
/// and the `ui_preferences` JSONB are NOT hydrated (both come back as
/// `None`/`Null`) — the sole caller
/// (`RecipientNotificationService`) reads only the email/eligibility
/// fields, and a group fan-out of M members otherwise detoasted +
/// shipped + parsed M avatars purely to discard them (the ROUND12 §Q1
/// avatar-narrowing pattern; benches/ROUND13.md §Q1). If a future
/// caller needs the avatar, add a wide sibling rather than widening
/// this one back.
async fn get_users_by_ids(&self, ids: Vec<Uuid>) -> UserRepositoryResult<Vec<User>> {
if ids.is_empty() {
return Ok(Vec::new());
@@ -425,9 +435,8 @@ impl UserRepository for UserPgRepository {
id, username, email, password_hash, role::text as role_text,
storage_quota_bytes, storage_used_bytes,
created_at, updated_at, last_login_at, active,
oidc_provider, oidc_subject, image, is_external,
given_name, family_name, email_verified_at, preferred_locale, notify_on_share,
ui_preferences
oidc_provider, oidc_subject, is_external,
given_name, family_name, email_verified_at, preferred_locale, notify_on_share
FROM auth.users
WHERE id = ANY($1)
"#,
@@ -460,14 +469,14 @@ impl UserRepository for UserPgRepository {
row.get("active"),
row.get("oidc_provider"),
row.get("oidc_subject"),
row.get("image"),
None, // image — not projected (notification-recipient path)
row.get("is_external"),
row.get("given_name"),
row.get("family_name"),
row.get("email_verified_at"),
row.get("preferred_locale"),
row.get("notify_on_share"),
row.get::<serde_json::Value, _>("ui_preferences"),
serde_json::Value::Null, // ui_preferences — not projected
)
})
.collect())