Inngest.StepTool (Inngest v0.3.0)

Copy Markdown View Source

Durable step helpers available as input.step inside an Inngest function.

Steps split function work into durable units that can be retried and memoized by Inngest. Step IDs are hashed with SHA-1 before they are reported to the executor. When the same step ID appears more than once in a function, the SDK appends :1, :2, and so on before hashing each repeated occurrence.

Reporting

SDK callReported opcodeNotes
run/3StepRunUsed when immediate execution is allowed and the step body runs in the current call request. Includes data, even when the result is nil.
run/4StepRunSame as run/3, with replay options such as keys: :atoms.
run/3StepPlannedUsed when ctx.disable_immediate_execution prevents running the step body in the current call request.
run/3StepErrorUsed when an executed step body raises. Includes the serialized error payload.
targeted stepIdStepNotFoundReturned when a targeted hashed step ID cannot be found during deterministic traversal.
sleep/3, sleep_until/3SleepUses opts.duration for the duration or ISO timestamp.
wait_for_event/3WaitForEventUses opts for event name, timeout, and matching expression.
invoke/3InvokeFunctionUses the active client ID for module targets, plus opts.payload and optional opts.timeout.
send_event/3StepRunImplemented as a durable run step around event sending with the active client.

Memoization

Run and invoke-style steps memoize successful values as %{"data" => value} and failed values as %{"error" => error}. Successful values are unwrapped before being returned to user code. Failed memoized steps raise Inngest.StepError; if that error bubbles out of the function, the SDK returns it as a non-retriable function error.

Sleep steps are memoized as nil. Wait-for-event steps are memoized as the received event payload or nil when the wait times out.

Legacy raw run-step values are not supported by the spec-compliant memoization path. A raw memoized run-step value raises Inngest.StepError so payload shape problems fail clearly.

Map Keys

Freshly executed run/3 results are returned exactly as user code returns them. Replayed memoized results come from JSON payloads, so map keys are strings by default:

%{"foo" => "bar"} =
  step.run(ctx, "load", fn ->
    %{foo: "bar"}
  end)

Use run/4 with keys: :atoms when you need to pattern match on atom keys after replay:

%{foo: "bar"} =
  step.run(ctx, "load", fn ->
    %{foo: "bar"}
  end, keys: :atoms)

keys: :atoms converts string keys recursively with String.to_existing_atom/1. It will not create new atoms. If a memoized key does not already exist as an atom, the SDK raises Inngest.StepError.

Warning

Atoms are not garbage collected by the Erlang VM. Creating too many atoms can exhaust the atom table and crash the VM. The SDK intentionally avoids creating atoms from arbitrary memoized JSON keys. Only use keys: :atoms for known, bounded response shapes whose atom keys already exist in your application.

Summary

Functions

Invokes another Inngest function and waits for its result.

Runs a durable step.

Runs a durable step with replay options.

Sends one or more events as a durable step.

Pauses the function for a duration such as "10s", "5m", or "1h".

Pauses the function until a date or timestamp.

Waits for another event before continuing.

Types

datetime()

@type datetime() :: binary() | DateTime.t() | Date.t() | NaiveDateTime.t()

id()

@type id() :: binary()

run_opt()

@type run_opt() :: {:keys, :strings | :atoms}

Functions

invoke(ctx, step_id, opts)

@spec invoke(Inngest.Function.Context.t(), binary(), map()) :: map()

Invokes another Inngest function and waits for its result.

Options include:

OptionDescription
:functionFunction module to invoke.
:dataPayload data for the invoked function.
:vOptional event payload version.
:timeoutOptional timeout for the invocation.

New invocations report an InvokeFunction opcode. Replayed memoized results are unwrapped from %{"data" => value} or raised as Inngest.StepError from %{"error" => error}.

When :function is a module, the reported function ID is built from the active Inngest.Client in the invocation context. This keeps step invokes aligned with the client used to register and serve functions.

run(ctx, step_id, func)

@spec run(Inngest.Function.Context.t(), id(), fun()) :: any()

Runs a durable step.

Fresh execution returns the value from func exactly as provided by user code. When the step has already been memoized, the SDK unwraps the executor payload from %{"data" => value} and returns value without reporting another opcode.

Use run/4 when replayed memoized map keys need to be converted to atoms.

run(ctx, step_id, func, opts)

@spec run(Inngest.Function.Context.t(), id(), fun(), [run_opt()]) :: any()

Runs a durable step with replay options.

Supported options:

OptionValuesDefaultDescription
:keys:strings, :atoms:stringsControls map keys for replayed memoized %{"data" => value} payloads.

keys: :atoms recursively converts string keys using String.to_existing_atom/1. It does not create atoms and raises Inngest.StepError if a replayed key does not already exist as an atom.

This option only applies to replayed memoized data. Freshly executed results are returned exactly as func returns them.

send_event(ctx, step_id, events)

Sends one or more events as a durable step.

The event send is executed once, then reported as a StepRun containing the sent event IDs. Replayed memoized results return the stored event-send result without sending again.

During function execution, sends use the active invocation client so event URL, event key, mode, and environment headers match the served app.

sleep(ctx, step_id, duration)

@spec sleep(Inngest.Function.Context.t(), id(), binary()) :: nil

Pauses the function for a duration such as "10s", "5m", or "1h".

The SDK reports a Sleep opcode with opts.duration. Once the sleep is memoized by the executor, replay returns nil.

sleep_until(ctx, step_id, time)

@spec sleep_until(Inngest.Function.Context.t(), id(), datetime()) :: nil

Pauses the function until a date or timestamp.

Accepts a binary timestamp, DateTime, Date, or NaiveDateTime. The SDK validates and reports the timestamp as a Sleep opcode with opts.duration. Once memoized by the executor, replay returns nil.

wait_for_event(ctx, step_id, opts)

@spec wait_for_event(Inngest.Function.Context.t(), id(), map()) :: map()

Waits for another event before continuing.

Options may include:

OptionDescription
:eventEvent name to wait for.
:timeoutMaximum wait duration.
:ifSpec expression used to match the incoming event.
:matchElixir shorthand that renders to event.<match> == async.<match>.

Replayed memoized values return an Inngest.Event when an event was received or nil when the wait timed out.