# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 defmodule ElixirRuntime.Loop do @moduledoc """ The main Runtime loop process. This Process is responsible for polling the Lambda Runtime Service for function invocations and invoking the user's code. If this process crashes then the Monitor will report the error and stacktrace automatically. """ use Task, restart: :permanent require Logger alias __MODULE__ alias Loop.Handler alias ElixirRuntime.Monitor @type client :: module() @doc "spawn a task to run the main loop asynchronously" def start_link(args \\ []) do client = Keyword.get(args, :client) Task.start_link(Loop, :main, [client]) end @doc "the main entrypoint for the runtime" @spec main(client()) :: no_return def main(client) do Monitor.watch(self()) handler = Handler.configured() loop(client, handler) end @doc "the runtime's main loop" def loop(client, handler) do Monitor.reset() client.next_invocation() |> process(client, handler) loop(client, handler) end defp process(:no_invocation, _client, _handler) do Logger.debug("no invocation to process") Process.sleep(50) end defp process(invocation = {id, body, context}, client, handler) do Monitor.started(id) Logger.info("handle invocation #{Kernel.inspect(invocation)}") response = handler |> Handler.invoke(Poison.decode!(body), context) |> Poison.encode!() client.complete_invocation(id, response) end end