fix: invalidate cached public site settings
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-05-18 17:52:16 +08:00
parent 33f25f4b21
commit bd98282bc5
3 changed files with 75 additions and 13 deletions

View File

@ -67,6 +67,7 @@ import {
EXTERNAL_IMAGE_API_CONFIG_KEY,
normalizeExternalImageApiConfig,
} from "@/lib/external-image-api/config";
import { clearScopedSiteSettingsCache } from "@/lib/site-settings/public-cache";
const settingSchema = z.object({
key: z.string(),
@ -270,6 +271,7 @@ export async function POST(request: Request) {
value: normalizeExternalImageApiConfig(value),
updatedBy: session.user.id,
});
clearScopedSiteSettingsCache();
return Response.json({
setting: saved[0],
@ -388,6 +390,7 @@ export async function POST(request: Request) {
value: nextValue,
updatedBy: session.user.id,
});
clearScopedSiteSettingsCache();
return Response.json({ setting: setting[0] });
} catch (error) {

View File

@ -98,6 +98,13 @@ import {
normalizeOssImageMigrationConfig,
OSS_MIGRATION_CONFIG_KEY,
} from "@/lib/storage/migration-config";
import {
clearScopedSiteSettingsCache,
deleteScopedSiteSettingsCache,
getScopedSiteSettingsCache,
PUBLIC_SITE_SETTINGS_CACHE_TTL_MS,
setScopedSiteSettingsCache,
} from "@/lib/site-settings/public-cache";
import {
getHomeChatAnimationHtmlBytes,
HOME_CHAT_ANIMATION_CONFIG_KEY,
@ -502,22 +509,19 @@ const PUBLIC_SITE_SETTINGS_SCOPES = new Set<string>([
"home",
]);
const SCOPED_SITE_SETTINGS_SERVER_CACHE_TTL_MS = 30_000;
const scopedSiteSettingsServerCache = new Map<
string,
{ data: Record<string, unknown>; expiresAt: number }
>();
function createScopedSiteSettingsResponse(
scope: PublicSiteSettingsScope,
data: Record<string, unknown>,
cacheStatus: "HIT" | "MISS" = "MISS",
cacheKey: string = scope
) {
scopedSiteSettingsServerCache.set(cacheKey, {
data,
expiresAt: Date.now() + SCOPED_SITE_SETTINGS_SERVER_CACHE_TTL_MS,
});
if (cacheStatus !== "HIT") {
setScopedSiteSettingsCache(
cacheKey,
data,
PUBLIC_SITE_SETTINGS_CACHE_TTL_MS
);
}
const response = NextResponse.json(data);
// Lightweight public settings change rarely; keep them browser-local briefly
@ -883,7 +887,7 @@ export async function GET(request: NextRequest) {
const cacheKey = brandName.trim()
? `${scopedScope}:${brandName.trim().toLowerCase()}`
: scopedScope;
const cached = scopedSiteSettingsServerCache.get(cacheKey);
const cached = getScopedSiteSettingsCache(cacheKey);
if (cached && cached.expiresAt > Date.now()) {
return createScopedSiteSettingsResponse(
scopedScope,
@ -892,6 +896,9 @@ export async function GET(request: NextRequest) {
cacheKey
);
}
if (cached) {
deleteScopedSiteSettingsCache(cacheKey);
}
return getScopedPublicSiteSettings(scopedScope, {
brandName,
@ -2625,7 +2632,7 @@ export async function PUT(request: NextRequest) {
}
await persistHomeAnimationConfig();
scopedSiteSettingsServerCache.clear();
clearScopedSiteSettingsCache();
return NextResponse.json({
...updated,
@ -3274,7 +3281,7 @@ export async function PUT(request: NextRequest) {
},
});
}
scopedSiteSettingsServerCache.clear();
clearScopedSiteSettingsCache();
return NextResponse.json({
...created,

View File

@ -0,0 +1,52 @@
const PUBLIC_SITE_SETTINGS_CACHE_TTL_MS = 30_000;
const PUBLIC_SITE_SETTINGS_CACHE_KEY = Symbol.for(
"ai-chatbot.public-site-settings-cache",
);
type PublicSiteSettingsCacheEntry = {
data: Record<string, unknown>;
expiresAt: number;
};
function getPublicSiteSettingsCacheStore() {
const globalCache = globalThis as typeof globalThis & {
[PUBLIC_SITE_SETTINGS_CACHE_KEY]?: Map<
string,
PublicSiteSettingsCacheEntry
>;
};
if (!globalCache[PUBLIC_SITE_SETTINGS_CACHE_KEY]) {
globalCache[PUBLIC_SITE_SETTINGS_CACHE_KEY] = new Map<
string,
PublicSiteSettingsCacheEntry
>();
}
return globalCache[PUBLIC_SITE_SETTINGS_CACHE_KEY]!;
}
export function getScopedSiteSettingsCache(cacheKey: string) {
return getPublicSiteSettingsCacheStore().get(cacheKey) ?? null;
}
export function setScopedSiteSettingsCache(
cacheKey: string,
data: Record<string, unknown>,
ttlMs: number = PUBLIC_SITE_SETTINGS_CACHE_TTL_MS,
) {
getPublicSiteSettingsCacheStore().set(cacheKey, {
data,
expiresAt: Date.now() + ttlMs,
});
}
export function deleteScopedSiteSettingsCache(cacheKey: string) {
getPublicSiteSettingsCacheStore().delete(cacheKey);
}
export function clearScopedSiteSettingsCache() {
getPublicSiteSettingsCacheStore().clear();
}
export { PUBLIC_SITE_SETTINGS_CACHE_TTL_MS };