← back to Wallco Ai
/api/designs/random: ETag + 304 on seeded calls (deterministic given seed+state) — unseeded stays no-store
4f0ff5ec812eb781463afd5430c469eeb77a3255 · 2026-05-12 19:57:44 -0700 · SteveStudio2
Files touched
Diff
commit 4f0ff5ec812eb781463afd5430c469eeb77a3255
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Tue May 12 19:57:44 2026 -0700
/api/designs/random: ETag + 304 on seeded calls (deterministic given seed+state) — unseeded stays no-store
---
server.js | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/server.js b/server.js
index f249181..2bf03a7 100644
--- a/server.js
+++ b/server.js
@@ -483,7 +483,18 @@ app.get('/api/designs/random', (req, res) => {
url: `/design/${d.id}`,
});
}
- res.setHeader('Cache-Control', 'no-store');
+ // Seeded calls are deterministic given (n, category, seed, DESIGNS state) — make them
+ // cacheable via ETag so a trade-user rail can poll without paying the shuffle cost.
+ // Unseeded calls stay no-store because the whole point is fresh randomness.
+ if (seedRaw !== undefined && seedRaw !== '') {
+ const etag = `"rand-${CATALOG_LAST_MODIFIED.getTime()}-${k}-${category || 'all'}-${parseInt(seedRaw,10)}-${pool.length}"`;
+ res.setHeader('ETag', etag);
+ res.setHeader('Cache-Control', 'private, max-age=0, must-revalidate');
+ const inm = req.headers['if-none-match'];
+ if (inm && inm === etag) return res.status(304).end();
+ } else {
+ res.setHeader('Cache-Control', 'no-store');
+ }
res.json({
n: k,
pool_size: pool.length,
← 01a41fa /admin/health: extended JSON w/ by-color cache stats (hits/m
·
back to Wallco Ai
·
drunk-animals: hero block on /designs?cat=drunk-animals + gh 69c2529 →