Skip to content

Commit 3d57ab1

Browse files
maxkadelclaude
andcommitted
Memoize Site.instance per-request via RequestStore
Site.instance (upstream Hyku) uses first_or_create with no memoization -- every call is a fresh DB round-trip. Profiling found a single /catalog page load calls it ~650-680 times, almost entirely through the `delegate :account, ..., to: :instance` line (the ubiquitous Site.account accessor), not through one obvious N+1 loop. Memoizes via RequestStore (already a transitive dependency), matching how current_account is already memoized in ApplicationController and HykuHelper. RequestStore clears automatically at each request boundary, lining up with when Apartment re-resolves the tenant -- no risk of a stale Site leaking across tenants on a reused Puma thread. Verified locally (docker compose): confirmed genuine red (2 of 4 examples fail) with this file removed, and green with it restored. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 3b45166 commit 3d57ab1

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

app/models/site_decorator.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
# OVERRIDE Hyku -- Site.instance uses `first_or_create`, which is never
4+
# memoized: every call is a fresh database round-trip. Profiling found a
5+
# single /catalog page load calls Site.instance ~650-680 times, almost
6+
# entirely through the `delegate :account, ..., to: :instance` line (the
7+
# ubiquitous `Site.account` accessor), not through one obvious N+1 loop.
8+
# Memoize per-request via RequestStore (already a transitive dependency
9+
# here), the same way `current_account` is already memoized in
10+
# ApplicationController/HykuHelper. RequestStore clears automatically at
11+
# each request boundary via its own Rack middleware, which lines up with
12+
# when Apartment re-resolves the tenant -- so there's no risk of a stale
13+
# Site leaking across tenants on a reused Puma thread.
14+
module SiteDecorator
15+
def instance
16+
RequestStore.store[:site_instance] ||= super
17+
end
18+
end
19+
20+
Site.singleton_class.prepend(SiteDecorator)

0 commit comments

Comments
 (0)