/**
 * Main-thread client for the DB factor worker.
 *
 * Spawns `db-worker.js` in a Node `worker_thread`, performs the init
 * handshake (passes dbPath + storePath), and returns a `WorkerBus` the
 * caller can use to send read requests and subscribe to DB events.
 *
 * The init handshake is a single `{kind:"init"}` postMessage followed by an
 * `{kind:"init-ok"}` or `{kind:"init-error"}` reply. This is done OUTSIDE
 * the WorkerBus message protocol so a bus method can't accidentally race
 * the construction of LocalStore inside the worker.
 *
 * Failure mode: if the worker can't load (the file is missing in a packaged
 * build, the DB can't be opened, etc.), `spawnDbWorker()` rejects. The
 * caller can fall back to in-process LocalStore — same code, same answers,
 * just shares the event loop with whatever else is running on main. That's
 * the legacy path; the worker is the new default but we don't paint
 * ourselves into a corner.
 */
import { Worker } from "node:worker_threads";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { WorkerBus } from "@bobfrankston/mailx-bus";
export async function spawnDbWorker(opts) {
    const here = dirname(fileURLToPath(import.meta.url));
    const workerPath = join(here, "db-worker.js");
    const worker = new Worker(workerPath);
    // Don't let the worker prevent process exit. Phase 1 design choice — the
    // service shuts down cleanly via its own gracefulShutdown which closes
    // the worker explicitly; without unref, a stuck worker could block exit.
    worker.unref();
    // Init handshake — promise resolves on init-ok, rejects on init-error.
    await new Promise((resolve, reject) => {
        const onMessage = (msg) => {
            if (!msg || typeof msg !== "object")
                return;
            if (msg.kind === "init-ok") {
                worker.off("message", onMessage);
                resolve();
            }
            else if (msg.kind === "init-error") {
                worker.off("message", onMessage);
                reject(new Error(`db-worker init: ${msg.error}`));
            }
            // Ignore other messages (bus traffic) — the bus is built AFTER
            // we resolve, so any bus message arriving here is stale.
        };
        worker.on("message", onMessage);
        worker.on("error", (e) => {
            worker.off("message", onMessage);
            reject(e);
        });
        worker.postMessage({ kind: "init", dbPath: opts.dbPath, storePath: opts.storePath });
    });
    // Wrap the post-init port in a WorkerBus on this side. The worker has
    // already wrapped its parentPort in a WorkerBus inside its init handler.
    const bus = new WorkerBus(worker);
    return {
        bus,
        worker,
        async close() {
            await worker.terminate();
        },
    };
}
//# sourceMappingURL=db-worker-client.js.map