Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create initializeFunction lifecycle hook #25

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 31 additions & 27 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import * as UserFunction from "./utils/UserFunction";

LogPatch.patchConsole();

export function run(appRoot: string, handler: string): void {
export async function run(appRoot: string, handler: string): Promise<void> {
if (!process.env.AWS_LAMBDA_RUNTIME_API) {
throw new Error("Missing Runtime API Server configuration.");
}
Expand Down Expand Up @@ -50,7 +50,10 @@ export function run(appRoot: string, handler: string): void {
BeforeExitListener.reset();
process.on("beforeExit", BeforeExitListener.invoke);

const handlerFunc = UserFunction.load(appRoot, handler) as HandlerFunction;
const handlerFunc = (await UserFunction.load(
appRoot,
handler
)) as HandlerFunction;
const runtime = new Runtime(client, handlerFunc, errorCallbacks);

runtime.scheduleIteration();
Expand Down
20 changes: 18 additions & 2 deletions src/utils/UserFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ function _loadUserApp(
}
}

async function _initializeFunction(userApp: any): Promise<void> {
try {
await userApp.initializeFunction();
} catch (e) {
if (e instanceof TypeError) {
// initializeFunction lifecycle hook not implemented
return;
} else {
throw e;
}
}
}

function _throwIfInvalidHandler(fullHandlerString: string): void {
if (fullHandlerString.includes(RELATIVE_PATH_SUBSTRING)) {
throw new MalformedHandlerName(
Expand Down Expand Up @@ -137,10 +150,10 @@ function _throwIfInvalidHandler(fullHandlerString: string): void {
* for traversing up the filesystem '..')
* Errors for scenarios known by the runtime, will be wrapped by Runtime.* errors.
*/
export const load = function (
export const load = async function (
appRoot: string,
fullHandlerString: string
): HandlerFunction {
): Promise<HandlerFunction> {
_throwIfInvalidHandler(fullHandlerString);

const [moduleRoot, moduleAndHandler] = _moduleRootAndHandler(
Expand All @@ -149,6 +162,9 @@ export const load = function (
const [module, handlerPath] = _splitHandlerString(moduleAndHandler);

const userApp = _loadUserApp(appRoot, moduleRoot, module);

await _initializeFunction(userApp);

const handlerFunc = _resolveHandler(userApp, handlerPath);

if (!handlerFunc) {
Expand Down
44 changes: 44 additions & 0 deletions test/unit/utils/UserFunction.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/** Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

"use strict";

require("should");
import { load } from "../../../src/utils/UserFunction";

describe("Invoking the load function", async() => {
it("should resolve promise when init hook function is present", async() => {
const handler = "InitPresent.handler"
const appRoot = "test/unit/utils/function";

const handlerFunc = (await load(
appRoot,
handler
)) as Function;

handlerFunc.should.be.Function;
handlerFunc().should.be.true;
});
it("should not fail when init hook function is absent", async() => {
const handler = "InitAbsent.handler"
const appRoot = "test/unit/utils/function";

const handlerFunc = (await load(
appRoot,
handler
)) as Function;

handlerFunc.should.be.Function;
});
it("should catch TypeError exception", async() => {
const handler = "InitThrowsTypeError.handler"
const appRoot = "test/unit/utils/function";

const handlerFunc = (await load(
appRoot,
handler
)) as Function;

handlerFunc.should.be.Function;
handlerFunc().should.be.true;
});
});
24 changes: 24 additions & 0 deletions test/unit/utils/function/InitAbsent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// console.log("******** enter the init block ********");

let resolved = false;

function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms)).then(() => {resolved = true});
}

async function init() {
// console.log("******** enter initializeFunction hook ********");
// console.log("******** Is promised resolved? " + resolved + " ********");
// console.log("******** sleep for 20 ms... ********")
let p = await sleep(20);
// console.log("******** wake up ********");
// console.log("******** Is promised resolved? " + resolved + " ********");
}

init();

exports.handler = async (event, context) => {
// console.log("******** enter the handler ********");
// console.log("******** Is promised resolved? " + resolved + " ********");
return ( resolved ? true: false );
}
22 changes: 22 additions & 0 deletions test/unit/utils/function/InitPresent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// console.log("******** enter the init block ********");

let resolved = false;

function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms)).then(() => {resolved = true});
}

exports.initializeFunction = async () => {
// console.log("******** enter initializeFunction hook ********");
// console.log("******** Is promised resolved? " + resolved + " ********");
// console.log("******** sleep for 20 ms... ********")
let p = await sleep(20);
// console.log("******** wake up ********");
// console.log("******** Is promised resolved? " + resolved + " ********");
}

exports.handler = async (event, context) => {
// console.log("******** enter the handler ********");
// console.log("******** Is promised resolved? " + resolved + " ********");
return ( resolved ? true: false );
}
7 changes: 7 additions & 0 deletions test/unit/utils/function/InitThrowsTypeError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
exports.initializeFunction = async () => {
throw new TypeError;
}

exports.handler = async (event, context) => {
return true;
}