# lambda: Computing Service for Erlang
Modern network applications implement 3-layer design:
* frontend (e.g. web server)
* compute tier
* persistent storage (e.g. database)
Lambda provides an implementation of a scalable stateless compute tier in Erlang.
## Basic Example
This example runs Pi calculations in a remote node. At least 4-core CPU is required to
run it locally.
Code below implements `calc` exporting Pi calculation. Put it into a temporary directory.
```erlang
-module(calc).
-export([pi/1]).
pi(Precision) ->
pi(4, -4, 3, Precision).
pi(LastResult, Numerator, Denominator, Precision) ->
NextResult = LastResult + Numerator / Denominator,
Pow = math:pow(10, Precision),
case trunc(LastResult * Pow) =:= trunc(NextResult * Pow) of
true ->
trunc(NextResult * Pow) / Pow;
false ->
pi(NextResult, -1 * Numerator, Denominator+2, Precision)
end.
```
Start an authority node: `ERL_FLAGS="-lambda authority true" rebar3 shell --name authority`, compile `calc` and
publish it with small capacity:
```
(authority@max-au)1> ===> Booted lambda
c("/tmp/calc.erl").
{ok,calc}
(authority@max-au)2> lambda:publish(calc, #{capacity => 2}).
ok
```
Start another shell, `rebar3 as test shell --name front`, discover `calc` and execute `pi(5)` remotely:
```
(front@max-au)1> ===> Booted lambda
lambda:discover(calc).
ok
(front@max-au)2> calc:pi(5).
6765.
ok
```
Use `erlperf` to verify maximum concurrency of 2:
```
(front@max-au)1> application:start(erlperf).
ok
(front@max-au)6> erlperf:run({calc, pi, [4]}, #{}, #{}).
{166,2}
```
Output above means that `erlperf` detected total throughput of 166 `pi` calls per second, while running 2 concurrent
processes (matching capacity published from `authority` node).
Add more processing capacity by simply starting another node `rebar3 shell --name more`:
```
(more@max-au)1> c("/tmp/calc.erl").
{ok,calc}
(more@max-au)2> lambda:publish(calc, #{capacity => 2}).
ok
```
Ensure `front` received more capacity:
```
(front@max-au)6> erlperf:run({calc, pi, [4]}, #{}, #{}).
{316,4}
```
## Advanced Example
[See Math - scalable 3-tier application](doc/MATH.md).
## Use cases
Primary use-case is to enable remote code execution, and support remote tier lifecycle. It includes but
not limited to:
* moving code to remote tier
* updating remote tier code via hot code load
* safe API update and deployment
## Design
[See DESIGN.md](doc/DESIGN.md)
## API
Public API is provided via `lambda` module. Lambda framework can supervise publishing and
discovery. Use release configuration (`sys.config`) to publish and/or discover modules:
```erlang
[
{lambda, [
{publish, calc},
{discover, basic}
]}
].
```
It is also supported to publish and discover modules under your application supervision,
adding appropriate child specs to supervisor:
```erlang
ChildSpes = [
#{
id => published_calc,
start => {lambda, start_publish, [calc]}
}
]
```
## Running tests
Running any tests will fetch additional libraries as dependencies.
This suite uses PropEr library to simulate all possible state changes.
```bash
rebar3 ct --cover && rebar3 cover --verbose
```
## Changelog
Version 0.1.0:
- initial release