perf(app): batch catalog updates, tune caches, add captcha env fallback
- catalog: apply bulk offer edits in a single transaction with one RCON refresh instead of N round-trips, virtualize the items table past 150 rows and cap the shop preview at 200 tiles - cache: lift the public cache TTLs and the boot warm-up into env-tunable constants (src/lib/perf-ttls.ts; CMS_*_TTL_SEC, CMS_WARMUP_ENABLED) - auth: resolve the captcha provider, site key and secret from CAPTCHA_PROVIDER, TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY when the admin settings are unset; an explicit DB value (including "none") still wins, so Turnstile can be enabled per-deploy without touching the DB.
This commit is contained in:
1 parent
05c2706eaf
commit
9f024dc6ac
15 files changed
+529
-83
No files matched your search
+34
@@ -103,6 +103,27 @@ const schema = z
|
||||
// Redis — strongly recommended in production (required for multi-instance).
|
||||
// Without it, rate limits / shared caches are in-process only.
|
||||
REDIS_URL: z.string().optional(),
|
||||
// ── Cache TTL tuning (seconds; see src/lib/perf-ttls.ts) ──────────────
|
||||
// Defaults match the previous hard-coded values; set only to tune.
|
||||
CMS_HOME_PAYLOAD_TTL_SEC: z.coerce.number().int().positive().optional(),
|
||||
CMS_NEWS_LIST_TTL_SEC: z.coerce.number().int().positive().optional(),
|
||||
CMS_NEWS_ARCHIVE_TTL_SEC: z.coerce.number().int().positive().optional(),
|
||||
CMS_SEARCH_TTL_SEC: z.coerce.number().int().positive().optional(),
|
||||
CMS_ONLINE_COUNT_TTL_SEC: z.coerce.number().int().positive().optional(),
|
||||
CMS_COUNTERS_TTL_SEC: z.coerce.number().int().positive().optional(),
|
||||
CMS_SITE_SETTINGS_TTL_SEC: z.coerce.number().int().positive().optional(),
|
||||
CMS_SITE_SETTINGS_MEMORY_TTL_SEC: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.optional(),
|
||||
// Boot-time cache warm-up (priming hot keys after each deploy). Set to
|
||||
// "false"/"0" to skip — useful on hosts where the boot DB burst is
|
||||
// undesirable (e.g. tiny containers right after a restore).
|
||||
CMS_WARMUP_ENABLED: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) => value !== "false" && value !== "0"),
|
||||
// App-layer anti-DDoS gate (proxy rate limiter). On by default in
|
||||
// production; set to "false" or "0" to disable without removing it.
|
||||
ANTI_DDOS_ENABLED: z
|
||||
@@ -151,6 +172,19 @@ const schema = z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) => value !== "false" && value !== "0"),
|
||||
// ── CAPTCHA (Turnstile) — env fallback for the DB-backed settings ─────
|
||||
// The admin panel (housekeeping → settings) wins when it has values; these
|
||||
// let a deploy enable Turnstile without touching the DB. An explicit DB
|
||||
// value — including "none" — always overrides the env fallback.
|
||||
CAPTCHA_PROVIDER: z.preprocess(
|
||||
(value) => (value === "" ? undefined : value),
|
||||
z.enum(["none", "turnstile", "recaptcha", "hcaptcha"]).optional(),
|
||||
),
|
||||
// Public site key (rendered in the widget via server → client props).
|
||||
TURNSTILE_SITE_KEY: z.string().optional(),
|
||||
// Server-only secret used against Cloudflare's siteverify endpoint.
|
||||
// Never NEXT_PUBLIC_: verification would become client-trusting.
|
||||
TURNSTILE_SECRET_KEY: z.string().optional(),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (data.NODE_ENV !== "production") return;
|
||||
|
||||
Reference in new issue
Block a user