Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to Distillery and update dependencies #16

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ lambda-*.tar

*.lock
*.swp

.DS_Store
4 changes: 2 additions & 2 deletions elixir_runtime/config/config.exs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

use Mix.Config
import Config

config :logger,
:console,
level: :debug,
metadata: [:module, :function, :line]

# Uncomment to enable environment-specific configuration
# import_config "#{Mix.env()}.exs"
# import_config "#{config_env()}.exs"
14 changes: 7 additions & 7 deletions elixir_runtime/lib/elixir_runtime/lambda_service_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ defmodule ElixirRuntime.LambdaServiceClient do
) :: no_return
def invocation_error(err_msg, id) do
url =
'http://#{service_endpoint()}/2018-06-01/runtime/invocation/#{id}/error'
~c"http://#{service_endpoint()}/2018-06-01/runtime/invocation/#{id}/error"

request = {url, [], 'text/plain', err_msg}
request = {url, [], ~c"text/plain", err_msg}
{:ok, _response} = :httpc.request(:post, request, [], [])
end

@impl true
@spec init_error(Monitor.Client.error()) :: no_return
def init_error(err_msg) do
url = 'http://#{service_endpoint()}/2018-06-01/runtime/init/error'
request = {url, [], 'text/plain', err_msg}
url = ~c"http://#{service_endpoint()}/2018-06-01/runtime/init/error"
request = {url, [], ~c"text/plain", err_msg}
{:ok, _response} = :httpc.request(:post, request, [], [])
end

Expand All @@ -44,16 +44,16 @@ defmodule ElixirRuntime.LambdaServiceClient do
) :: no_return
def complete_invocation(id, response) do
url =
'http://#{service_endpoint()}/2018-06-01/runtime/invocation/#{id}/response'
~c"http://#{service_endpoint()}/2018-06-01/runtime/invocation/#{id}/response"

request = {url, [], 'text/plain', response}
request = {url, [], ~c"text/plain", response}
{:ok, _response} = :httpc.request(:post, request, [], [])
end

@impl true
@spec next_invocation() :: Runtime.Client.invocation()
def next_invocation do
url = 'http://#{service_endpoint()}/2018-06-01/runtime/invocation/next'
url = ~c"http://#{service_endpoint()}/2018-06-01/runtime/invocation/next"
response = :httpc.request(:get, {url, []}, [], [])
Logger.debug("Http get from #{url} was #{Kernel.inspect(response)}")
parse(response)
Expand Down
4 changes: 2 additions & 2 deletions elixir_runtime/lib/elixir_runtime/loop.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ defmodule ElixirRuntime.Loop do

response =
handler
|> Handler.invoke(Poison.decode!(body), context)
|> Poison.encode!()
|> Handler.invoke(Jason.decode!(body), context)
|> Jason.encode!()

client.complete_invocation(id, response)
end
Expand Down
10 changes: 5 additions & 5 deletions elixir_runtime/lib/elixir_runtime/monitor/error.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule ElixirRuntime.Monitor.Error do

alias __MODULE__

@derive Poison.Encoder
@derive Jason.Encoder
defstruct [
:errorMessage,
:errorType,
Expand All @@ -23,15 +23,15 @@ defmodule ElixirRuntime.Monitor.Error do
stackTrace: list
}

@doc "Build an Error from a structured process-exit reason"
@spec from_exit_reason(error_type, {atom(), list()}) :: error
@doc "Build an Error from a process-exit reason"
@spec from_exit_reason(error_type, term) :: error
def from_exit_reason(error_type, reason)

def from_exit_reason(error_type, _reason = {error, stacktrace}) do
exception = Exception.normalize(:error, error, stacktrace)
build_error(error_name(error_type, exception), exception, stacktrace)
end

@doc "Build an Error from an unknown process-exit reason"
@spec from_exit_reason(error_type, term) :: error
def from_exit_reason(error_type, reason) do
exception = Exception.normalize(:error, {"unexpected exit", reason})
build_error(error_name(error_type, exception), exception, [])
Expand Down
8 changes: 4 additions & 4 deletions elixir_runtime/lib/elixir_runtime/monitor/state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ defmodule ElixirRuntime.Monitor.State do

@doc "report an error before an invocation was started"
@spec error(monitor_state, term()) :: no_return
def error(monitor_state, reason)

def error({:not_started, client}, reason) do
Monitor.Error.from_exit_reason(:runtime, reason)
|> Poison.encode!()
|> Jason.encode!()
|> client.init_error()
end

@doc "report an error before an invocation was started"
@spec error(monitor_state, term()) :: no_return
def error({:in_progress, id, client}, reason) do
Monitor.Error.from_exit_reason(:function, reason)
|> Poison.encode!()
|> Jason.encode!()
|> client.invocation_error(id)
end

Expand Down
2 changes: 2 additions & 0 deletions elixir_runtime/lib/epmd/stub_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# SPDX-License-Identifier: MIT-0

defmodule EPMD.StubClient do
@doc since: "0.2.0"
@deprecated "No longer needed when using mix release."
@moduledoc """
This module implements an EPMD client which does not actually coordinate
with the real EPMD or allow the current node to communicate with other
Expand Down
35 changes: 26 additions & 9 deletions elixir_runtime/lib/mix/tasks/bootstrap.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,23 @@ defmodule Mix.Tasks.Bootstrap do

use Mix.Task

@runtime_libs "elixir_runtime-0.1.0/priv"

@shortdoc "Generate a bootstrap script for the project"
def run(_) do
name =
Mix.Project.config()
|> Keyword.fetch!(:app)
|> to_string
name = app_name()

path = "_build/#{Mix.env()}/rel/#{name}/bootstrap"

Mix.Generator.create_file(path, bootstrap(name))
File.chmod!(path, 0o777)

Mix.shell().info("Bootstrap file created: #{path}")

end

# The bootstrap script contents
defp bootstrap(app) when is_binary(app) do
"""
\#!/bin/bash
\#!/bin/sh

set -x

Expand All @@ -38,11 +36,30 @@ defmodule Mix.Tasks.Bootstrap do
export HOME

\# So that distillery doesn't try to write any files
\# Ignored and not needed when using mix release
export RELEASE_READ_ONLY=true

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$BASE/lib/#{@runtime_libs}
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$BASE/lib/#{runtime_app_name()}-#{runtime_version()}/priv

$EXE foreground
$EXE start
"""
end

defp app_name() do
Mix.Project.config()
|> Keyword.fetch!(:app)
|> to_string
end

defp runtime_app_name() do
Application.get_application(__MODULE__)
|> Atom.to_string()

end

defp runtime_version() do
Application.get_application(__MODULE__)
|> Application.spec(:vsn)
end

end
2 changes: 2 additions & 0 deletions elixir_runtime/lib/mix/tasks/gen_lambda_release.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# SPDX-License-Identifier: MIT-0

defmodule Mix.Tasks.GenLambdaRelease do
@doc since: "0.2.0"
@deprecated "No longer needed when using mix release."
@moduledoc """
Generate a distillery release configuration file for lambda release builds.
"""
Expand Down
5 changes: 4 additions & 1 deletion elixir_runtime/lib/mix/tasks/zip.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ defmodule Mix.Tasks.Zip do
@shortdoc "zip the contents of the current release"
def run(_) do
path = release_path(app_name())
zip_file = "#{app_name()}_lambda.zip"

cmd = "cd #{path} && zip -r lambda.zip * && cp lambda.zip #{System.cwd()}"
cmd = "set -xe && cd #{path} && zip -r #{zip_file} *"

System.cmd("sh", ["-c", cmd])

Mix.shell().info("Zip file created: #{Path.join(path, zip_file)}")
end

defp app_name() do
Expand Down
16 changes: 9 additions & 7 deletions elixir_runtime/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ defmodule Lambda.MixProject do
def project do
[
app: :aws_lambda_elixir_runtime,
version: "0.1.0",
elixir: "~> 1.7",
version: "0.2.0",
elixir: "~> 1.15",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
deps: deps(),
Expand All @@ -17,7 +17,8 @@ defmodule Lambda.MixProject do
# Docs
name: "AWS Lambda Elixir Runtime",
source_url: "https://github.com/aws-samples/aws-lambda-elixir-runtime",
homepage_url: "https://github.com/aws-samples/aws-lambda-elixir-runtime/tree/master/elixir_runtime",
homepage_url:
"https://github.com/aws-samples/aws-lambda-elixir-runtime/tree/master/elixir_runtime",
docs: [
source_url_pattern:
"https://github.com/aws-samples/aws-lambda-elixir-runtime/blob/master/elixir_runtime/%{path}#L%{line}",
Expand All @@ -34,16 +35,17 @@ defmodule Lambda.MixProject do
def application do
[
mod: {ElixirRuntime.Application, []},
extra_applications: [:logger, :inets]
extra_applications: [:logger, :inets, :ssl]
]
end

# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:poison, "~> 3.1"},
{:mox, "~> 0.4", only: :test},
{:ex_doc, "~> 0.19", only: :dev, runtime: false}
{:jason, "~> 1.4"},
{:mox, "~> 1.0", only: :test},
{:ex_doc, "~> 0.27", only: :dev, runtime: false},
{:castore, "~> 1.0", only: [:dev, :test]}
]
end

Expand Down
Binary file removed elixir_runtime/priv/libcrypto.so.1.0.0
Binary file not shown.
Binary file added elixir_runtime/priv/libcrypto.so.1.1
Binary file not shown.
Binary file modified elixir_runtime/priv/libssl.so
Binary file not shown.
4 changes: 2 additions & 2 deletions elixir_runtime/test/elixir_runtime/monitor/state_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ defmodule ElixirRuntime.Monitor.State.Test do

test "report an error from initial state" do
reason = {:badarg, []}
expected = Poison.encode!(Monitor.Error.from_exit_reason(:runtime, reason))
expected = Jason.encode!(Monitor.Error.from_exit_reason(:runtime, reason))

State.initial(FakeClient) |> State.error(reason)

Expand All @@ -48,7 +48,7 @@ defmodule ElixirRuntime.Monitor.State.Test do
test "report an error while an invocation is in progress" do
invoke_id = "fakeid"
reason = {:badarg, []}
expected = Poison.encode!(Monitor.Error.from_exit_reason(:function, reason))
expected = Jason.encode!(Monitor.Error.from_exit_reason(:function, reason))

State.initial(FakeClient)
|> State.start_invocation(invoke_id)
Expand Down
2 changes: 1 addition & 1 deletion elixir_runtime/test/support/fake_invoke.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Support.FakeInvoke do

def with_message(message) do
body = %{msg: message}
{generated_id(), Poison.encode!(body), %{}}
{generated_id(), Jason.encode!(body), %{}}
end

def id({id, _body, _context}), do: id
Expand Down
2 changes: 1 addition & 1 deletion examples/hello_world/config/config.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

use Mix.Config
import Config
11 changes: 11 additions & 0 deletions examples/hello_world/config/runtime.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Config

# config/runtime.exs is executed for all environments, including
# during releases. It is executed after compilation and before the
# system starts, so it is typically used to load production configuration
# and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration.
if config_env() == :prod do

end
18 changes: 13 additions & 5 deletions examples/hello_world/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ defmodule HelloWorld.MixProject do
def project do
[
app: :hello_world,
version: "0.1.0",
elixir: "~> 1.7",
version: "0.2.0",
elixir: "~> 1.15",
start_permanent: Mix.env() == :prod,
deps: deps()
deps: deps(),
releases: [
hello_world: [
version: "0.2.0",
applications: [hello_world: :permanent, aws_lambda_elixir_runtime: :permanent],
include_erts: true,
include_executables_for: [:unix],

]
]
]
end

Expand All @@ -24,8 +33,7 @@ defmodule HelloWorld.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:aws_lambda_elixir_runtime, path: "../../elixir_runtime"},
{:distillery, "~> 2.0"}
{:aws_lambda_elixir_runtime, path: "../../elixir_runtime"}
]
end
end
34 changes: 0 additions & 34 deletions examples/hello_world/rel/config.exs

This file was deleted.

8 changes: 8 additions & 0 deletions examples/hello_world/rel/env.bat.eex
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@echo off
rem Set the release to load code on demand (interactive) instead of preloading (embedded).
rem set RELEASE_MODE=interactive

rem Set the release to work across nodes.
rem RELEASE_DISTRIBUTION must be "sname" (local), "name" (distributed) or "none".
rem set RELEASE_DISTRIBUTION=name
rem set RELEASE_NODE=<%= @release.name %>
Loading