perf: cache allowed origins set instead of rebuilding per request#486
perf: cache allowed origins set instead of rebuilding per request#486hobostay wants to merge 1 commit intonexu-io:mainfrom
Conversation
buildAllowedOrigins() was called on every API request, creating a new Set each time. Since the allowed origins only depend on resolvedPort and OD_WEB_PORT (which don't change at runtime), cache the result after the first build. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Hi @hobostay! 🎉 Thanks for the contribution — this is a smart optimization that eliminates repeated Set construction on every request. I will run a deep review and get back to you within 24h. Thanks for making open-design better! |
lefarcen
left a comment
There was a problem hiding this comment.
Hey @hobostay, thanks for the optimization! This eliminates ~1200-1800 Set constructions per second on a busy daemon (12-18 origins × 100 req/s). I verified the caching is safe — resolvedPort, host, and OD_WEB_PORT are all immutable after startServer() completes.
Two minor suggestions below (non-blocking):
| ); | ||
| return _cachedAllowedOrigins; | ||
| } | ||
|
|
There was a problem hiding this comment.
P3 Stale comment reference — this line still mentions buildAllowedOrigins after the rename to getAllowedOrigins. Not a functional issue, but in security-sensitive origin-checking code it's worth keeping comments accurate to avoid future confusion.
Suggested fix: update the comment to reference getAllowedOrigins().
|
Additional suggestion — test coverage gap: The existing origin tests in Suggestion: Add a focused integration test against real
This would catch any future cache lifetime issues. Not blocking, but worth considering for future robustness. |
mrcfps
left a comment
There was a problem hiding this comment.
@hobostay I reviewed the daemon origin-cache change and found one merge-blocking TypeScript issue in the new cache variable. Once the cache is explicitly typed, the optimization should preserve the intended origin policy while avoiding the repeated Set allocation. Thanks for the focused performance cleanup 🙂
Generated by Looper 0.5.4 · runner=reviewer · agent=opencode| // both use the same policy (loopback + explicit bind host, HTTP + HTTPS, | ||
| // OD_WEB_PORT support). | ||
| function buildAllowedOrigins() { | ||
| let _cachedAllowedOrigins = null; |
There was a problem hiding this comment.
This cache needs an explicit Set<string> | null type before it can merge. With apps/daemon/tsconfig.json enabling strict, a let initialized only with null is not safely typed as the later Set, but the changed code assigns new Set(...) and then returns it for .has(...) checks in the middleware. That makes the daemon typecheck fail (or leaves the cache without the intended Set<string> contract), blocking this otherwise small optimization.
Please type the cache and return value explicitly, for example:
let _cachedAllowedOrigins: Set<string> | null = null;
function getAllowedOrigins(): Set<string> {
if (_cachedAllowedOrigins) return _cachedAllowedOrigins;
// ...
}That keeps the cached origin set type aligned with the middleware usage and avoids a strict-mode compile break. 🙂
Summary
Setof allowed origins after first build instead of creating a newSeton every API requestProblem
buildAllowedOrigins()was called inside the/apimiddleware on every single request, creating a newSetwith ~12-18 entries each time. The allowed origins depend only onresolvedPortandOD_WEB_PORT, which don't change at runtime.Test plan
🤖 Generated with Claude Code