alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
44 lines (40 loc) • 1.75 kB
text/typescript
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,
);
}
}
}