TemporalEx (temporal_ex v0.2.1)

Copy Markdown

Ergonomic Temporal client SDK for Elixir.

Provides a high-level, protobuf-free API for interacting with Temporal workflow services. Users work with plain Elixir terms — maps, keyword lists, strings — and never need to construct protobuf structs.

Quick Start

# Start a client connection
{:ok, client} = TemporalEx.connect(
  target: "localhost:7233",
  namespace: "default"
)

# Start a workflow
{:ok, handle} = TemporalEx.start_workflow(client, "MyWorkflow", [%{key: "value"}],
  id: "my-workflow-123",
  task_queue: "my-task-queue"
)

# Interact with the workflow
:ok = TemporalEx.WorkflowHandle.signal(handle, "my-signal", [%{data: 1}])
{:ok, description} = TemporalEx.WorkflowHandle.describe(handle)
{:ok, result} = TemporalEx.WorkflowHandle.result(handle)

Summary

Functions

Starts a supervised client process connected to a Temporal server.

Counts workflow executions matching a visibility query.

Creates a new Temporal Schedule.

Returns a ScheduleHandle for an existing schedule.

Returns system information from the Temporal server.

Returns a WorkflowHandle for an existing workflow execution.

Lists schedules matching an optional query.

Lists workflow executions matching a visibility query.

Starts a workflow with an initial signal atomically.

Starts a new workflow execution.

Functions

connect(opts \\ [])

@spec connect(keyword()) :: {:ok, pid()} | {:error, term()}

Starts a supervised client process connected to a Temporal server.

Options

  • :target — Temporal server address (default: "localhost:7233")
  • :namespace — Default namespace (default: "default")
  • :api_key — API key or Bearer token
  • :tls — Map/keyword list with :client_cert_pem_b64, :client_key_pem_b64, :ca_cert_file
  • :identity — Client identity string
  • :data_converter — Module implementing TemporalEx.DataConverter (default: TemporalEx.DataConverter.Json)
  • :name — GenServer registration name
  • :call_timeout — Default RPC timeout in ms (default: 5000)

Examples

{:ok, client} = TemporalEx.connect(target: "localhost:7233", namespace: "default")

{:ok, client} = TemporalEx.connect(
  target: "my-ns.tmprl.cloud:7233",
  namespace: "my-ns",
  api_key: "my-api-key"
)

count_workflows(client, query, opts \\ [])

@spec count_workflows(GenServer.server(), String.t(), keyword()) ::
  {:ok, integer()} | {:error, TemporalEx.Error.t()}

Counts workflow executions matching a visibility query.

Examples

{:ok, count} = TemporalEx.count_workflows(client, "WorkflowType = 'MyWorkflow'")

create_schedule(client, schedule_id, opts)

@spec create_schedule(GenServer.server(), String.t(), keyword()) ::
  {:ok, TemporalEx.ScheduleHandle.t()} | {:error, TemporalEx.Error.t()}

Creates a new Temporal Schedule.

Arguments

  • client — Client pid or registered name
  • schedule_id — Unique schedule identifier
  • opts — Schedule configuration

Options (required)

  • :spec — When the schedule triggers (keyword list):

    • :intervals — List of interval specs: [[every: 60]] (seconds) or [[every: 60, offset: 10]]
    • :calendars — List of calendar specs: [[hour: "8", minute: "30"]]
    • :cron_expressions — List of cron strings: ["0 */5 * * *"]
    • :timezone — Timezone name: "America/Chicago"
    • :jitter — Max random jitter in seconds
    • :start_time / :end_timeDateTime bounds
  • :action — What to run (keyword list):

    • :workflow_type — Workflow type name (required)
    • :workflow_id — Workflow ID (required)
    • :task_queue — Task queue name (required)
    • :args — List of workflow arguments

Options (optional)

  • :policies — Scheduling policies (keyword list):

    • :overlap_policy:skip, :buffer_one, :buffer_all, :cancel_other, :terminate_other, :allow_all
    • :catchup_window — Seconds
    • :pause_on_failure — Boolean
  • :state — Initial state:

    • :paused — Boolean
    • :notes — String
  • :memo — Map of memo fields

  • :search_attributes — Map of search attributes

  • :identity — Caller identity

  • :request_id — Idempotency key

Examples

