1/**
2 * Self-registered *internal extension* for the generated Lambda entry.
3 *
4 * Registering an internal extension buys the Shutdown phase: a sandbox
5 * with no registered extensions is killed with no signal at all (0 ms);
6 * with an internal extension Lambda sends SIGTERM and allows 500 ms before
7 * SIGKILL — the entry closes the instance scope in that window.
8 *
9 * The extension deliberately subscribes to NO events (`events: []`).
10 * Subscribing to `INVOKE` and holding `/event/next` open as a
11 * post-response work window was tried and rejected: a buffered Function
12 * URL does not return the response to the caller until the entire Invoke
13 * phase completes, so held work showed up as response latency anyway — and
14 * environments whose invoke phase was extended this way were observed
15 * being condemned and recycled (no END/REPORT, SIGTERM within seconds,
16 * fresh INIT on the next request). Per-invocation cleanup therefore
17 * settles inline in the dispatch; keep request finalizers fast.
18 *
19 * A registered extension must signal readiness via the blocking
20 * `/event/next` long-poll or the Init phase hangs; for an extension
21 * subscribed to no events that call never resolves, so it is fired
22 * un-awaited and parks for the sandbox's lifetime.
23 *
24 * https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html
25 */
26export const registerLambdaExtension = async (): Promise<void> => {
27 const api = process.env.AWS_LAMBDA_RUNTIME_API;
28 if (!api) return;
29 const base = `http://${api}/2020-01-01/extension`;
30 try {
31 const registration = await fetch(`${base}/register`, {
32 method: "POST",
33 headers: { "Lambda-Extension-Name": "alchemy-graceful-shutdown" },
34 body: JSON.stringify({ events: [] }),
35 });
36 const extensionId = registration.headers.get("lambda-extension-identifier");
37 if (extensionId) {
38 void fetch(`${base}/event/next`, {
39 headers: { "Lambda-Extension-Identifier": extensionId },
40 }).catch(() => undefined);
41 }
42 } catch {
43 // Not running on Lambda (or the Extensions API refused) — the function
44 // still works, it just gets no shutdown window.
45 }
46};