Code Monkey home page Code Monkey logo

serverless-plugin-warmup's Introduction

Serverless WarmUp Plugin ♨

Serverless npm version npm monthly downloads Node.js CI Coverage Status license

Keep your lambdas warm during winter.

Requirements:

  • Node v18.x or higher
  • Serverless v3.8 or higher
  • AWS provider

How it works

WarmUp solves cold starts by creating a scheduled lambda (the warmer) that invokes all the selected service's lambdas in a configured time interval (default: 5 minutes) and forcing your containers to stay warm.

Installation

Install via npm in the root of your Serverless service:

npm install --save-dev serverless-plugin-warmup

Add the plugin to the plugins array in your Serverless serverless.yaml:

plugins:
  - serverless-plugin-warmup

Configuration

The warmup plugin supports creating one or more warmer functions. Warmers must be defined under custom.warmup in the serverless.yaml file before they can be used in the functions' configs:

custom:
  warmup:
    officeHoursWarmer:
      enabled: true
      events:
        - schedule: cron(0/5 8-17 ? * MON-FRI *)
      concurrency: 10
      verbose: true
      logRetentionInDays: 14
    outOfOfficeHoursWarmer:
      enabled: true
      events:
        - schedule: cron(0/5 0-7 ? * MON-FRI *)
        - schedule: cron(0/5 18-23 ? * MON-FRI *)
        - schedule: cron(0/5 * ? * SAT-SUN *)
      concurrency: 1
      verbose: false
    testWarmer:
      enabled: false

The options are the same for all the warmers:

  • folderName Folder to temporarily store the generated code (defaults to .warmup)
  • cleanFolder Whether to automatically delete the generated code folder. You might want to keep it if you are doing some custom packaging (defaults to true)
  • name Name of the generated warmer lambda (defaults to ${service}-${stage}-warmup-plugin-${warmerName})
  • roleName Name to be applied to the default warmer lambda role. Ignored if a the role setting is used (defaults to ${service.service}-${stage}-${region}-${warmerName.toLowerCase()}-role)
  • role Role to apply to the warmer lambda (defaults to a custom role with minimal permissions)
  • tags Tag to apply to the generated warmer lambda (defaults to the serverless default tags)
  • vpc The VPC and subnets in which to deploy. Can be any Serverless VPC configuration or be set to false in order to deploy the warmup function outside of a VPC (defaults to the vpc in the provider)
  • memorySize The memory to be assigned to the warmer lambda (defaults to 128)
  • events The event that triggers the warmer lambda. Can be any Serverless event (defaults to - schedule: rate(5 minutes))
  • architecture The instruction set to use for the lambda (defaults to x86_64)
  • package The package configuration. Can be any Serverless package configuration (defaults to { individually: true, patterns: ['!**', '.warmup/${warmerName}/**'] })
  • timeout How many seconds until the warmer lambda times out. (defaults to 10)
  • environment Can be used to set environment variables in the warmer lambda. You can also unset variables configured at the provider by setting them to undefined. However, you should almost never have to change the default. (defaults to unset all package level environment variables. )
  • tracing Specify whether to enable/disable tracing at the function level. When tracing is enabled, warmer functions will use NPM to install the X-Ray client and use it to trace requests (It takes any of the values supported by serverless as boolean, Activeor PassThrough and defaults to the provider-level setting)
  • verbose If set to false, it disables the console.logs placed on this warmer lambda (defaults to true)
  • logRetentionInDays Set the retention time in days for the log group associated to this warmer lamba. Can be any of the values specified in the AWS documentation.
  • prewarm If set to true, it warms up your lambdas right after deploying (defaults to false)

There are also some options which can be set under custom.warmup.<yourWarmer> to be applied to all your lambdas or under yourLambda.warmup.<yourWarmer> to overridde the global configuration for that particular lambda. Keep in mind that in order to configure a warmer at the function level, it needed to be previously configured at the custom section or the pluging will error.

  • enabled Whether your lambda should be warmed up or not. Can be a boolean, a stage for which the lambda will be warmed up or a list of stages for which your lambda will be warmed up (defaults to false)
  • alias Alias qualifier to use when invoking the functions. Necessary, for example, when this plugin is combined with the serverless-plugin-canary-deployments serverless canary plugin (warmup should always be declared after).
  • clientContext Custom data to send as client context to the data. It should be an object where all the values are strings. (defaults to the payload. Set it to false to avoid sending any client context custom data)
  • payload The payload to send to your lambda. This helps your lambda identify when the call comes from this plugin (defaults to { "source": "serverless-plugin-warmup" })
  • payloadRaw Whether to leave the payload as-is. If false, the payload will be stringified into JSON. (defaults to false)
  • concurrency The number of times that each of your lambda functions will be called in parallel. This can be used in a best-effort attempt to force AWS to spin up more parallel containers for your lambda. (defaults to 1)