{:ok, handle} = TemporalEx.create_schedule(client, "my-schedule",
  spec: [intervals: [[every: 60]]],
  action: [
    workflow_type: "MyWorkflow",
    workflow_id: "my-workflow",
    task_queue: "my-queue",
    args: [%{key: "value"}]
  ],
  policies: [overlap_policy: :skip]
)

get_schedule_handle(client, schedule_id)

@spec get_schedule_handle(GenServer.server(), String.t()) ::
  TemporalEx.ScheduleHandle.t()

Returns a ScheduleHandle for an existing schedule.

This does not make any RPC calls — it simply creates the handle struct.

Examples

handle = TemporalEx.get_schedule_handle(client, "my-schedule")
{:ok, desc} = TemporalEx.ScheduleHandle.describe(handle)

get_system_info(client)

@spec get_system_info(GenServer.server()) ::
  {:ok, struct()} | {:error, TemporalEx.Error.t()}

Returns system information from the Temporal server.

Examples

{:ok, info} = TemporalEx.get_system_info(client)

get_workflow_handle(client, workflow_id, run_id \\ nil)

@spec get_workflow_handle(GenServer.server(), String.t(), String.t() | nil) ::
  TemporalEx.WorkflowHandle.t()

Returns a WorkflowHandle for an existing workflow execution.

This does not make any RPC calls — it simply creates the handle struct.

Examples

handle = TemporalEx.get_workflow_handle(client, "my-workflow-123")
{:ok, desc} = TemporalEx.WorkflowHandle.describe(handle)

list_schedules(client, opts \\ [])

@spec list_schedules(
  GenServer.server(),
  keyword()
) :: {:ok, list(), binary()} | {:error, TemporalEx.Error.t()}

Lists schedules matching an optional query.

Options

  • :page_size — Maximum results per page (default: 100)
  • :next_page_token — Pagination token

Examples

{:ok, schedules, token} = TemporalEx.list_schedules(client)

list_workflows(client, query, opts \\ [])

@spec list_workflows(GenServer.server(), String.t(), keyword()) ::
  {:ok, list(), binary()} | {:error, TemporalEx.Error.t()}

Lists workflow executions matching a visibility query.

Options

  • :page_size — Maximum number of results per page (default: 100)
  • :next_page_token — Token for pagination

Examples

{:ok, workflows, token} = TemporalEx.list_workflows(client, "WorkflowType = 'MyWorkflow'")

signal_with_start(client, workflow_type, args, signal_name, signal_args, opts)

@spec signal_with_start(
  GenServer.server(),
  String.t(),
  list(),
  String.t(),
  list(),
  keyword()
) ::
  {:ok, TemporalEx.WorkflowHandle.t()} | {:error, TemporalEx.Error.t()}

Starts a workflow with an initial signal atomically.

If the workflow is already running, only the signal is delivered.

Arguments

  • client — Client pid or registered name
  • workflow_type — Workflow type name string
  • args — List of workflow arguments
  • signal_name — Signal name to send
  • signal_args — List of signal arguments
  • opts — Same options as start_workflow/4

start_workflow(client, workflow_type, args, opts)

@spec start_workflow(GenServer.server(), String.t(), list(), keyword()) ::
  {:ok, TemporalEx.WorkflowHandle.t()} | {:error, TemporalEx.Error.t()}

Starts a new workflow execution.

Arguments

  • client — Client pid or registered name
  • workflow_type — Workflow type name string
  • args — List of arguments to pass to the workflow
  • opts — Keyword list of options

Options (required)

  • :id — Unique workflow ID
  • :task_queue — Task queue to schedule the workflow on

Options (optional)

  • :execution_timeout — Max total workflow execution time in seconds
  • :run_timeout — Max single run time in seconds
  • :task_timeout — Max workflow task processing time in seconds
  • :retry_policy — Keyword list or map with retry config
  • :memo — Map of memo fields
  • :search_attributes — Map of search attribute fields
  • :start_delay — Delay before starting the workflow in seconds
  • :request_id — Idempotency key
  • :identity — Caller identity
  • :id_reuse_policy — Workflow ID reuse policy atom
  • :id_conflict_policy — Workflow ID conflict policy atom
  • :cron_schedule — Cron schedule string

Examples

{:ok, handle} = TemporalEx.start_workflow(client, "ProcessOrder", [%{order_id: 123}],
  id: "order-123",
  task_queue: "orders"
)