Created
January 10, 2024 02:16
-
-
Save randallb/a1aa7983b0cb798ec526e3c43b54e582 to your computer and use it in GitHub Desktop.
deno runtime for aws lambda
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { Handler } from "packages/lib/types/Handler.ts"; | |
import { shutdownBackend } from "packages/events/mod.ts"; | |
// import { createLogger } from "packages/logs/mod.ts"; | |
import { APIGatewayEvent } from "packages/lib/types/aws.ts"; | |
function createLogger(..._args: Array<string>) { | |
return console.log; | |
} | |
const log = createLogger("lambda:runtime", "debug"); | |
const logInfo = createLogger("lambda:runtime", "info"); | |
const logError = createLogger("lambda:runtime", "error"); | |
let abortController = new AbortController(); | |
let isShuttingDown = false; | |
async function handleShutdown() { | |
if (isShuttingDown) return; | |
isShuttingDown = true; | |
logInfo("Shutting down gracefully..."); | |
// Abort the ongoing fetch operation | |
abortController.signal.onabort = async () => { | |
logInfo("killed request"); | |
await Deno.writeTextFile( | |
"/tmp/.restart", | |
`${Date.now()}`, | |
); | |
}; | |
abortController.abort(); | |
} | |
globalThis.addEventListener("unload", handleShutdown); | |
const AWS_LAMBDA_RUNTIME_API = Deno.env.get( | |
"AWS_LAMBDA_RUNTIME_API", | |
); | |
async function respond<T>( | |
lambdaRuntimeIncomingRequest: Response, | |
handler: Handler<T>, | |
) { | |
const requestId = lambdaRuntimeIncomingRequest.headers.get( | |
"Lambda-Runtime-Aws-Request-Id", | |
); | |
if (!requestId) throw new Error("Missing Lambda-Runtime-Aws-Request-Id"); | |
log("debug", "Processing request", requestId); | |
let responseBody = { | |
statusCode: 500, | |
body: "My bad!", | |
}; | |
try { | |
const awsRequest = await lambdaRuntimeIncomingRequest.json(); | |
responseBody = await handler(awsRequest); | |
} catch (error) { | |
logError("error", error); | |
throw error; | |
} | |
const awsResponse = await fetch( | |
`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${requestId}/response`, | |
{ | |
method: "POST", | |
headers: { "Content-Type": "application/json" }, | |
body: JSON.stringify(responseBody), | |
}, | |
); | |
await shutdownBackend(); | |
return awsResponse; | |
} | |
export default async function serveLambda<T = APIGatewayEvent>( | |
handler: Handler<T>, | |
) { | |
const args = Deno.args; | |
if (args[0] === "cache") { | |
log("Exiting because all we wanted to do was cache the dependencies"); | |
return; | |
} | |
log("info", "Starting Lambda runtime server"); | |
logInfo(`waiting at ${Date.now()}`); | |
while (true) { | |
log("debug", "Awaiting request"); | |
try { | |
const incomingRequest = await fetch( | |
`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next`, | |
{ | |
signal: abortController.signal, | |
}, | |
); | |
await respond<T>(incomingRequest, handler); | |
} catch (_e) { | |
break; | |
} | |
abortController = new AbortController(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment