Skip to content

Commit

Permalink
update README and to match 0.2.0 syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
darwin67 committed Nov 7, 2023
1 parent d83e446 commit 0989f69
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 65 deletions.
148 changes: 87 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
[![CI](https://github.com/darwin67/ex-inngest/actions/workflows/ci.yml/badge.svg)](https://github.com/darwin67/ex-inngest/actions/workflows/ci.yml)
[![Hex.pm](https://img.shields.io/hexpm/v/inngest.svg)](https://hex.pm/packages/inngest)
[![Hexdocs.pm](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/inngest/)
## Notice

<!-- MDOC ! -->
This is the README for `main` branch, which is for pre `0.2.0` release.

### Experimental - non official, use at your own risk
<!-- MDOC ! -->

Elixir SDK for **[Inngest](https://www.inngest.com)**
<div align="center">
<a href="https://www.inngest.com"><img src="https://user-images.githubusercontent.com/306177/191580717-1f563f4c-31e3-4aa0-848c-5ddc97808a9a.png" width="300" /></a>
<br/>
<br/>
<p>
A durable event-driven workflow engine SDK for Elixir.<br />
Read the <a href="https://www.inngest.com/docs?ref=github-inngest-elixir-readme">documentation</a> and get started in minutes.
</p>
<p>
<a href="https://github.com/darwin67/ex-inngest/actions/workflows/ci.yml"><img src="https://github.com/darwin67/ex-inngest/actions/workflows/ci.yml/badge.svg"></a>
<a href="https://hex.pm/packages/inngest"><img src="https://img.shields.io/hexpm/v/inngest.svg" /></a>
<a href="https://hexdocs.pm/inngest/"><img src="https://img.shields.io/badge/hex-docs-lightgreen.svg" /></a>
<br/>
<a href="https://www.inngest.com/discord"><img src="https://img.shields.io/discord/842170679536517141?label=discord" /></a>
<a href="https://twitter.com/inngest"><img src="https://img.shields.io/twitter/follow/inngest?style=social" /></a>
</p>
</div>

# [Inngest](https://www.inngest.com) 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

Expand All @@ -17,7 +40,7 @@ to your list of dependencies in `mix.exs`
# mix.exs
def deps do
[
{:inngest, "~> 0.1"}
{:inngest, git: "https://github.com/inngest/ex_inngest.git", branch: "main"}
]
end
```
Expand All @@ -31,71 +54,74 @@ macro.

``` elixir
defmodule MyApp.AwesomeFunction do
use Inngest.Function,
name: "awesome function", # The name of the function
event: "func/awesome" # The event this function will react to
use Inngest.Function
alias Inngest.{FnOpts, Trigger}

@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")

# Declare a "run" macro that runs contains the business logic
run "hello world" do
{:ok, %{result: "hello world"}}
{:ok, "hello world"}
end
end
```

The Elixir SDK follows `ExUnit`'s pattern of accumulative macros, where each block
is a self contained piece of logic.

You can declare multiple blocks of `run` or other available macros, and the function
will execute the code in the order it is declared.
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

Here's a slightly more complicated version, which should provide you an idea what is
capable with Inngest.
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.

``` elixir
defmodule MyApp.AwesomeFunction do
use Inngest.Function,
name: "awesome function", # The name of the function
event: "func/awesome" # The event this function will react to

# An Inngest function will automatically retry when it fails

# "run" is a normal unit execution. It is not memorized and will be
# executed every time the function gets re-invoked.
#
# The return "data" from each execution block will be accumulated
# and passed on to the next execution
run "1st run" do
{:ok, %{run: "do something"}}
end

# "step" is a unit execution where the return value will be memorized.
# An already executed "step" will not be executed again when re-invoked
# and will use the previously returned value
#
# e.g. The previous `%{run: "do something"}` can be extracted out via
# pattern matching, just like how you do it in `ExUnit`
step "1st step", %{data: %{run: output}} do
{:ok, %{hey: output}}
end

# "sleep" will pause the execution for the declared amount of duration.
sleep "2s"

step "2nd step" do
{:ok, %{yo: "lo"}}
end

# "sleep" can also sleep until a valid datetime string
sleep "until July 31 2023 - 8pm", do: "2023-07-18T07:31:00Z"

# "wait_for_event" will pause the function execution until the declared
# event is received
wait_for_event "test/wait", do: [timeout: "1d", match: "data.yo"]

step "result", %{data: data} do
{:ok, %{result: data}}
use Inngest.Function
alias Inngest.{FnOpts, Trigger}

@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
```
Expand Down
8 changes: 4 additions & 4 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ defmodule Inngest.MixProject do

# Docs
name: "Inngest",
source_url: "https://github.com/darwin67/ex_inngest",
source_url: "https://github.com/inngest/ex_inngest",
description: "Elixir SDK for Inngest",
homepage_url: "https://inngest.com",
docs: [
main: "Inngest",
authors: ["Darwin Wu"],
authors: ["Inngest Engineering<[email protected]>"],
# source_ref: "v#{@version}",
assets: "docs/assets",
logo: "docs/assets/logo.png",
Expand Down Expand Up @@ -72,9 +72,9 @@ defmodule Inngest.MixProject do

defp package do
[
maintainers: ["Darwin Wu"],
maintainers: ["Inngest Engineering<[email protected]>"],
licenses: ["GPL-3.0-or-later"],
links: %{github: "https://github.com/darwin67/ex_inngest"},
links: %{github: "https://github.com/inngest/ex_inngest"},
files: ~w(lib mix.exs README.md LICENSE VERSION CHANGELOG.md)
]
end
Expand Down

0 comments on commit 0989f69

Please sign in to comment.