Skip to main content

A construct for deploying a Lambda function that can be invoked every time unit less than one minute.

Project description

cdk-lambda-subminute

License Release npm downloads pypi downloads NuGet downloads repo languages

npm (JS/TS) PyPI (Python) Maven (Java) Go NuGet
Link Link Link Link Link

This construct creates a state machine that can invoke a Lambda function per time unit which can be less than one minute, such as invoking every 10 seconds. You only need to craft a Lambda function and then assign it as an argument into the construct. An example is included.

Serverless Architecture

Introduction

This construct library is reffered to thie AWS Architecture blog post, A serverless solution for invoking AWS Lambda at a sub-minute frequency, written by Emanuele Menga. I made it as a constrcut library where you only need to care about a target Lambda function, how frequent and how long you want to execute.

Example

Typescript

You could also refer to here.

$ cdk --init language typescript
$ yarn add cdk-lambda-subminute
class TypescriptStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const targetLabmda = new Function(this, 'targetFunction', {
      code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); })'), // It's just a simple function for demonstration purpose only.
      functionName: 'testTargetFunction',
      runtime: Runtime.NODEJS_18_X,
      handler: 'index.handler',
    });
    const cronJobExample = 'cron(50/1 15-17 ? * SUN-SAT *)';
    const subminuteMaster = new LambdaSubminute(this, 'LambdaSubminute', { targetFunction: targetLabmda, cronjobExpression: cronJobExample });

    new cdk.CfnOutput(this, 'OStateMachineArn', { value: subminuteMaster.stateMachineArn });
    new cdk.CfnOutput(this, 'OIteratorFunctionArn', { value: subminuteMaster.iteratorFunction.functionArn });
  }
}

const app = new cdk.App();
new TypescriptStack(app, 'TypescriptStack', {
});

Python

You could also refer to here.

# upgrading related Python packages
$ python -m ensurepip --upgrade
$ python -m pip install --upgrade pip
$ python -m pip install --upgrade virtualenv
# initialize a CDK Python project
$ cdk init --language python
# make packages installed locally instead of globally
$ source .venv/bin/activate
$ cat <<EOL > requirements.txt
aws-cdk.core
aws-cdk.aws-lambda
cdk-lambda-subminute
EOL
$ python -m pip install -r requirements.txt
from aws_cdk import core as cdk
from aws_cdk.aws_lambda import Code, Function, Runtime
from cdk_lambda_subminute import LambdaSubminute

class PythonStack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        target_lambda = Function(
            self, "targetFunction",
            code=Code.from_inline(
                "exports.handler = function(event, ctx, cb) { return cb(null, \"hi\"); })"),
            function_name="testTargetFunction",
            runtime=Runtime.NODEJS_18_X,
            handler="index.handler"
        )
        cron_job_example = "cron(10/1 4-5 ? * SUN-SAT *)"
        subminute_master = LambdaSubminute(
            self, "LambdaSubminute",
            target_function=target_lambda,
            cronjob_expression=cron_job_example,
            frequency=7,
            interval_time=8)

        cdk.CfnOutput(self, "OStateMachineArn",
                      value=subminute_master.state_machine_arn)
        cdk.CfnOutput(self, "OIteratorFunctionArn",
                      value=subminute_master.iterator_function.function_arn)
$ deactivate

Java

You could also refer to here.

$ cdk init --language java
$ mvn package
.
.
<properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <cdk.version>2.76.0</cdk.version>
      <constrcut.verion>2.0.128</constrcut.verion>
      <junit.version>5.7.1</junit.version>
</properties>
 .
 .
 <dependencies>
     <!-- AWS Cloud Development Kit -->
      <dependency>
            <groupId>software.amazon.awscdk</groupId>
            <artifactId>core</artifactId>
            <version>${cdk.version}</version>
      </dependency>
      <dependency>
            <groupId>software.amazon.awscdk</groupId>
            <artifactId>lambda</artifactId>
            <version>${cdk.version}</version>
      </dependency>
      <dependency>
            <groupId>io.github.hsiehshujeng</groupId>
            <artifactId>cdk-lambda-subminute</artifactId>
            <version>${constrcut.verion}</version>
      </dependency>
     .
     .
     .
 </dependencies>
package com.myorg;

import software.amazon.awscdk.core.CfnOutput;
import software.amazon.awscdk.core.CfnOutputProps;
import software.amazon.awscdk.core.Construct;
import software.amazon.awscdk.core.Stack;
import software.amazon.awscdk.core.StackProps;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.FunctionProps;
import software.amazon.awscdk.services.lambda.Runtime;
import io.github.hsiehshujeng.cdk.lambda.subminute.LambdaSubminute;
import io.github.hsiehshujeng.cdk.lambda.subminute.LambdaSubminuteProps;

public class JavaStack extends Stack {
    public JavaStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public JavaStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Function targetLambda = new Function(this, "targetFunction",
          FunctionProps.builder()
              .code(Code.fromInline("exports.handler = function(event, ctx, cb) { return cb(null, \"hi\"); })"))
              .functionName("estTargetFunction")
              .runtime(Runtime.NODEJS_18_X)
              .handler("index.handler")
              .build());
        String cronJobExample = "cron(50/1 4-5 ? * SUN-SAT *)";
        LambdaSubminute subminuteMaster = new LambdaSubminute(this, "LambdaSubminute", LambdaSubminuteProps.builder()
              .targetFunction(targetLambda)
              .cronjobExpression(cronJobExample)
              .frequency(6)
              .intervalTime(9)
              .build());

