110 lines
2.6 KiB
TypeScript
110 lines
2.6 KiB
TypeScript
import { prisma } from "@/lib/prisma";
|
|
import { DEFAULT_SETTINGS } from "@/lib/constants";
|
|
|
|
type SettingsCacheEntry = {
|
|
value: string;
|
|
expiresAt: number;
|
|
};
|
|
|
|
declare global {
|
|
// eslint-disable-next-line no-var
|
|
var calbookSettingsCache: Map<string, SettingsCacheEntry> | undefined;
|
|
}
|
|
|
|
const settingsCache = global.calbookSettingsCache ?? new Map<string, SettingsCacheEntry>();
|
|
if (!global.calbookSettingsCache) {
|
|
global.calbookSettingsCache = settingsCache;
|
|
}
|
|
|
|
const SETTINGS_CACHE_TTL_MS = Number(process.env.SETTINGS_CACHE_TTL_MS ?? "30000");
|
|
|
|
function nowMs() {
|
|
return Date.now();
|
|
}
|
|
|
|
function readCachedSetting(key: string): string | null {
|
|
const entry = settingsCache.get(key);
|
|
if (!entry) return null;
|
|
if (entry.expiresAt <= nowMs()) {
|
|
settingsCache.delete(key);
|
|
return null;
|
|
}
|
|
return entry.value;
|
|
}
|
|
|
|
function writeCachedSetting(key: string, value: string) {
|
|
settingsCache.set(key, {
|
|
value,
|
|
expiresAt: nowMs() + SETTINGS_CACHE_TTL_MS
|
|
});
|
|
}
|
|
|
|
export function clearSettingsCache() {
|
|
settingsCache.clear();
|
|
}
|
|
|
|
export async function getSettings(keys?: string[]) {
|
|
const map: Record<string, string> = { ...DEFAULT_SETTINGS };
|
|
|
|
if (keys && keys.length > 0) {
|
|
const keySet = Array.from(new Set(keys));
|
|
const missing: string[] = [];
|
|
|
|
for (const key of keySet) {
|
|
const cached = readCachedSetting(key);
|
|
if (cached === null) {
|
|
missing.push(key);
|
|
} else {
|
|
map[key] = cached;
|
|
}
|
|
}
|
|
|
|
if (missing.length > 0) {
|
|
const records = await prisma.setting.findMany({
|
|
where: { key: { in: missing } }
|
|
});
|
|
const byKey = new Map(records.map((row) => [row.key, row.value]));
|
|
|
|
for (const key of missing) {
|
|
const value = byKey.get(key) ?? DEFAULT_SETTINGS[key] ?? "";
|
|
writeCachedSetting(key, value);
|
|
map[key] = value;
|
|
}
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
const records = await prisma.setting.findMany();
|
|
for (const row of records) {
|
|
map[row.key] = row.value;
|
|
writeCachedSetting(row.key, row.value);
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
export async function getSetting(key: string): Promise<string> {
|
|
const cached = readCachedSetting(key);
|
|
if (cached !== null) return cached;
|
|
const settings = await getSettings([key]);
|
|
return settings[key] ?? DEFAULT_SETTINGS[key] ?? "";
|
|
}
|
|
|
|
export async function setSettings(values: Record<string, string>) {
|
|
const entries = Object.entries(values);
|
|
await prisma.$transaction(
|
|
entries.map(([key, value]) =>
|
|
prisma.setting.upsert({
|
|
where: { key },
|
|
create: { key, value },
|
|
update: { value }
|
|
})
|
|
)
|
|
);
|
|
|
|
for (const [key, value] of entries) {
|
|
writeCachedSetting(key, value);
|
|
}
|
|
}
|