1import { appAtomRegistry } from "./atom-registry";
2import { createThreadOutboxManager } from "./thread-outbox-manager";
3import type { QueuedThreadMessage } from "./thread-outbox-model";
4import { expoThreadOutboxStorage, flushThreadOutboxWrites } from "./thread-outbox-storage";
5
6export * from "./thread-outbox-model";
7
8export const threadOutboxManager = createThreadOutboxManager({
9 registry: appAtomRegistry,
10 storage: expoThreadOutboxStorage,
11});
12
13/**
14 * Lands queued outbox mutations before the JS runtime is torn down (app update
15 * restart). An enqueued message is published to the atom immediately but its
16 * durable write waits behind the mutation queue, so draining only the writes
17 * already mid-file would miss it.
18 */
19export async function flushThreadOutbox(): Promise<void> {
20 await threadOutboxManager.serialize(async () => {});
21 await flushThreadOutboxWrites();
22}
23
24export function enqueueThreadOutboxMessage(message: QueuedThreadMessage): Promise<void> {
25 return threadOutboxManager.enqueue(message);
26}
27
28/** Waits for pending writes to settle; false if the message was rolled back. */
29export function confirmThreadOutboxMessageQueued(message: QueuedThreadMessage): Promise<boolean> {
30 return threadOutboxManager.confirmQueued(message);
31}
32
33/**
34 * Rewrite a queued message; no-op (false) if it was removed in the meantime,
35 * or (with `expectedRevision` from `threadOutboxRevision`) if any other write
36 * was accepted since the revision was read.
37 */
38export function updateThreadOutboxMessage(
39 message: QueuedThreadMessage,
40 expectedRevision?: number,
41): Promise<boolean> {
42 return threadOutboxManager.update(message, expectedRevision);
43}
44
45/** Snapshot of a queued message's write revision, for update's CAS. */
46export function threadOutboxRevision(messageId: QueuedThreadMessage["messageId"]): number {
47 return threadOutboxManager.revisionOf(messageId);
48}
49
50// Removal lives in `thread-outbox-removal.ts`: taking a message out of the
51// outbox must also release its local attachment files, and that owner needs
52// the composer draft state this module must not depend on.