Skip to content

Commit

Permalink
Add readme, lower required versions, ensure ping inits app
Browse files Browse the repository at this point in the history
  • Loading branch information
sihil committed Nov 5, 2016
1 parent a394954 commit 71e633f
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 2 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Plaλ!
=====

[ ![Download](https://api.bintray.com/packages/sihil/plambda/plambda/images/download.svg) ](https://bintray.com/sihil/plambda/plambda/_latestVersion)

This is a somewhat comedic attempt to make [Play!](https://www.playframework.com/) apps work in AWS Lambda. It actually succeeds surprisingly well (so long as your expectations are appropriately low).

Getting started
---------------

1. Look at yourself in the mirror and consider whether running your app in AWS Lambda is something you'll be able to live with. Plaλ comes with no warranty and I will provide no counselling for this life choice.
2. Add the Plaλ library to your Play 2.5 project and also include Play's test framework (2.5.x) and the AWS S3 client (1.11.x) - the wrapper relies on these being present, but does not provide them. Add this to your build.sbt:
```
resolvers += "Plambda Releases" at "https://dl.bintray.com/sihil/plambda"
libraryDependencies ++= Seq(
"net.sihil" %% "plambda" % "0.0.1",
"com.amazonaws" % "aws-java-sdk-s3" % "1.11.48",
component("play-test")
)
```
3. Configure your application to dist a zip file containing all the libraries etc. Add this to the settings for your play project in your SBT configuration:
```
topLevelDirectory in Universal := None
```
4. Run `dist` - this should now create you a zip file suitable for uploading to AWS Lambda
5. Create a CloudFormation stack. I suggest you start with the example template provided and customise as appropriate to grant your application any permissions it needs (note that prior to bringing this up you'll need to upload an initial copy of your lambda into the S3 bucket specified).

Known limitations? Plenty
-------------------------

- Multiple cookies are dealt with by magic so long as they are set on a redirect response (3XX)
- Multiple identical query parameters are not supported
- Performance is somewhat poor when the application has not been used recently due to the start up time of Lambda functions. This is somewhat mitigated by using 1.5Gb of RAM as larger amounts of memory also seems to mean a faster CPU. In adition a five minute "ping" is supported by Plambda and used in the CloudFormation which helps to keep the function luke warm at minimal cost.

Future work
-----------

- Try using it with more projects
- Build an asset interceptor that attempts to re-route known static assets to a static location such as an S3 bucket (seems that this is best done by creating some custom
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ description := "Wrapper for running Play! apps in AWS Lambda"

scalaVersion in ThisProject := "2.11.8"

val playVersion = "2.5.9"
val awsSdkVersion = "1.11.52"
val playVersion = "2.5.0"
val awsSdkVersion = "1.11.0"

libraryDependencies ++= Seq(
"com.typesafe.play" %% "play" % playVersion % "provided",
Expand Down
Empty file added cloudformation/plambda.yaml
Empty file.
11 changes: 11 additions & 0 deletions src/main/scala/plambda/LambdaEntrypoint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ object LambdaEntrypoint {
val PLAMBDA_ENDPOINT = "/plambda"
val COOKIE_ENDPOINT = s"$PLAMBDA_ENDPOINT/moreCookies"
val PING_ENDPOINT = s"$PLAMBDA_ENDPOINT/ping"

var started = false
def init() = {
if (!started) {
started = true
println(s"Initialised LambdaEntrypoint in ${application.mode.toString} mode")
}
}
}

class LambdaEntrypoint extends Writeables {
Expand All @@ -56,6 +64,9 @@ class LambdaEntrypoint extends Writeables {
lambdaRequest match {
case LambdaRequest("PING", _, _, _, _) =>
logger.log("PING")
// the purpose of the ping is to keep this as warm as possible, so make sure the application has been
// initialised
LambdaEntrypoint.init()
LambdaResponse(HttpConstants.OK, body="PONG")
case LambdaRequest("GET", LambdaEntrypoint.COOKIE_ENDPOINT, Some(queryParams), Some(headers), _) =>
routeToPlambda(headers, LambdaEntrypoint.COOKIE_ENDPOINT, queryParams)
Expand Down

0 comments on commit 71e633f

Please sign in to comment.