Interact.UseCase (Interact v1.0.3)

Copy Markdown View Source

A use case is either a module that exports a unary exec/1 function, or any unary function (an fn closure or a &Module.function/1 capture). Interact.UseCase wraps either form in a struct and provides a pipeline for controlling execution.

Pipeline

import Interact.UseCase

create(MyApp.MyUseCase)   # fully-qualified module, or a unary function
|> async()                # fire and forget; default is synchronous (optional)
|> timeout(ms)            # kill the task after ms milliseconds (optional)
|> callback(functions)    # called with the result struct after completion (optional)
|> reply(pids)            # processes to receive the result struct (optional)
|> input(data)            # input passed to exec/1
|> run()                  # execute the use case

run/2 is a shorthand for input/2 |> run/1. Every pipeline function accepts a module or function directly and calls create/1 automatically, so the pipeline can start at any step — create/1 is never required.

The struct is single-use: once run/1 is called the use case is considered started, and any further pipeline call — including run/1 itself — raises ArgumentError.

Result struct

The %Interact.UseCase{} returned by run/1 always reflects the full execution:

  • output — return value of exec/1, or nil on error
  • error — exception struct if exec/1 raised, nil on success
  • stacktrace — stacktrace when error is an exception, nil otherwise
  • started_at, finished_atDateTime UTC timestamps
  • timedout_atDateTime UTC timestamp set when the deadline was exceeded, nil otherwise

Callbacks and replies fire even on failure, so result handling is uniform regardless of outcome.

Summary

Types

t(i, o)

@type t(i, o) :: %Interact.UseCase{
  async: boolean(),
  callbacks: [(t(i, o) -> any())],
  error: Exception.t() | nil,
  finished_at: DateTime.t() | nil,
  input: i | nil,
  logic: atom() | (i -> o),
  output: o | nil,
  reply: [pid()],
  stacktrace: Exception.stacktrace() | nil,
  started_at: DateTime.t() | nil,
  timedout_at: DateTime.t() | nil,
  timeout: timeout()
}

Functions

async(usecase)

@spec async(t(i, o) | atom() | (i -> o)) :: t(i, o) when i: any(), o: any()

callback(usecase, callbacks)

@spec callback(t(i, o) | atom() | (i -> o), (t(i, o) -> any()) | [(t(i, o) -> any())]) ::
  t(i, o)
when i: any(), o: any()

create(logic)

@spec create(atom() | (i -> o)) :: t(i, o) when i: any(), o: any()

input(usecase, data)

@spec input(t(i, o) | atom() | (i -> o), i) :: t(i, o) when i: any(), o: any()

reply(usecase, pids)

@spec reply(t(i, o) | atom() | (i -> o), pid() | [pid()]) :: t(i, o)
when i: any(), o: any()

run(usecase)

@spec run(t(i, o) | atom() | (i -> o)) :: t(i, o) when i: any(), o: any()

run(usecase, input_data)

@spec run(t(i, o) | atom() | (i -> o), i) :: t(i, o) when i: any(), o: any()

timeout(usecase, ms)

@spec timeout(t(i, o) | atom() | (i -> o), timeout()) :: t(i, o)
when i: any(), o: any()