        new CfnOutput(this, "OStateMachineArn",
                CfnOutputProps.builder()
                  .value(subminuteMaster.getStateMachineArn())
                  .build());
        new CfnOutput(this, "OIteratorFunctionArn",
                CfnOutputProps.builder()
                  .value(subminuteMaster.getIteratorFunction().getFunctionName())
                  .build());
    }
}

C#

You could also refer to here.

$ cdk init --language csharp
$ dotnet add src/Csharp package Amazon.CDK.AWS.Lambda
$ dotnet add src/Csharp package Lambda.Subminute --version 2.0.128
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;
using ScottHsieh.Cdk;

namespace Csharp
{
    public class CsharpStack : Stack
    {
        internal CsharpStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var targetLambda = new Function(this, "targetFunction", new FunctionProps
            {
                Code = Code.FromInline("exports.handler = function(event, ctx, cb) { return cb(null, \"hi\"); })"),
                FunctionName = "testTargetFunction",
                Runtime = Runtime.NODEJS_18_X,
                Handler = "index.handler"
            });
            string cronJobExample = "cron(50/1 6-7 ? * SUN-SAT *)";
            var subminuteMaster = new LambdaSubminute(this, "LambdaSubminute", new LambdaSubminuteProps
            {
                TargetFunction = targetLambda,
                CronjobExpression = cronJobExample,
                Frequency = 10,
                IntervalTime = 6,
            });

            new CfnOutput(this, "OStateMachineArn", new CfnOutputProps
            {
                Value = subminuteMaster.StateMachineArn
            });
            new CfnOutput(this, "OIteratorFunctionArn", new CfnOutputProps
            {
                Value = subminuteMaster.IteratorFunction.FunctionArn
            });
        }
    }
}

Statemachine Diagram

image

Known issue

Originally, I utilized PythonFuncion in the module of @aws-cdk/aws-lambda-python to build the iterator Lambda function. Every thing works fine, including test, on my local machine (MacBook Pro M1), until it comes to the CI in Github Actions, it awlays gave me the following message:

## cdk version: 1.105.0 (build 4813992)
Bundling did not produce any output. Check that content is written to /asset-output.

      64 |     }));
      65 |
    > 66 |     this.function = new PythonFunction(this, 'Iterator', {
         |                     ^
      67 |       functionName: 'lambda-subminute-iterator',
      68 |       description: 'A function for breaking the limit of 1 minute with the CloudWatch Rules.',
      69 |       logRetention: RetentionDays.THREE_MONTHS,

      at AssetStaging.bundle (node_modules/@aws-cdk/core/lib/asset-staging.ts:484:13)
      at AssetStaging.stageByBundling (node_modules/@aws-cdk/core/lib/asset-staging.ts:328:10)
      at stageThisAsset (node_modules/@aws-cdk/core/lib/asset-staging.ts:194:35)
      at Cache.obtain (node_modules/@aws-cdk/core/lib/private/cache.ts:24:13)
      at new AssetStaging (node_modules/@aws-cdk/core/lib/asset-staging.ts:219:44)
      at new Asset (node_modules/@aws-cdk/aws-s3-assets/lib/asset.ts:127:21)
      at AssetCode.bind (node_modules/@aws-cdk/aws-lambda/lib/code.ts:277:20)
      at new Function (node_modules/@aws-cdk/aws-lambda/lib/function.ts:583:29)
      at new PythonFunction (node_modules/@aws-cdk/aws-lambda-python/lib/function.ts:106:5)
      at new IteratorLambda (src/cdk-lambda-subminute.ts:66:21)
      at new LambdaSubminute (src/cdk-lambda-subminute.ts:25:22)
      at Object.<anonymous>.test (test/integ.test.ts:23:3)

I actually have tried many different methods according to the following threads but to no avail. I'll attempt to test some thoughts or just post the issue onto the CDK Github repo.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cdk_lambda_subminute-2.0.166.tar.gz (10.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cdk_lambda_subminute-2.0.166-py3-none-any.whl (10.8 MB view details)

Uploaded Python 3

File details

Details for the file cdk_lambda_subminute-2.0.166.tar.gz.

File metadata

  • Download URL: cdk_lambda_subminute-2.0.166.tar.gz
  • Upload date:
  • Size: 10.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.3

File hashes

Hashes for cdk_lambda_subminute-2.0.166.tar.gz
Algorithm Hash digest
SHA256 42776c483732e46f9f40c926244604ebe26df37d2ad1e857f57d28c1c1d13bf0
MD5 6bd02bc14aed92bd634413f11cfb42b1
BLAKE2b-256 6cea1a84b3a7b23e47680bb2bf7fa5737b5a13edef4ecd3de8207e8be88f9722

See more details on using hashes here.

File details

Details for the file cdk_lambda_subminute-2.0.166-py3-none-any.whl.

File metadata

File hashes

Hashes for cdk_lambda_subminute-2.0.166-py3-none-any.whl
Algorithm Hash digest
SHA256 26897bae84698feff1cd51a0a562135532e82d368f52f81c9cc51b7a7830060f
MD5 6f287fe463eaca9b3b24e4b101b14257
BLAKE2b-256 22eefcf889a57e415d10014ec8f32fe355b22aedb2d0b912b15c4f035489d697

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page