Merged in feature/warmup (pull request #1887)
* unified warmup function Approved-by: Linus Flood
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import type { CacheOrGetOptions } from "./cacheOrGetOptions"
|
||||
|
||||
const ONE_HOUR_IN_SECONDS = 3_600 as const
|
||||
const ONE_DAY_IN_SECONDS = 86_400 as const
|
||||
|
||||
@@ -60,6 +62,7 @@ export type DataCache = {
|
||||
* @param key The cache key
|
||||
* @param getDataFromSource An async function that provides a value to cache
|
||||
* @param ttl Time to live, either a named cache time or a number of seconds
|
||||
* @param opts Options to control cache behavior when retrieving or storing data.
|
||||
* @returns The cached value or the result from the callback
|
||||
*/
|
||||
cacheOrGet: <T>(
|
||||
@@ -67,7 +70,8 @@ export type DataCache = {
|
||||
getDataFromSource: (
|
||||
overrideTTL?: (cacheTime: CacheTime) => void
|
||||
) => Promise<T>,
|
||||
ttl: CacheTime
|
||||
ttl: CacheTime,
|
||||
opts?: CacheOrGetOptions
|
||||
) => Promise<T>
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { type CacheTime, type DataCache } from "@/services/dataCache/Cache"
|
||||
|
||||
import {
|
||||
type CacheOrGetOptions,
|
||||
shouldGetFromCache,
|
||||
} from "../cacheOrGetOptions"
|
||||
import { cacheLogger } from "../logger"
|
||||
import { generateCacheKey } from "./generateCacheKey"
|
||||
import { get } from "./get"
|
||||
@@ -8,10 +12,15 @@ import { set } from "./set"
|
||||
export const cacheOrGet: DataCache["cacheOrGet"] = async <T>(
|
||||
key: string | string[],
|
||||
callback: (overrideTTL: (cacheTime: CacheTime) => void) => Promise<T>,
|
||||
ttl: CacheTime
|
||||
ttl: CacheTime,
|
||||
opts?: CacheOrGetOptions
|
||||
) => {
|
||||
const cacheKey = generateCacheKey(key)
|
||||
const cachedValue = await get<T>(cacheKey)
|
||||
|
||||
let cachedValue: Awaited<T> | undefined = undefined
|
||||
if (shouldGetFromCache(opts)) {
|
||||
cachedValue = await get<T>(cacheKey)
|
||||
}
|
||||
|
||||
let realTTL = ttl
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import { type CacheTime, type DataCache } from "@/services/dataCache/Cache"
|
||||
import { cacheLogger } from "@/services/dataCache/logger"
|
||||
|
||||
import {
|
||||
type CacheOrGetOptions,
|
||||
shouldGetFromCache,
|
||||
} from "../../cacheOrGetOptions"
|
||||
import { get } from "./get"
|
||||
import { set } from "./set"
|
||||
|
||||
export const cacheOrGet: DataCache["cacheOrGet"] = async <T>(
|
||||
key: string | string[],
|
||||
callback: (overrideTTL?: (cacheTime: CacheTime) => void) => Promise<T>,
|
||||
ttl: CacheTime
|
||||
ttl: CacheTime,
|
||||
opts?: CacheOrGetOptions
|
||||
): Promise<T> => {
|
||||
if (Array.isArray(key)) {
|
||||
key = key.join("-")
|
||||
@@ -18,14 +23,16 @@ export const cacheOrGet: DataCache["cacheOrGet"] = async <T>(
|
||||
realTTL = cacheTime
|
||||
}
|
||||
|
||||
const cached = await get(key)
|
||||
let cached: Awaited<T> | undefined = undefined
|
||||
if (shouldGetFromCache(opts)) {
|
||||
cached = await get(key)
|
||||
if (cached) {
|
||||
return cached
|
||||
}
|
||||
|
||||
if (cached) {
|
||||
return cached as T
|
||||
cacheLogger.debug(`Miss for key '${key}'`)
|
||||
}
|
||||
|
||||
cacheLogger.debug(`Miss for key '${key}'`)
|
||||
|
||||
try {
|
||||
const data = await callback(overrideTTL)
|
||||
await set(key, data, realTTL)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { unstable_cache } from "next/cache"
|
||||
import { revalidateTag, unstable_cache } from "next/cache"
|
||||
|
||||
import {
|
||||
type CacheTime,
|
||||
@@ -6,18 +6,26 @@ import {
|
||||
getCacheTimeInSeconds,
|
||||
} from "@/services/dataCache/Cache"
|
||||
|
||||
import {
|
||||
type CacheOrGetOptions,
|
||||
shouldGetFromCache,
|
||||
} from "../../cacheOrGetOptions"
|
||||
import { cacheLogger } from "../../logger"
|
||||
|
||||
export const cacheOrGet: DataCache["cacheOrGet"] = async <T>(
|
||||
key: string | string[],
|
||||
callback: () => Promise<T>,
|
||||
ttl: CacheTime
|
||||
ttl: CacheTime,
|
||||
opts?: CacheOrGetOptions
|
||||
): Promise<T> => {
|
||||
if (!Array.isArray(key)) {
|
||||
key = [key]
|
||||
}
|
||||
|
||||
const perf = performance.now()
|
||||
if (!shouldGetFromCache(opts)) {
|
||||
revalidateTag(key[0])
|
||||
}
|
||||
|
||||
const res = await unstable_cache(callback, key, {
|
||||
revalidate: getCacheTimeInSeconds(ttl),
|
||||
|
||||
27
apps/scandic-web/services/dataCache/cacheOrGetOptions.ts
Normal file
27
apps/scandic-web/services/dataCache/cacheOrGetOptions.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Options to control cache behavior when retrieving or storing data.
|
||||
*
|
||||
* - "cache-first": Default behaviour, check if the needed data is available in the cache first. If the data is found, it is returned immediately. Otherwise, the data is fetched and then cached.
|
||||
* - "fetch-then-cache": Always fetch the data first, and then update the cache with the freshly fetched data.
|
||||
*/
|
||||
export type CacheStrategy = "cache-first" | "fetch-then-cache"
|
||||
export type CacheOrGetOptions = {
|
||||
cacheStrategy?: CacheStrategy
|
||||
}
|
||||
|
||||
export function defaultCacheOrGetOptions(
|
||||
opts: CacheOrGetOptions = {}
|
||||
): CacheOrGetOptions {
|
||||
return {
|
||||
cacheStrategy: "cache-first",
|
||||
...opts,
|
||||
}
|
||||
}
|
||||
|
||||
export function shouldGetFromCache(
|
||||
opts: CacheOrGetOptions | undefined
|
||||
): boolean {
|
||||
opts = defaultCacheOrGetOptions(opts)
|
||||
|
||||
return opts.cacheStrategy === "cache-first"
|
||||
}
|
||||
@@ -3,11 +3,10 @@ import { env } from "@/env/server"
|
||||
import { isEdge } from "@/utils/isEdge"
|
||||
|
||||
import { createMemoryCache } from "./MemoryCache/createMemoryCache"
|
||||
import { type DataCache } from "./Cache"
|
||||
import { createDistributedCache } from "./DistributedCache"
|
||||
import { cacheLogger } from "./logger"
|
||||
|
||||
import type { DataCache } from "./Cache"
|
||||
|
||||
export type { CacheTime, DataCache } from "./Cache"
|
||||
|
||||
export async function getCacheClient(): Promise<DataCache> {
|
||||
|
||||
Reference in New Issue
Block a user