hal: A runtime environment for Haskell applications running on AWS Lambda.

[ aws, bsd3, library, web ] [ Propose Tags ]

This library uniquely supports different types of AWS Lambda Handlers for your needs/comfort with advanced Haskell. Instead of exposing a single function that constructs a Lambda, this library exposes many.


[Skip to Readme]
Versions [faq] 0.1.0, 0.1.1, 0.1.2, 0.2.0, 0.3.0
Dependencies aeson (>=1.3.1.1 && <1.4), base (>=4.7 && <5), bytestring (>=0.10.8.2 && <0.11), containers (>=0.5.11.0 && <0.6), envy (>=1.5.1.0 && <1.6), exceptions (>=0.10.0 && <0.11), http-conduit (>=2.3.2 && <2.4), http-types (>=0.12.2 && <0.13), mtl (>=2.2.2 && <2.3), text (>=1.2.3.1 && <1.3), time (>=1.8.0.2 && <1.9) [details]
License BSD-3-Clause
Copyright 2018 Nike, Inc.
Author Nike, Inc.
Maintainer nikeoss
Category Web, AWS
Home page https://github.com/Nike-inc/hal#readme
Bug tracker https://github.com/Nike-inc/hal/issues
Source repo head: git clone https://github.com/Nike-inc/hal
Uploaded by nikeoss at Tue Jan 8 17:12:24 UTC 2019
Distributions NixOS:0.3.0
Downloads 281 total (90 in the last 30 days)
Rating (no votes yet) [estimated by rule of succession]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs available [build log]
Last success reported on 2019-01-08 [all 1 reports]

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

For package maintainers and hackage trustees


Readme for hal-0.1.1

[back to package description]

hal

A runtime environment for Haskell applications running on AWS Lambda.

Flexible

This library uniquely supports different types of AWS Lambda Handlers for your needs/comfort with advanced Haskell. Instead of exposing a single function that constructs a Lambda, this library exposes many.

For lambdas that are pure and safe, then pureRuntime is ideal. It accepts a handler with the signature (FromJSON a, ToJSON b) => a -> b. This runtime guarantees that side-effects cannot occur.

For advanced use cases mRuntimeWithContext unlocks the full power of Monad Transformers. It accepts handlers with the signature (HasLambdaContext r, MonadCatch m, MonadReader r m, MonadIO m, FromJSON event, ToJSON result) => (event -> m result) This enables users to add caching logic or expose complex environments.

With numerous options in between these two, developers can choose the right balance of flexibility vs simplicity.

Performant

Measuring lambda performance is tricky, so investigation and optimization is ongoing. Current indications show a warm execution overhead of only ~20% more than the official Rust Runtime (a much lower level language).

Robust

While testing continues, we have executed over 30k test events without error caused by the runtime. Naive approaches lead to error rates well over 10%.

Table of Contents

Quick Start

This quick start assumes you have the following tools installed:

Add hal to your stack.yaml's extra-deps and enable Docker integration so that your binary is automatically compiled in a compatible environment for AWS. Also add hal to your project's dependency list (either project-name.cabal or package.yaml)

#...
packages:
  - '.'
  - hal-0.1.0
# ...
docker:
  enable: true
# ...

Then, define your types and handler:

{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE DeriveGeneric #-}

module Main where

import AWS.Lambda.Runtime (pureRuntime)
import Data.Aeson (FromJSON, ToJSON)
import GHC.Generics (Generic)

data Request = Request {
  input :: String
} deriving (Generic)

instance FromJSON Request

data Response = Response {
  output :: String
} deriving (Generic)

instance ToJSON Response

idHandler :: Request -> Response
idHandler Request { input } = Response { output = input }

main :: IO ()
main = pureRuntime idHandler

Don't forget to define your CloudFormation stack:

# file: template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Test for the Haskell Runtime.
Resources:
  HelloWorldApp:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: NOT_USED
      Runtime: provided
      CodeUri: .stack-work/docker/_home/.local/bin/
      Description: My Haskell runtime.
      MemorySize: 128
      Timeout: 3

Finally, build, upload and test your lambda!

# Build the binary, make sure your executable is named `bootstrap`
stack build --copy-bins

# Create your function package
aws cloudformation package \
  --template-file template.yaml
  --s3-bucket your-existing-bucket > \
  deployment_stack.yaml

# Deploy your function
aws cloudformation deploy \
  --stack-name "hello-world-haskell" \
  --region us-west-2 \
  --capabilities CAPABILITY_IAM \
  --template-file deployment_stack.yaml

# Take it for a spin!
aws lambda invoke \
  --function-name your-function-name \
  --region us-west-2
  --payload '{"input": "foo"}'
  output.txt

Usage

TODO

Local Testing

Dependencies

Build

docker pull fpco/stack-build:lts-12.21 #first build only
stack build --copy-bins

Execute

echo '{ "accountId": "byebye" }' | sam local invoke --region us-east-1