Skip to content
Source
Sign inSign up

thread-dismissal.ts

33 lines970 Bytes

1interface ThreadDismissal {
2 readonly finished: Promise<void>;
3 readonly restore: () => void;
4}
5​
6const rows = new Map<string, Set<() => ThreadDismissal>>();
7​
8export function registerThreadDismissal(key: string, dismiss: () => ThreadDismissal) {
9 const registrations = rows.get(key) ?? new Set();
10 registrations.add(dismiss);
11 rows.set(key, registrations);
12 return () => {
13 registrations.delete(dismiss);
14 if (registrations.size === 0) rows.delete(key);
15 };
17​
18export async function withThreadDismissal<T>(
19 key: string,
20 action: () => Promise<T>,
21 succeeded: (result: T) => boolean,
22): Promise<T> {
23 const dismissals = Array.from(rows.get(key) ?? [], (dismiss) => dismiss());
24 let committed = false;
25 try {
26 await Promise.all(dismissals.map(({ finished }) => finished));
27 const result = await action();
28 committed = succeeded(result);
29 return result;
30 } finally {
31 if (!committed) dismissals.forEach(({ restore }) => restore());
32 }