custom:
  warmup:
    default:
      enabled: true # Whether to warm up functions by default or not
      folderName: '.warmup' # Name of the folder created for the generated warmup 
      cleanFolder: false
      memorySize: 256
      name: warmer-default
      roleName: my-custom-role
      role: WarmupRole
      tags:
        Project: foo
        Owner: bar 
      vpc: false
      events:
        - schedule: 'cron(0/5 8-17 ? * MON-FRI *)' # Run WarmUp every 5 minutes Mon-Fri between 8:00am and 5:55pm (UTC)
      package:
        individually: true
        patterns:
          - '!../**'
          - '!../../**'
          - ./**
      timeout: 20
      tracing: true
      verbose: false # Disable the logs
      logRetentionInDays: 14
      prewarm: true # Run WarmUp immediately after a deploymentlambda
      clientContext:
        source: my-custom-source
        other: '20'
      payload: 
        source: my-custom-source
        other: 20
      payloadRaw: true # Won't JSON.stringify() the payload, may be necessary for Go/AppSync deployments
      concurrency: 5 # Warm up 5 concurrent instances
    
functions:
  myColdfunction:
    handler: 'myColdfunction.handler'
    events:
      - http:
          path: my-cold-function
          method: post
    warmup:
      default:
        enabled: false

  myLowConcurrencyFunction:
    handler: 'myLowConcurrencyFunction.handler'
    events:
      - http:
          path: my-low-concurrency-function
          method: post
    warmup:
      default:
        clientContext:
          source: different-source-only-for-this-lambda
        payload:
          source: different-source-only-for-this-lambda
        concurrency: 1
   
  myProductionOnlyFunction:
    handler: 'myProductionOnlyFunction.handler'
    events:
      - http:
          path: my-production-only-function
          method: post
    warmup:
      default:
        enabled: prod
      
   myDevAndStagingOnlyFunction:
    handler: 'myDevAndStagingOnlyFunction.handler'
    events:
      - http:
          path: my-dev-and-staging-only-function
          method: post
    warmup:
      default:
        enabled:
          - dev
          - staging

Runtime Configuration

Concurrency can be modified post-deployment at runtime by setting the warmer lambda environment variables.
Two configuration options exist:

  • Globally set the concurrency for all lambdas on the stack (overriding the deployment-time configuration):
    Set the environment variable WARMUP_CONCURRENCY
  • Individually set the concurrency per lambda
    Set the environment variable WARMUP_CONCURRENCY_YOUR_FUNCTION_NAME. Must be all uppercase and hyphens (-) must be replaced with underscores (_). If present for one of your lambdas, it overrides the global concurrency setting.

Networking

The WarmUp function use normal calls to the AWS SDK in order to keep your lambdas warm. If you set up at the provider level or the warmer confir level that the wamer function should be deployed into into a VPC subnet you need to keep in mind a couple of things:

  • If the subnet is public, access to the AWS API should be allowed by Internet Gateway.
  • If the subnet is private, a Network Address Translation (NAT) gateway is needed so the warmers can connect to the AWS API.
  • In either case, the security group and the network ACLs need to allow access from the warmer to the AWS API.

Since the AWS SDK doesn't provide any timeout by default, this plugin uses a default connection timeout of 1 second. This is to avoid the issue of a lambda constantly timing out and consuming all its allowed duration simply because it can't connect to the AWS API.

Permissions

WarmUp requires permission to be able to invoke your lambdas.

If no role is provided at the custom.warmup level, each warmer function gets a default role with minimal permissions allowing the warmer function to:

  • Create its log stream and write logs to it
  • Invoke the functions that it should warm (and only those)
  • Create and attach elastic network interfaces (ENIs) which is necessary if deploying to a VPC

The default role for each warmer looks like:

resources:
  Resources:
    WarmupRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: WarmupRole
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: WarmUpLambdaPolicy
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
               # Warmer lambda to send logs to CloudWatch
                - Effect: Allow
                  Action:
                    - logs:CreateLogGroup
                    - logs:CreateLogStream
                  Resource: 
                    - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${warmer.name}:*
                - Effect: Allow
                  Action:
                    - logs:PutLogEvents
                  Resource: 
                    - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${warmer.name}:*:*
                # Warmer lambda to invoke the functions to be warmed
                - Effect: 'Allow'
                  Action:
                    - lambda:InvokeFunction
                  Resource:
                    - !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${fn1.name}
                    - !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${fn2.name}
                    # and one more row for each function that must be warmed up by the warmer
                # Warmer lambda to manage ENIS (only needed if deploying to VPC, https://docs.aws.amazon.com/lambda/latest/dg/vpc.html)
                - Effect: Allow
                  Action:
                    - ec2:CreateNetworkInterface
                    - ec2:DescribeNetworkInterfaces
                    - ec2:DetachNetworkInterface
                    - ec2:DeleteNetworkInterface
                  Resource: "*"

The permissions can also be added to all lambdas using setting the role to IamRoleLambdaExecution and setting the permissions in iamRoleStatements under provider (see https://serverless.com/framework/docs/providers/aws/guide/functions/#permissions):

provider:
  name: aws
  runtime: nodejs20.x
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 'lambda:InvokeFunction'
      Resource:
      - !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${self:service}-${opt:stage, self:provider.stage}-*
custom:
  warmup:
    default:
      enabled: true
      role: IamRoleLambdaExecution
      architecture: 'arm64'

If setting prewarm to true, the deployment user used by the AWS CLI and the Serverless framework also needs permissions to invoke the warmer.

On the function side

When invoked by WarmUp, your lambdas will have the event source serverless-plugin-warmup (unless otherwise specified using the payload option):

{
  "Event": {
    "source": "serverless-plugin-warmup"
  }
}

To minimize cost and avoid running your lambda unnecessarily, you should add an early return call before your lambda logic when that payload is received.

Javascript

Using the Promise style:

module.exports.lambdaToWarm = async function(event, context) {
  /** Immediate response for WarmUp plugin */
  if (event.source === 'serverless-plugin-warmup') {
    console.log('WarmUp - Lambda is warm!');
    return 'Lambda is warm!';
  }

  // ... function logic
}

Using the Callback style:

module.exports.lambdaToWarm = function(event, context, callback) {
  /** Immediate response for WarmUp plugin */
  if (event.source === 'serverless-plugin-warmup') {
    console.log('WarmUp - Lambda is warm!')
    return callback(null, 'Lambda is warm!')
  }

  // ... function logic
}

Using the context. This could be useful if you are handling the raw input and output streams.

module.exports.lambdaToWarm = async function(event, context) {
  /** Immediate response for WarmUp plugin */
  if (context.custom.source === 'serverless-plugin-warmup') {
    console.log('WarmUp - Lambda is warm!');
    return 'Lambda is warm!';
  }

  // ... function logic
}

If you're using the concurrency option you might want to add a slight delay before returning on warmup calls to ensure that your function doesn't return before all concurrent requests have been started:

module.exports.lambdaToWarm = async (event, context) => {
  if (event.source === 'serverless-plugin-warmup') {
    console.log('WarmUp - Lambda is warm!');
    /** Slightly delayed (25ms) response 
    	to ensure concurrent invocation */
    await new Promise(r => setTimeout(r, 25));
    return 'Lambda is warm!';
  }

  // ... add lambda logic after
}

Python

You can handle it in your function:

def lambda_handler(event, context):
    # early return call when the function is called by warmup plugin
    if event.get("source") == "serverless-plugin-warmup":
        print("WarmUp - Lambda is warm!")
        return {}

    # ... function logic

Or you could use a decorator to avoid the redundant logic in all your functions:

def skip_execution_if.warmup_call(func):
    def warmup_wrapper(event, context):
      if event.get("source") == "serverless-plugin-warmup":
        print("WarmUp - Lambda is warm!")
        return {}

      return func(event, context)

    return warmup_wrapper

# ...

@skip_execution_if.warmup_call
def lambda_handler(event, context):
    # ... function logic

Java

You can handle it in your function:

public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
  if ("serverless-plugin-warmup".equals(input.get("source"))) {
    System.out.println("WarmUp - Lambda is warm!");
    return ApiGatewayResponse.builder()
        .setStatusCode(200)
        .build();
  }
  
  // ... function logic
}

Ruby

You can handle it in your function:

def handle_request(app:, event:, context:, config: {})
  if event['source'] == 'serverless-plugin-warmup'
    puts 'WarmUp - Lambda is warm!'
    return {} 
  end

  # ... function logic
end

Lifecycle hooks

WarmUp plugin uses 3 lifecycles hooks:

  • warmup:addWarmers:addWarmers: This is where the warmers are added to the service. It runs after:package:initialize.
  • warmup:cleanupTempDir:cleanup: This is where the warmers' temp folders are removed. It runs after:package:createDeploymentArtifacts.
  • warmup:prewarm:start: This is where the warmers are invoked. It runs after:deploy:deploy or when running the command serverless warmup prewarm.
  • warmup:prewarm:end: This is after the warmers are invoked.

Usage

Packaging

WarmUp supports

serverless package

By default, each warmer function is packaged individually and it uses a folder named .warmup/<function_name> to serve as temporary folder during the packaging process. This folder is deleted at the end of the packaging process unless the cleanFolder option is set to false.

If you are doing your own package artifact you can set the cleanFolder option to false and include the .warmup folder in your custom artifact.

Deployment

WarmUp adds package the warmers and add them to your services automatically when you run

serverless deploy

After the deployment, any warmer with prewarm: true is automatically invoked to warm up your functions without delay.

Prewarming

Apart from prewarming automatically after each deployment. You can invokes a warmer after a sucessful deployment to warm up functions using:

serverless warmup prewarm -warmers <warmer_name>

The warmers flag takes a comma-separated list of warmer names. If it's nor provided, all warmers with prewarm set to true are invoked.

Migrations

v5.X to v6.X

Removed include/exclude in favour of patterns

From Serverless 2.32.0 the patterns option is the recommended approach to include/exclude files from packaging. In version 3.X, the include and exclude are removed.

This plugin applies the same philosophy.

What used to be:

custom:
  warmup:
    default:
      enabled: 'prod'
      package:
        individually: true
        exclude: '../**',
        include: 'myFolder'

is the same as

custom:
  warmup:
    default:
      enabled: 'prod'
      package:
        individually: true
        patterns:
          - '!../**',
          - 'myFolder'

v4.X to v5.X

Support multiple warmer

Previous versions of the plugin only support a single warmer which limited use cases like having different concurrentcies in different time periods. From v5, multiple warmers are supported. The warmup field in the custom section or the function section, takes an object where each key represent the name of the warmer and the value the configuration which is exactly as it used to be except for the changes listed below.

custom:
  warmup:
    enabled: true
    events:
      - schedule: rate(5 minutes)

have to be named, for example, to default:

custom:
  warmup:
    default:
      enabled: true
      events:
        - schedule: rate(5 minutes)

Change the default temporary folder to .warmup

Previous versions of the plugin named the temporary folder to create the warmer handler _warmup. It has been renamed to .warmup to better align with the serverless framework and other plugins' behaviours.

Remembe to add .warmup to your git ignore.

Default to Unqualified alias

Previous versions of the plugin used the $LATEST alias as default alias to warm up if no alias was provided. From v5, the unqualified alias is the default. You can still use the $LATEST alias by setting it using the alias option.

custom:
  warmup:
    default:
      alias: $LATEST

Automatically exclude package level includes

Previous versions of the plugin exclude everything in the service folder and include the .warmup folder. This caused that any files that you include to the service level were also included in the plugin specially if you include ancestor folders (like ../**) From v5, all service level include are automatically excluded from the plugin. You still override this behaviour using the package option.

Removed shorthand

Previous versions of the plugin supported replacing the configuration by a boolean, a string representing a stage or an array of strings representing a list of stages. From v5, this is not supported anymore. The enabled option is equivalent.

custom:
  warmup: 'prod'

is the same as

custom:
  warmup:
    default: # Name of the warmer, see above
      enabled: 'prod'

Removed legacy options

The following legacy options have been completely removed:

  • default Has been renamed to enabled
  • schedule schedule: rate(5 minutes) is equivalent to events: - schedule: rate(5 minutes).
  • source Has been renamed to payload
  • sourceRaw Has been renamed to payloadRaw

Automatically creates a role for the lambda

If no role is provided in the custom.warmup config, a default role with minimal permissions is created for each warmer. See "Permissions" section

Support Tracing

If tracing is enabled at the provider level or at the warmer config level, the X-Ray client is automatically installed and X-Ray tracing is enabled.

Add a 1 second connect timeout to the AWS SDK

See the "Networking" section for more details.

Cost

You can check the Lambda pricing and CloudWatch pricing or can use the AWS Lambda Pricing Calculator to estimate the monthly cost

Example

If you have a single warmer and want to warm 10 functions, each with memorySize = 1024 and duration = 10, using the default settings ($0.0000166667 for every GB-second) and ignoring the free tier:

  • WarmUp: runs 8640 times per month = $0.0
  • 10 warm lambdas: each invoked 8640 times per month = $0.3
  • Total = $0.3

CloudWatch costs are not consdiered in this example.

Contribute

Help us making this plugin better and future-proof.

  • Clone the code
  • Install the dependencies with npm install
  • Create a feature branch git checkout -b new_feature
  • Add your code and add tests if you implement a new feature
  • Validate your changes npm run lint and npm test (or npm run test-with-coverage)

License

This software is released under the MIT license. See the license file for more details.

Acknowledgements

Thanks to Fidel who initially developed this plugin.

serverless-plugin-warmup's People

Contributors

abetomo avatar batovpasha avatar carlovsk avatar cjnoname avatar codemoomba avatar davisonr avatar dependabot[bot] avatar ejwilburn avatar goncaloneves avatar ipherian avatar jiangzhuo avatar johndww avatar juanjodiaz avatar jussisaurio avatar kf6kjg avatar khaledosman avatar lantrix avatar mdial89f avatar mikeputnam avatar mnightingale avatar murtyjones avatar netizen01 avatar noorts avatar offensivebias-08-145 avatar ojongerius avatar patrickjs avatar rafaelrpinto avatar richarddd avatar tamasbjn avatar trentbartlem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

serverless-plugin-warmup's Issues

Pricing on the Readme seems off

So I was just going through the Readme, on the pricing example if I'm reading it right it's saying 8640 times a month, 1024 memory and a 10 second run time, is it 10 seconds because it's assumed cold containers?

Also I can't seem to find a way to make it add up to $14.58 - on the pricing calculator if I do those number of executions, 1024 memory and 10,000ms execution time I end up on $1.44.

It's no biggie I can do PR for some pricing examples but I was just trying to understand the math that was used please? I think someone may done 100,000ms rather than 10,000 for a 10 second start by mistake?

Serverless error attempting to delete `warmUpPlugin` function

When using a custom name, I encountered a serverless error in my TravisCI build's deploy section.

Serverless was trying to remove/apply x-ray settings to a lambda with a warmUpPlugin suffix on the lambda ARN. I was able to work around this by manually creating a lambda with that name, but I believe this to be a bug.

Perhaps related to this line: https://github.com/FidelLimited/serverless-plugin-warmup/blob/master/src/index.js#L232

Warm up settings:

  warmup:
    memorySize: 128
    name: '${self:service}-${opt:stage}-lambda-warmup'

Companion Middy middleware

Hi,

I have created a Middy middleware to be used with this plugin. You can find it here. With the middleware you won't have to manually handle the warmup request.

Thanks for creating this plugin, and I hope somebody finds my middleware useful!

Alex

Unable to import module '_warmup/index'

Hi. So I installed the plugin: ([email protected] for [email protected])

using

plugins:
  - serverless-plugin-warmup

custom:
  warmup:
    prewarm: true
    schedule: 'rate(10 minutes)'

provider:
  # ...  
  iamRoleStatements:
    - Effect: Allow
      Action:
        - lambda:InvokeFunction
      Resource:
      - Fn::Join:
        - ':'
        - - arn:aws:lambda
          - Ref: AWS::Region
          - Ref: AWS::AccountId
          - function:${self:service}-${opt:stage, self:provider.stage}-*
  # ...
  • deployment works
  • lambda is created and named {service}-{environment}warmup-plugin (not the same as README.md states, but close enough)
  • cloudwatch timer is created successfully
  • When the warmup lambda is triggered, it fails with various flavours of
Unable to import module '_warmup/index': Error
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)

None of the other functions in my project are Node, so I'm not sure whether there's a step missing from the setup that's causing this.

Incompatibility with serverless-plugin-typescript

Every time I try and package I get:

{ file: undefined,
  start: undefined,
  length: undefined,
  messageText: "File '_warmup/index.ts' not found.",
  category: 1,
  code: 6053,
  reportsUnnecessary: undefined }

  Type Error ---------------------------------------------

  Cannot read property 'getLineAndCharacterOfPosition' of undefined

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Stack Trace --------------------------------------------

TypeError: Cannot read property 'getLineAndCharacterOfPosition' of undefined
    at allDiagnostics.forEach.diagnostic (/Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/src/typescript.ts:72:47)
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (/Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/src/typescript.ts:68:18)
    at Generator.next (<anonymous>)
    at /Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/dist/src/typescript.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/dist/src/typescript.js:3:12)
    at Object.run (/Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/dist/src/typescript.js:62:12)
    at TypeScriptPlugin.<anonymous> (/Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/src/index.ts:132:42)
    at Generator.next (<anonymous>)
    at /Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/dist/src/index.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/dist/src/index.js:3:12)
    at TypeScriptPlugin.compileTs (/Users/dsmiley/workspace/mfour-survey-service/node_modules/serverless-plugin-typescript/dist/src/index.js:103:16)
    at BbPromise.reduce (/Users/dsmiley/nvm/versions/node/v11.4.0/lib/node_modules/serverless/lib/classes/PluginManager.js:391:55)
From previous event:
    at PluginManager.invoke (/Users/dsmiley/nvm/versions/node/v11.4.0/lib/node_modules/serverless/lib/classes/PluginManager.js:391:22)
    at PluginManager.run (/Users/dsmiley/nvm/versions/node/v11.4.0/lib/node_modules/serverless/lib/classes/PluginManager.js:422:17)
    at variables.populateService.then.then (/Users/dsmiley/nvm/versions/node/v11.4.0/lib/node_modules/serverless/lib/Serverless.js:157:33)
    at processImmediate (timers.js:632:19)
    at process.topLevelDomainCallback (domain.js:120:23)
From previous event:
    at Serverless.run (/Users/dsmiley/nvm/versions/node/v11.4.0/lib/node_modules/serverless/lib/Serverless.js:144:8)
    at serverless.init.then (/Users/dsmiley/nvm/versions/node/v11.4.0/lib/node_modules/serverless/bin/serverless:44:28)

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information -----------------------------
     OS:                     darwin
     Node Version:           11.4.0
     Serverless Version:     1.34.1

I've spent a day and half combing through your issues and going through step by step guide with no joy. Any help is greatly appreciated:

iamRoleStatements not allowing invocation

I'm receiving the following error on every attempted invoke:

Warm Up Invoke Error: auth-service-dev-myFunctionName { AccessDeniedException: User: 
arn:aws:sts::[redacted]:assumed-role/auth-service-dev-us-east-1-lambdaRole/auth-service-
dev-warmup-plugin is not authorized to perform: lambda:InvokeFunction on resource: 
arn:aws:lambda:us-east-1:[redacted]:function:auth-service-dev-myFunctionName

My config looks like this:

custom:
  warmup:
    folderName: '_warmup' # Name of the folder created for the generated warmup
    cleanFolder: false
    memorySize: 128
    schedule: 'cron(0/5 14-4 ? * MON-SUN *)' # Run WarmUP every 5 minutes Mon-Sun between 8:00am and 10:55pm (UTC)
    timeout: 20
    prewarm: true # Run WarmUp immediately after a deployment
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 'lambda:InvokeFunction'
      Resource: "*"

Is there something obvious I'm missing about setting up permissions for the warmup plugin?

Error upon deployment

Error in the logs

module initialization error
TypeError

sls version: 1.32.0
[email protected]

This was working before i upgraded to babel7

service: adcentre-invoices
frameworkVersion: ">=1.2.0 <2.0.0"

plugins:
  - serverless-webpack # Use serverless-webpack plugin to transpile ES6/ES7
  - serverless-offline-ssm
  - serverless-offline
  - serverless-apigw-binary
  - serverless-domain-manager
  - serverless-plugin-warmup

provider:
  name: aws
  runtime: nodejs8.10
  region: ap-southeast-2
  warmup:
    folderName: "_warmup" # Name of the folder created for the generated warmup
    cleanFolder: true
    memorySize: 256
    name: ${self:custom.warmupLambdaName}
    schedule: "rate(5 minutes)" # Run WarmUP every 5 minutes
    timeout: 20
    prewarm: true # Run WarmUp immediately after a deployment
  apigwBinary:
    types: #list of mime-types
      # - 'image/jpeg'
      # - 'text/html'
      - "application/pdf"
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true
    packager: "npm"
    package:
      individually: true #Webpack compiles and optimizes each function individually,
      # removing unnecessary imports and reducing code sizes significantly

webpack.config.js

const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
const Dotenv = require("dotenv-webpack");

module.exports = {
  entry: slsw.lib.entries,
  target: "node",
  // Generate sourcemaps for proper error messages
  devtool: "source-map",
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  mode: slsw.lib.webpack.isLocal ? "development" : "production",
  optimization: {
    // We no not want to minimize our code.
    minimize: false
  },
  performance: {
    // Turn off size warnings for entry points
    hints: false
  },
  plugins: [new Dotenv()],
  // Run babel on all .js files and skip those in node_modules
  module: {
    rules: [
      {
        test: /\.js$/,
        include: __dirname,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"]
          }
        }
      }
    ]
  }
};

devDep

  "devDependencies": {
    "@babel/core": "^7.1.0",
    "@babel/plugin-transform-runtime": "^7.1.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/register": "^7.0.0",
    "@pact-foundation/pact": "5.9.1",
    "@pact-foundation/pact-node": "^6.19.4",
    "artillery": "^1.6.0-22",
    "aws-sdk": "2.315.0",
    "babel-loader": "^8.0.0",
    "babel-plugin-istanbul": "5.0.1",
    "babel-plugin-source-map-support": "2.0.1",
    "body-parser": "^1.18.3",
    "chai": "4.1.2",
    "commitizen": "^2.10.1",
    "cors": "^2.8.4",
    "cross-env": "5.2.0",
    "cz-conventional-changelog": "^2.1.0",
    "dotenv": "^6.0.0",
    "eslint": "^5.6.0",
    "eslint-config-airbnb-base": "^13.1.0",
    "eslint-config-prettier": "^3.0.1",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-prettier": "^2.6.2",
    "express": "^4.16.3",
    "helmet": "^3.13.0",
    "husky": "0.14.3",
    "lint-staged": "7.3.0",
    "mocha": "5.2.0",
    "mocha-lcov-reporter": "1.3.0",
    "nock": "^10.0.0",
    "nodemon": "^1.18.3",
    "npm-run-all": "^4.1.3",
    "nyc": "^13.0.1",
    "prettier": "1.14.3",
    "prettier-eslint": "^8.8.2",
    "renovate-config-seek": "^0.3.0",
    "rimraf": "2.6.2",
    "serverless": "^1.30.0",
    "serverless-apigw-binary": "^0.4.4",
    "serverless-domain-manager": "^2.6.0",
    "serverless-offline": "^3.25.9",
    "serverless-offline-ssm": "^1.1.0",
    "serverless-plugin-warmup": "^3.6.1-rc.1",
    "serverless-webpack": "5.2.0",
    "sinon": "^6.0.0",
    "sinon-chai": "^3.0.0",
    "webpack": "^4.19.1",
    "webpack-node-externals": "1.7.2"
  }

babelrc

{
  "comments": false,
  "plugins": ["source-map-support", "@babel/plugin-transform-runtime"],
  "presets": [
    [
      "@babel/preset-env",
      {
        "debug": false,
        "targets": {
          "node": "8.10"
        },
        "shippedProposals": true
      }
    ]
  ],
  "env": {
    "test": {
      "plugins": ["istanbul"]
    }
  }
}

Error when deploying a package

The plugin seems to work fine and as expected if I run a serverless deploy to package and deploy everything in one step. However, on our build server we split this in two distinct steps: build and deployment. During the build we run a serverless package and then, once we want deploy, a serverless deploy --package=... using the already packaged archive. This worked fine in the 2.1.0 release we used before, but seems to be broken in 3.0.2 now.

The following exception in thrown:

TypeError: Cannot read property 'prewarm' of undefined
    at WarmUP.afterDeployFunctions (/var/atlassian/application-data/bamboo/xml-data/build-dir/100040705-100106241/node_modules/serverless-plugin-warmup/src/index.js:80:20)
    at BbPromise.reduce (/var/atlassian/application-data/bamboo/xml-data/build-dir/100040705-100106241/node_modules/serverless/lib/classes/PluginManager.js:254:55)
From previous event:
    at PluginManager.invoke (/var/atlassian/application-data/bamboo/xml-data/build-dir/100040705-100106241/node_modules/serverless/lib/classes/PluginManager.js:254:22)
    at PluginManager.run (/var/atlassian/application-data/bamboo/xml-data/build-dir/100040705-100106241/node_modules/serverless/lib/classes/PluginManager.js:273:17)
    at variables.populateService.then (/var/atlassian/application-data/bamboo/xml-data/build-dir/100040705-100106241/node_modules/serverless/lib/Serverless.js:105:33)
    at runCallback (timers.js:666:20)
    at tryOnImmediate (timers.js:639:5)
    at processImmediate [as _immediateCallback] (timers.js:611:5)
From previous event:
    at Serverless.run (/var/atlassian/application-data/bamboo/xml-data/build-dir/100040705-100106241/node_modules/serverless/lib/Serverless.js:92:74)
    at serverless.init.then (/var/atlassian/application-data/bamboo/xml-data/build-dir/100040705-100106241/node_modules/serverless/bin/serverless:30:50)

There's no specific configuration in our serverless.yml other than warmup: true for a couple of functions.

This issue was most likely introduced due to new pre-warm feature in @juanjoDiaz's PR #16

Lambda warmup not waming up the function properly

I installed the warmup plugin to my project and just realized that it is not working properly.

The warmup-lambda is peroperly executing every 5 minutes:
image

The logs indicate a successful execution:

START RequestId: 3b04bd5d-7de1-11e8-8fdf-7b05371b3361 Version: $LATEST
2018-07-02T10:18:14.729Z	3b04bd5d-7de1-11e8-8fdf-7b05371b3361	Warm Up Start
2018-07-02T10:18:15.187Z	3b04bd5d-7de1-11e8-8fdf-7b05371b3361	Warm Up Invoke Success: glypo-dev-captureTransaction { StatusCode: 200, Payload: '"Lambda is warm!"' }
2018-07-02T10:18:15.187Z	3b04bd5d-7de1-11e8-8fdf-7b05371b3361	Warm Up Finished with 0 invoke errors

But the function monitoring on captureTransaction doesn't log an invocation:
image

Also the end to end test is still showing following load times on sequential execution:

Received: 4846
Received: 1537
Received: 1627
Received: 1580

Unnecessary error message when pre-warming

This is a relatively minor issue, but currently some unnecessary messages are displayed when setting pre-warm to true:

Serverless: WarmUP: Pre-warming up your functions
Serverless: WarmUp: Error while pre-warming functions

This error occurs if pre-warm is true, warmup: default is set to certain stages, and we're deploying to a stage not specified to be warmed. I.e. serverless.yml looks like this:

custom:  
  warmup:
     prewarm: true
     default:   
       - staging
       - prod

And then we deploy to dev.

Circular dependency when using package: artifact

When we build a zip of our project we need the _warmup directory to exist with the correct configurations so that we can include it in the zip to be deployed. This directory seems to get created only when running the "sls package" command, which in turn requires our zip file to exist. It would be nice if there was a way to generate the contents of the _warmup directory by some other means, so that I can create this, then package everything into my deployable zip, and then use "sls deploy".

I can't see a decent workaround at the moment. My deployment script is currently running "sls package" before anything else, and ignoring the error which is caused by the package artifact not having already been built.

"Enabled" option not working (warmer not firing)

I know I 100% setup something wrong, but cannot figure it out for the life of me. Here is my YML

service: policy

provider:
  name: aws
  runtime: nodejs8.10
  environment: ${file(env.yml):${opt:stage, self:provider.stage}}
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 'lambda:InvokeFunction'
      Resource: "*"

plugins:
  - serverless-offline
  - serverless-plugin-warmup

custom:
  warmup:
    enabled: true
    schedule: rate(1 minutes)
    prewarm: true

functions:
  withCustomer:
    handler: handler.withCustomer
    events:
      - http:
          path: /withCustomer
          method: POST
          cors: true
          warmup: true

When I deploy, I immediately see Serverless: WarmUP: no lambda to warm and at the end, I get the following:

functions:
  withCustomer: policy-staging-withCustomer
Serverless: WarmUP: Pre-warming up your functions
Serverless: WarmUp: Error while pre-warming functions

I check the logs, but can't see anything when I search for "warm" or any tags I've tried as well. I know I'm doing something dumb, but can't see it.

Instructions on getting warmup to work with serverless-webpack

I preface this with the fact that I'm a webpack newbie so this may be suboptimal.

If using the serverless-webpack plugin then you need to make some changes to webpack.config.js to get serverless-plugin-warmup to work.

  1. Add a new chunk for warmup with the specific path that the warmup plugin uses.
  2. Add an output section as per above. This ensures that the warmup handler is appears in the bundle at the same path as it would have originally.

For example:

  entry: {
    handler: [/* possibly other entry points like babel-polyfill, ... */ './handler.js'],
    '_warmup/index': './_warmup/index.js',
  },
  output: {
    libraryTarget: 'commonjs',  // <- as per serverless-webpack README
    path: '.webpack',
    filename: '[name].js',
  },

An issue with this setup is that serverless webpack invoke no longer works because _warmup does not exist then.

Another potential issue is the reliance on the _warmup/index.js path not changing.

Add "cost" command to estimate costs based on the current configuration

awesome plugin!

it would be cool to be able to get a cost estimate of the sum of the warmups scheduled, e.g. with serverless warmup cost

idk, how much this would save, but log group pre-processing before a function call can save the need for a warmup call - process the latest log group, check the request id time, and then decide whether to issue warmup call

Feature Request: Allow warming up >1 function instances

Thanks for the plugin! Currently the only limitation which stops me from using it instead of custom solution is that it warms up only 1 function, but I want to have ~ 10 warm functions w/ VPC connections, so it can handle a sudden burst.

What do you think? Is this a unique use case which doesn't belong to this plugin or you can consider this feature?

Add tests

Related to #15

It's a bit of a pain in the neck to work on the plugin and have to test all the cases manually.
Some unit or integration tests will help a lot.

I don't have time for this at the moment. So just leaving here in case we can get a champion to contribute 🙂

Unable to import module

Hi,

the plugin does not work for me, from CloudWatch Logs:

Unable to import module '_warmup/index': Error at Function.Module._resolveFilename (module.js:469:15) at Function.Module._load (module.js:417:25) at Module.require (module.js:497:17) at require (internal/module.js:20:19)
Unable to import module '_warmup/index': Error
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)

How do I tell if it's working?

Super basic question. I followed everything in the readme; set all of my functions to have warmup: true, serverless-plugin-warmup is in my serverless.yml's plugins, as well as this definition:

  warmup:
    folderName: '_warmup' # Name of the folder created for the generated warmup 
    cleanFolder: false
    memorySize: 256
    name: 'make-them-pop'
    schedule: 'cron(0 0/1 * 1/1 * ? *)' # Run WarmUP every 5 minutes Mon-Fri between 8:00am and 5:55pm (UTC)
    timeout: 20
    prewarm: true # Run WarmUp immediately after a deployment

(trying to run it every minute locally for debugging purposes).

When I run my offline/local serverless project, I don't see any console logs relating to Warmup, so have no idea if/when the service is running. I don't see a _warmup folder anywhere, so maybe this is a sign it's not working?

How can I test this plugin?

Project is going stale!

@goncaloneves PRs are pilling up and releases take forever.
Do you want me to start getting them merged?
If you give me permission to npm I can also release after merging them.

Enable Warmup function could be specified outside of the node module.

As an organisation, I NEED to be able to write my own warmup function
SO THAT I can write more complex business logic and attach other event sources.

I think this would simply be a pointer in the yaml that packages a function external to the serverless-plugin-warmup.

The reason this could be useful is shown in my comment, specifically the bit about SNS sources.

Hangs up on remove or deploy when changing .yaml

I'am having problems when Im updating my .yaml for serverless-plugin-warmup.

...
plugins:
  - serverless-plugin-warmup
custom:
  warmup:
    name: webhook-warmup-plugin
    prewarm: true
...
functions:
  webhook:
    handler: handler.webhook
    warmup: true
    events:
      - http:
          path: webhook
          method: get

Before adding that custom all are working. Then I tried to sls deploy but it hangs up. What I did is that I stopped the deploy then tried to sls remove. Then it gave an error like

Stack:arn:aws:cloudformation:us-west-2:124176118271:stack/webhook-dev/5363ea00-11e5-11e8-a57b-50a68a0e32f2 is in UPDATE_COMPLETE_CLEANUP_IN_PROGRESS state and can not be updated.

This happened to me like twice when changing some config like the VPC or the custom.

Note:
Also the first time I encounter this problem I deleted my s3 bucket for my lambda then deleted the cloud formation. Your help is much appreciated. Thanks.

Warm Lambda not being utilized.

I recognize that this is slightly out of scope for what this library accomplishes, but I'm noticing that even with successful warmups being executed every 5 minutes, my Lambda containers tend not to be reused. I'm regularly seeing startup times of 2-3 seconds when calling from a different event source (e.g. going thru API Gateway).

Seems from this answer that it's common to see a warm Lambda container not being reused when being called from a different event source than the one used to warm the Lambda.

Just wondering if this is a common occurrence and if there is any way to increase the likelihood of container reuse when calling from a different even source.

Handle multiple schedules?

I know that this works:

custom:
  warmup:
    schedule: 'rate(10 minutes)'

but would it be possible to trigger from multiple schedules?

e.g.

custom:
  warmup:
    schedule:
      - 'cron(0/10 11-13 ? * MON-FRI *)'
      - 'cron(0/10 17-20 ? * MON-SAT *)'

Enabling warmup only for a specific stage

Hi,

Not an issue so sorry for creating an issue. But I was wondering how can I use this plugin to enable warmup only for a specific stage (production for example).

custom variableSyntax fails to deploy in version 3.6.0-rc.1

with a variableSyntax in serverless.yml set to:

provider:
  variableSyntax: "\\${{([\\s\\S]+?)}}"

Deployments using [email protected] fails with the error:

  Serverless Error ---------------------------------------

  The stack service name "serverless-service-${{env:SERVERLESS_STAGE}}" is not valid. A service name should only contain alphanumeric (case sensitive) and hyphens. It should start with an alphabetic character and shouldn't exceed 128 characters.

The same deployment using [email protected] deploys successfully.

Help Wanted: Facing cold start issue

I have implemented this plugin and still facing cold start issue. My event source is API Gateway.

Note: I am using VPC, and by default lambda function within VPC are kept warm for 15 minutes.

Following is my warmup config:

  warmup:
    default: true
    folderName: '_warmup'
    cleanFolder: true
    memorySize: 128
    name: 'keep-function-warm'
    role: warmup-role
    timeout: 20
    prewarm: true
    concurrency: 5

How can I resolve this?

Feature Request : specify schedule by stages

Hi,

First of all, thanks for the plugin! There is currently a way to activate the warmup only on some stages and that's great. But it could be even nicer to be able to set a configuration per stages (for example if we want different schedule or timeout).

Thx,

Serverless.yml plugin order doesn't work

I need to to apply the plugin after the serverless-plugin-typescript compiles my project, but that doesn't work, the warmup is always applied first, even if it's declared after in my serverless.yml
Problem is that typescript expects an index.ts file instead of index.js inside the _warmup folder

serverless.yml
...
plugins:          
  - serverless-plugin-typescript
  - serverless-plugin-warmup

I fix this adding a custom options typescript: true in the .yml file, then modifying the filePath to index.ts if option's true.

Feature Request : customize event source

I am using java lambda functions with spring-boot that do handle all the serialize / deserialize , so having a dynamic event source that can be set in configuration will help utilize it better.

Enable Travis Builds

In #76 I added the necessary configuration for this repo to work with Travis CI.
However, it seems that I don't have ownership of the project so I can't enable it on the Travis side.

Could some of the admins either bump my privileges (at least until Travis is working) or go to Travis and set up the build?

Strange IAM permission

I'm trying to understand why does this plugin need following permissions?

- ec2:CreateNetworkInterface
- ec2:DescribeNetworkInterfaces
- ec2:DetachNetworkInterface
- ec2:DeleteNetworkInterface

Unable to import module

Hi,

the plugin does not work for me, from CloudWatch Logs:

Unable to import module '_warmup/index': Error at Function.Module._resolveFilename (module.js:469:15) at Function.Module._load (module.js:417:25) at Module.require (module.js:497:17) at require (internal/module.js:20:19)
Unable to import module '_warmup/index': Error
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)

Does it only work if you are using nodejs runtime?

Webpack errors due to Commonjs use

Just getting errors and the fn never runs that it makes. Below are logs for the plugin-warmup function.

Looks like this is the error:

{
  "errorMessage": "callback called with Error argument, but there was a problem while retrieving one or more of its message, name, and stack"
}
20:47:43
START RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283 Version: $LATEST

20:47:44
module initialization error: TypeError

20:47:45
END RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283

20:47:45
REPORT RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283	Duration: 1269.59 ms	Billed Duration: 1300 ms Memory Size: 128 MB	Max Memory Used: 33 MB

20:47:45
module initialization error TypeError

20:48:38
START RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283 Version: $LATEST

20:48:39
module initialization error: TypeError

20:48:39
END RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283

20:48:39
REPORT RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283	Duration: 1162.79 ms	Billed Duration: 1200 ms Memory Size: 128 MB	Max Memory Used: 31 MB

20:48:39
module initialization error TypeError

20:50:42
START RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283 Version: $LATEST

20:50:43
module initialization error: TypeError

20:50:43
END RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283

20:50:43
REPORT RequestId: 1113ea0b-ce60-11e8-9706-b39018c2c283	Duration: 1355.07 ms	Billed Duration: 1400 ms Memory Size: 128 MB	Max Memory Used: 31 MB

20:50:43
module initialization error TypeError

20:52:43
START RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585 Version: $LATEST

20:52:44
module initialization error: TypeError

20:52:44
END RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585

20:52:44
REPORT RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585	Duration: 1541.81 ms	Billed Duration: 1600 ms Memory Size: 128 MB	Max Memory Used: 31 MB

20:52:44
module initialization error TypeError

20:53:47
START RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585 Version: $LATEST

20:53:48
module initialization error: TypeError

20:53:48
END RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585

20:53:48
REPORT RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585	Duration: 1591.97 ms	Billed Duration: 1600 ms Memory Size: 128 MB	Max Memory Used: 32 MB

20:53:48
module initialization error TypeError

20:55:48
START RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585 Version: $LATEST

20:55:49
module initialization error: TypeError

20:55:50
END RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585

20:55:50
REPORT RequestId: c3deca1d-ce60-11e8-ac11-0334b25c9585	Duration: 1485.05 ms	Billed Duration: 1500 ms Memory Size: 128 MB	Max Memory Used: 31 MB

20:55:50
module initialization error TypeError

20:57:43
START RequestId: 76eef019-ce61-11e8-840b-81109a057e28 Version: $LATEST

20:57:44
module initialization error: TypeError

