import { BackgroundTaskProvider } from "./BackgroundTaskProvider.ts";

/**
 * Cloudflare Workers variant of {@link BackgroundTaskProvider}.
 *
 * Cloudflare freezes the isolate once the response is returned, so a plain
 * fire-and-forget promise would be killed mid-flight. The platform exposes a
 * per-request `executionCtx.waitUntil(promise)` that keeps the isolate alive
 * until `promise` settles; the request entry point (generated by the Cloudflare
 * build) stashes it in the Alepha store under `cloudflare.waitUntil`.
 *
 * This is the ONE place that reads that key — call sites use
 * {@link BackgroundTaskProvider.defer} and stay platform-agnostic.
 *
 * `waitUntil` is request-scoped, so `defer()` must be called within the
 * request's async context (which is where background work is scheduled). Outside
 * a request (e.g. a cron tick) the key is absent and we fall back to the base
 * fire-and-track behaviour.
 */
export class WorkerdBackgroundTaskProvider extends BackgroundTaskProvider {
  protected override keepAlive(promise: Promise<void>): void {
    const waitUntil = this.alepha.store.get("cloudflare.waitUntil") as
      | ((p: Promise<unknown>) => void)
      | undefined;

    if (typeof waitUntil !== "function") {
      // No request-scoped execution context (cron / outside a request). The
      // base tracking + a long-lived isolate keep the promise alive.
      return;
    }

    try {
      waitUntil(promise);
    } catch (error) {
      // The runtime rejects waitUntil if called outside a request scope; the
      // promise still runs, just without the isolate-alive guarantee.
      this.log.debug(
        "waitUntil rejected — falling back to fire-and-track",
        error as Error,
      );
    }
  }
}
