(READ ONLY) Margin is an open annotation layer for the internet. Powered by the AT Protocol.
margin.at
extension
web
atproto
comments
1type QueueEntry = {
2 url: string;
3 resolve: (data: Record<string, string> | null) => void;
4};
5
6const MAX_CONCURRENT = 3;
7const queue: QueueEntry[] = [];
8let active = 0;
9const inflight = new Map<string, Promise<Record<string, string> | null>>();
10
11function processQueue() {
12 while (active < MAX_CONCURRENT && queue.length > 0) {
13 const entry = queue.shift()!;
14 active++;
15
16 doFetch(entry.url)
17 .then(entry.resolve)
18 .finally(() => {
19 active--;
20 processQueue();
21 });
22 }
23}
24
25function doFetch(url: string): Promise<Record<string, string> | null> {
26 const existing = inflight.get(url);
27 if (existing) return existing;
28
29 const promise = fetch(`/api/url-metadata?url=${encodeURIComponent(url)}`)
30 .then((res) => (res.ok ? res.json() : null))
31 .catch(() => null)
32 .finally(() => {
33 inflight.delete(url);
34 });
35
36 inflight.set(url, promise);
37 return promise;
38}
39
40export function fetchMetadata(
41 url: string,
42): Promise<Record<string, string> | null> {
43 try {
44 const cached = sessionStorage.getItem(`og:${url}`);
45 if (cached) return Promise.resolve(JSON.parse(cached));
46 } catch {
47 /* ignore */
48 }
49
50 return new Promise((resolve) => {
51 queue.push({ url, resolve });
52 processQueue();
53 }).then((data) => {
54 if (data) {
55 try {
56 sessionStorage.setItem(`og:${url}`, JSON.stringify(data));
57 } catch {
58 /* ignore */
59 }
60 }
61 return data as Record<string, string> | null;
62 });
63}