feat: cache marka api responses

This commit is contained in:
Max Richter
2025-11-04 12:09:17 +01:00
parent bb4e895770
commit fea9b69d4d
9 changed files with 163 additions and 98 deletions

View File

@@ -1,3 +1,4 @@
import { createCache } from "../cache.ts";
import { MARKA_API_KEY } from "../env.ts";
import { getImage } from "../image.ts";
import { GenericResource } from "./schema.ts";
@@ -24,32 +25,62 @@ async function addImageToResource<T extends GenericResource>(
return resource as T;
}
export async function fetchResource<T extends GenericResource>(
type Resource = GenericResource & {
content: GenericResource["content"] & Array<GenericResource>;
};
const fetchCache = createCache<Resource>("marka");
const cacheLock = new Map<string, Promise<Resource>>();
async function cachedFetch(
url: string,
): Promise<Resource | undefined> {
if (fetchCache.has(url)) {
return fetchCache.get(url);
}
if (cacheLock.has(url)) {
return cacheLock.get(url);
}
const response = (async () => {
const response = await fetch(url);
const res = await response.json();
fetchCache.set(url, res);
return res;
})();
cacheLock.set(
url,
response,
);
const res = await response;
if (!res) {
cacheLock.delete(url);
}
return res;
}
export async function fetchResource<T extends Resource>(
resource: string,
): Promise<T | undefined> {
try {
const response = await fetch(
`${url}/resources/${resource}`,
);
const res = await response.json();
const d = `${url}/resources/${resource}`;
const res = await cachedFetch(d);
if (!res) return;
return addImageToResource<T>(res);
} catch (_e) {
return;
}
}
export async function listResources<T = GenericResource>(
export async function listResources<T extends GenericResource>(
resource: string,
): Promise<T[]> {
try {
const response = await fetch(
`${url}/resources/${resource}`,
);
const list = await response.json();
const d = `${url}/resources/${resource}`;
const list = await cachedFetch(d);
if (!list) return [];
return Promise.all(
list?.content
.filter((a: GenericResource) => a?.content?._type)
.map((res: GenericResource) => addImageToResource(res)),
.filter((a) => a?.content?._type)
.map((res) => addImageToResource(res) as Promise<T>),
);
} catch (_e) {
return [];

View File

@@ -1,4 +1,13 @@
export function formatDate(date: Date): string {
export function formatDate(date?: string | Date): string {
if (!date) return "";
if (typeof date === "string") {
try {
const d = new Date(date);
return formatDate(d);
} catch (_e) {
return "";
}
}
const options = { year: "numeric", month: "long", day: "numeric" } as const;
return new Intl.DateTimeFormat("en-US", options).format(date);
}