20:57:45
END RequestId: 76eef019-ce61-11e8-840b-81109a057e28```

Plugin timing out without doing anything when running in VPC

Hi,

I'm currently using Serverless 1.13.2.and using serverless-plugin-warmup to warmup my lambdas.

The warmup lambda is correctly invoked every 5 minutes. However, it doesn't actually call any of my lambdas and eventually times out. I've increased the time out to several minutes and it still doesn't call anything and simply times out.

The logs don't tell much either:

START RequestId: 37f7c285-4b45-11e7-85cb-c75ba9915e76 Version: $LATEST
2017-06-07T05:50:33.990Z	37f7c285-4b45-11e7-85cb-c75ba9915e76	Warm Up Start
END RequestId: 37f7c285-4b45-11e7-85cb-c75ba9915e76
REPORT RequestId: 37f7c285-4b45-11e7-85cb-c75ba9915e76	Duration: 10000.97 ms	Billed Duration: 10000 ms Memory Size: 128 MB	Max Memory Used: 32 MB
2017-06-07T05:50:43.982Z 37f7c285-4b45-11e7-85cb-c75ba9915e76 Task timed out after 10.00 seconds

Any hint of what the problem might be?

Feature Request: run a warmup on functions immediately after deployment

Currently if you set the warmup time interval to 5 minutes, and you deploy your Serverless project, the first time a warmup runs will be 5 minutes after the deployment. If you execute your newly deployed Lambda function manually within the first 5 minutes after deployment, it will have a cold start.

Perhaps the plugin could run all the Lambdas from localhost immediately after the ç stack update is finished i.e. after "Serverless: Stack update finished..." in the Serverless logs

ENOENT: no such file or directory, open 'serverless-graphql-apollo/app-backend/.webpack/.serverless/warmUpPlugin.zip'

Hi,
Firstly, thanks for making these plugin. I running into the following error when trying to deploy with the serverless-plugin-warmup enabled.

This is the error message:

yarn run v1.1.0
warning You are using Node "7.10.0" which is not supported and may encounter bugs or unexpected behavior. Yarn supports the following semver range: "^4.8.0 || ^5.7.0 || ^6.2.2 || ^8.0.0"
$ serverless --stage=production deploy
Serverless: WarmUP: setting 2 lambdas to be warm
Serverless: WarmUP: serverless-graphql-apollo-production-graphql
Serverless: WarmUP: serverless-graphql-apollo-production-graphiql
Serverless: Bundling with Webpack...
Time: 1578ms
           Asset     Size  Chunks             Chunk Names
      handler.js  7.32 kB       0  [emitted]  handler
_warmup/index.js  4.13 kB       1  [emitted]  _warmup/index
Serverless: Packing external modules: graphql@^0.10.5, [email protected], babel-core@^6.17.0, babel-polyfill@^6.16.0, graphql-tools@^1.0.0, request@^2.83.0, request-promise@^4.2.2
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Excluding development dependencies...

  Error --------------------------------------------------

  ENOENT: no such file or directory, open '/Users/kristiankyvik/code/serverless-graphql-apollo/app-backend/.webpack/.serverless/warmUpPlugin.zip'

This is my serverless.yml:

service: serverless-graphql-apollo

frameworkVersion: ">=1.21.0 <2.0.0"

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: us-east-1
  environment:
    MLAB_API_KEY: ${file(./serverless.env.yml):${opt:stage}.MLAB_API_KEY}
    HOME: /tmp
    SLS_DEBUG: true

plugins:
  - serverless-plugin-warmup
  - serverless-offline
  - serverless-webpack
  - serverless-delete-loggroups
  
custom:
  serverless-offline:
    port: 4000
    babelOptions:
      presets: ["es2015", "stage-2"]
  webpackIncludeModules: true

functions:
  graphql:
    handler: handler.graphqlHandler
    warmup: true
    events:
    - http:
        path: graphql
        method: post
        cors: true

  graphiql:
    handler: handler.graphiqlHandler
    warmup: true
    events:
    - http:
        path: graphiql
        method: get
        cors: true

And this is my webpack config:

const path = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies
const nodeExternals = require('webpack-node-externals');
// eslint-disable-next-line import/no-extraneous-dependencies
const slsw = require('serverless-webpack');

module.exports = {
  entry: slsw.lib.entries,
  target: 'node',
  externals: [nodeExternals()],
  module: {
    rules: [{
      test: /\.js$/,
      use: [
        'imports-loader?graphql',
        {
          loader: 'babel-loader',
          options: {
            presets: ['es2015'],
          },
        },
      ],
    }],
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js',
  },
};

Please let me know if you guys any ideas of how I can fix this.

Support serverless-aws-alias plugin

Overview

The serverless-aws-alias plugin adds support for function aliases to the Serverless framework, i.e. a service can be deployed to multiple aliases within a stage.

The plugin works perfectly together with the warmup plugin. The warmup lambdas are aliased correctly and also the created CW event rule trigger calls the correct aliased functions. It is even possible to deploy differently configured warmup lambdas into one stage.

Sample deployed CW Event:
image

The only thing that does not work with the plugin combination is, that the warmup lambda itself calls the functions without any Qualifier (i.e. alias) specified. So the deployed warmup lambda calls the $LATEST version of any aliased lambda instead of the aliased version.

Solution

The alias plugin sets the environment variable SERVERLESS_ALIAS to the alias the function is deployed to. To fix the issue, the warmup code just should set the alias is present and fall back to $LATEST otherwise.

When testing a fix, the warmup plugin must precede the alias plugin in the service definition! I documented how to add the warmup plugin correctly in my README in the Interoperability section.

Warming up all lambdas with custom.warmup.enable = true

Im trying to configure two lambdas to warm up, but the plug in doesn't detect them, I'm getting:

Serverless: WarmUP: no lambda to warm
Serverless: Installing requirements of requirements.txt in .serverless...

with this configuration:

custom:
  stage: ${opt:stage, self:provider.stage}
  lambdaMetricsTableName: ${self:provider.stage}-lambda-metric
  tableThroughputs:
    prod: 50
    dev: 50
    default: 5
  tableThroughput: ${self:custom.tableThroughputs.${self:custom.stage}, self:custom.tableThroughputs.default}
  pythonRequirements:
    dockerizePip: non-linux
  warmup:
    enabled: false
    timeout: 20
    prewarm: true

functions:
  check-pax-availability:
    handler: src/check_availability.run
  check-pax-availability-intervals:
    handler: src/check_availability_SAT_rotation_interval.run
    memorySize: 1024
    warmup:
      enabled: true
      concurrency: 500
  check-available-times:
    handler: src/check_available_times.run
    memorySize: 1024
    warmup:
      enabled: true
      concurrency: 5
  auto-assign-tables:
    handler: src/auto_assign_tables.run
  layout-generation-unique-product:
    handler: src/layouts_generation_utils.run

Tags for warmup lambda function

It would be great if we can add tags to warmup lambda function.
like this :

warmup:
  cleanFolder: false
  memorySize: 256
  name: 'sample_warmup'
  schedule: 'rate(3 minutes)'
  timeout: 20
  prewarm: true
  folderName: '_warmup'
  tags: # Function specific tags
    Project: sampleproject
    Owner: foo bar
    Environment: dev

Getting 500 error due to no mongo connection

When using this plugin for some reason it breaks my database connection. Any ideas why?

{"error":{"name":"MongoError","message":"no connection available"}}

I use the following function to connect to mongo before running my lambda functions.

const mongoose = require('mongoose');

mongoose.Promise = global.Promise;
let cachedDB = null;

module.exports = fn => (...args) => {
  const [, context] = args;

  context.callbackWaitsForEmptyEventLoop = false;

  if (cachedDB && cachedDB.readyState != 0 && cachedDB.readyState != 3) {
    fn(...args);
  } else {
    mongoose.connect(process.env.MONGO_URI);

    mongoose.connection.on('error', err => {
      console.log('Connection Error');
      console.log(err);
    });

    mongoose.connection.once('open', () => {
      cachedDB = mongoose.connection;
      fn(...args);
    });
  }
};

The warmup lambda function not created

I recently came across this plugin and I wanted to try it out but I'm having an issue with getting it to work. Basically when I do SLS deploy the scheduled warm lambda function is not created as part of the deploy and consequently the other lambda functions that I wanted to keep warm are not invoked. I'm currently running [email protected] I initially installed the latest version and encountered an issue mentioned here Error when deploying a package hence I downgraded to version 2.1.0-rc.1; am I missing anything here?

inject into stack instead living separately

if this function were injected into serverless.yml during preprocessing, then it could benefit from other goodies that serverless.yml functions enjoy: logging, command line invocation, etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.