Skip to content

Repository files navigation

Lambda Timeout Wrapper

A utility to handle AWS Lambda timeouts gracefully by providing early detection and cleanup opportunities.

Features

  • Early timeout detection with configurable safety margin
  • Support for user-provided cleanup handlers
  • Graceful cleanup of resources before timeout
  • Fallback timer mode for testing outside Lambda
  • Configurable logging

Installation

npm install @hopdrive/lambda-timeout-wrapper

Usage

Traditional API

import{createTimeoutWrapper}from'@hopdrive/lambda-timeout-wrapper';// Create a wrapper with Lambda contextconstwrapper=createTimeoutWrapper({getRemainingTimeInMillis: context.getRemainingTimeInMillis,logger: console.log});// Use the wrapperconstresult=awaitwrapper(// Your main functionasync()=>{// Your long-running code herereturn{success: true};},// Timeout handlerasync()=>{// Cleanup code when timeout is imminentawaitcleanup();},// Optional user cleanup handlerasync()=>{// Additional cleanup specific to your use caseawaituserCleanup();});

Simplified API

import{withTimeout}from'@hopdrive/lambda-timeout-wrapper';// Direct usage in Lambda handler with minimal configurationexportconsthandler=withTimeout(event,context,{// Main function to runrun: async()=>{// Your main Lambda logic herereturn{statusCode: 200,body: 'Success'};},// Cleanup handler - runs first when timeout occursonCleanup: async()=>{// Close any open resources},// Timeout handler - runs after cleanup when timeout is imminentonTimeout: async()=>{// Your timeout handling logicreturn{statusCode: 408,body: 'Request timed out'};}});

This ultra-simplified API makes it easier to use the wrapper directly in your Lambda handlers. The wrapper automatically:

  • Gets the remaining time from the Lambda context
  • Sets sensible defaults (safetyMarginMs: 1000, logger: console.log)
  • Handles the proper execution order of handlers when a timeout occurs

Configuration

The wrapper accepts the following options:

interfaceTimeoutWrapperOptions{// Time in ms to start timeout handling before actual timeout (default: 5000)safetyMarginMs?: number;// Interval in ms to check for timeout (default: 1000)checkIntervalMs?: number;// Time in ms allocated for cleanup operations (default: 3000)cleanupTimeMs?: number;// Function to get remaining execution time in msgetRemainingTimeInMillis?: ()=>number;// Whether to use fallback timer instead of Lambda contextisUsingFallbackTimer?: boolean;// Logger function for timeout wrapper messageslogger?: (message: string)=>void;}

Error Handling

The wrapper will throw a TimeoutError when a timeout is detected. This error includes:

interfaceTimeoutErrorextendsError{isLambdaTimeout: boolean;handlerError?: Error;}

Testing

For testing outside of Lambda, you can use the fallback timer mode:

constwrapper=createTimeoutWrapper({isUsingFallbackTimer: true,getRemainingTimeInMillis: ()=>60000// 60 seconds});

Development

Setup

# Clone the repository
git clone https://github.com/hopdrive/lambda-timeout-wrapper.git
cd lambda-timeout-wrapper
# Install dependencies
npm install

Build

# Build all formats (CJS, ESM, and type declarations)
npm run build
# Build specific formats
npm run build:cjs
npm run build:esm
npm run build:types

Test

# Run tests
npm test

Deployment

# Standard deployment (specify version)
npm run deploy 1.0.1
# Force deployment (creates an empty commit, specify version)
npm run deploy-force 1.0.1
# Using the @hopdrive/package-deploy-scripts integration
npm run deploy-wrapper # Uses the wrapper around package-deploy-scripts

During deployment, the lib/version.js file is automatically generated using the genversion npm package. This file exports the current package version from package.json, making it accessible throughout the codebase.

Examples

This package includes several example implementations in the examples directory:

1. Simple Lambda Example

File:examples/simple-lambda-example.js

A basic example showing how to use the wrapper in a standard AWS Lambda function without any framework dependencies.

2. Netlify Function Example

Files:

  • JavaScript: examples/netlify-function-example.js
  • TypeScript: examples/netlify-function-example.ts

Shows how to use the wrapper in a Netlify Function, which runs on AWS Lambda, with database connection handling.

3. Local Testing Example

File:examples/local-fallback-example.js

Demonstrates how to use the wrapper with the fallback timer mode for local development and testing outside of a Lambda environment.

How to Use These Examples

AWS Lambda or Netlify Functions

  1. Install the package:

    npm install @hopdrive/lambda-timeout-wrapper
  2. For Netlify Functions:

    • Create a netlify/functions directory in your project
    • Copy the example file and customize as needed
    • Install TypeScript if using the TypeScript example:
      npm install --save-dev typescript @netlify/functions
    • Create a netlify.toml file to configure function settings:
      [build]
      functions = "netlify/functions"
      [functions]
      # Extend the timeout to 30 seconds (default is 10)timeout = 30
  3. Deploy to AWS or Netlify:

    • Follow standard AWS Lambda or Netlify deployment procedures
    • Your functions will now gracefully handle timeouts

Local Testing

  1. Install the package:

    npm install @hopdrive/lambda-timeout-wrapper
  2. Run the local example:

    node examples/local-fallback-example.js
  3. Customize timeout values:

    • Adjust getRemainingTimeInMillis to simulate different Lambda timeouts
    • Modify the simulated task duration to test timeout behavior

Key Concepts Demonstrated

1. Creating the Wrapper

constwrapper=createTimeoutWrapper({// Get remaining time from Lambda context (for Lambda/Netlify)getRemainingTimeInMillis: context.getRemainingTimeInMillis,// OR use fallback timer for local testing// isUsingFallbackTimer: true,// getRemainingTimeInMillis: () => 10000, // 10 seconds// Set safety margin (how early to detect timeout)safetyMarginMs: 3000,// 3 seconds// Enable logginglogger: console.log});

2. Using the Wrapper

constresult=awaitwrapper(// Main function - your primary logicasync()=>{// Do your work herereturn{success: true};},// Timeout handler - runs when timeout is imminentasync()=>{// Handle timeout gracefullyreturn{timedOut: true};},// User cleanup handler - always runs after success or timeoutasync()=>{// Clean up resources here (database connections, etc.)});

3. Error Handling

try{constresult=awaitwrapper(/* ... */);returnresult;}catch(error){// Check if it's a timeout errorif(error.isLambdaTimeout){// Handle timeout-specific error case}// Handle other errors}

Implementation Details for Netlify Functions

  1. Directory Structure:

    your-project/
    ├── netlify.toml
    └── netlify/
    └── functions/
    └── your-function.js
    
  2. Required Dependencies:

    • For JavaScript:
      npm install @hopdrive/lambda-timeout-wrapper
    • For TypeScript:
      npm install @hopdrive/lambda-timeout-wrapper
      npm install --save-dev typescript @netlify/functions @types/node
  3. Running Locally:

    npm install -g netlify-cli
    netlify dev
  4. Testing: Access your function at: http://localhost:8888/.netlify/functions/your-function

Testing Timeout Behavior

To test timeout behavior:

  1. Increase task duration:

    • Modify the setTimeout duration in the examples to exceed the timeout limit
  2. Decrease safety margin:

    • Set a smaller safetyMarginMs value to test different cleanup timing
  3. Observe graceful shutdown:

    • Watch how resources are properly cleaned up when timeout occurs

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages