Skip to content

darwin67/inngest-ex

Repository files navigation



A durable event-driven workflow engine SDK for Elixir.
Read the documentation and get started in minutes.


Inngest Elixir SDK

Inngest's Elixir SDK allows you to create event-driven, durable workflows in your existing API — without new infrastructure.

It's useful if you want to build reliable software without worrying about queues, events, subscribers, workers, or other complex primitives such as concurrency, parallelism, event batching, or distributed debounce. These are all built in.

Installation

The Elixir SDK can be downloaded from Hex. Add it to your list of dependencies in mix.exs

# mix.exs
def deps do
  [
    {:inngest, "~> 0.2"}
  ]
end

Example

This is a basic example of what an Inngest function will look like.

A Module can be turned into an Inngest function easily by using the Inngest.Function macro.

defmodule MyApp.AwesomeFunction do
  use Inngest.Function

  @func %FnOpts{id: "awesome-fn", name: "Awesome Function"} # The id and name of the function
  @trigger %Trigger{event: "func/awesome"} # The event this function will react to

  @impl true
  def exec(_ctx, _input) do
    IO.inspect("Do something")

    {:ok, "hello world"}
  end
end

And just like that, you have an Inngest function that will react to an event called func/awesome. Inngest.Function.exec/2 will then be called by the SDK to run and execute the logic.

Advanced

The above example will be no different from other background processing libraries, so let's take a look at a more complicated version. Which should provide you an idea what is capable with Inngest.

defmodule MyApp.AwesomeFunction do
  use Inngest.Function

  @func %FnOpts{id: "awesome-fn", name: "Awesome Function"} # The id and name of the function
  @trigger %Trigger{event: "func/awesome"} # The event this function will react to

  @impl true
  def exec(ctx, %{step: step} = input) do
    IO.inspect("Starting function...")

    %{greet: greet} =
      # A return value wrapped in a `step` are memorized, meaning
      # it's guaranteed to be idempotent.
      # if it fails, it'll be retried.
      step.run(ctx, "step1", fn ->
        %{greet: "hello"}
      end)

    # Sleeping will pause the execution from running, and function
    # will be reinvoked when time is up.
    step.sleep(ctx, "wait-a-little", "10s")

    %{name: name} =
      step.run(ctx, "retrieve-user", fn ->
        # retrieve user from here
        %{name: user_name}
      end)

    # There are times you want to wait for something to happen before
    # continue on the workflow. `wait_for_event` allows exactly that.
    evt = step.wait_for_event("wait-for-registration-complete", %{
      event: "user/register.completed",
      timeout: "1h"
    })

    # You might want to trigger some other workflow, sending an event
    # will trigger the functions that are registered against the `event`.
    step.send_event("completed-work", %{
      name: "func/awesome.completed",
      data: %{name: name}
    })

    {:ok, %{greetings: "#{greet} #{name}", registered: is_nil(evt)}}
  end
end

See the guides for more details regarding use cases and how each macros can be used.