A Lein plugin, template and small Clojurescript library for exposing functions via AWS Lambda.
- Low instance warmup penalty
- Specify execution roles and resource limits in project definition
- Use core.async for deferred completion
- Smaller zip files with
:optimizations
:advanced
support - Blog post/tutorial
$ lein new cljs-lambda my-lambda-project
$ cd my-lambda-project
$ lein cljs-lambda default-iam-role
$ lein cljs-lambda deploy
$ lein cljs-lambda invoke work-magic '{"variety": "black"}'
The above requires a recent Node runtime, and a properly-configured (aws configure
) AWS CLI installation >= 1.7.31. Please run pip install --upgrade awscli
if you're using an older version (aws --version
).
Or, put:
In your Clojurescript project's :plugins
vector.
(ns cljs-lambda-example.cat
(:require [cljs-lambda.util :refer [async-lambda-fn]]))
(def ^:export meow
(async-lambda-fn
(fn [{meow-target :name} context]
(go
(<! (async/timeout 1000))
{:from "the-cat"
:to meow-target
:message "I'm meowing at you"}))))
And its associated project.clj
See the example project:
{:cljs-lambda
{:cljs-build-id "cljs-lambda-example"
:aws-profile "XYZ"
:defaults
{:role "arn:aws:iam::151963828411:role/lambda_basic_execution"}
:functions
[{:name "dog-bark"
:invoke cljs-lambda-example.dog/bark}
{:name "cat-meow"
:invoke cljs-lambda-example.cat/meow}]}}
If :aws-profile
is present, the value will be passed as --profile
to all invocations of the AWS CLI, otherwise the CLI's default profile will be used.
The following keys are valid for entries in [:cljs-lambda :functions]
. The optional keys are listed at the end, alongside their defaults:
{:name "the-lambda-function-name"
:invoke my-cljs-namespace.module/fn
:role "arn:..."
[:description "I don't think this field sees much action"
:create true
:timeout 3 ;; seconds
:memory-size 128]} ;; MB
Values in [:cljs-lambda :defaults]
will be merged into each function map. These values are written to Lambda on deploy
. Alternatively:
$ lein cljs-lambda update-config
Will update the remote (Lambda) configuration of all of the functions listed in the project file. The :create
key, defaulting to true
, determines whether a create-function
Lambda command will be issued if an attempt is made to deploy
a not-yet-existing Lambda function.
The plugin depends on cljsbuild
, and assumes there is a :cljsbuild
section
in your project.clj
. A deployment or build via cljs-lambda
invokes
cljsbuild
- it'll run either the first build in the :builds
vector, or the
one identified by [:cljs-lambda :cljs-build-id]
.
- Source map support will be enabled if the
:source-map
key of the active build istrue
. - If
:optimizations
is set to:advanced
on the active build, the zip output will be structured accordingly (i.e. it'll only containindex.js
and the single compiler output file). - With
:advanced
,*main-cli-fn*
is required to be set (i.e.(set! *main-cli-fn* identity)
)
deploy
means "deploy all functions in this project". It could be changed pretty easily.- I guess we ought to use the docstring for
:description
, if none is supplied. - PR's welcome.
It's pretty tiny - please see the example project, or the project generated by lein new cljs-lambda
.
$ lein cljs-lambda invoke my-lambda-fn '{"arg1": "value" ...}'
If you're interested in programmatically invoking Lambda functions from Clojure/Clojurescript, it's pretty easy with eulalie:
(eulalie.lambda.util/invoke!
{:access-key ... :secret-key ... [:token :region etc.]}
"my-lambda-fn"
:request-response
{:arg1 "value" :arg2 ["value"]})
cljs-lambda is free and unencumbered public domain software. For more information, see http://unlicense.org/ or the accompanying UNLICENSE file.