Powered by AppSignal & Oban Pro

Funx.Monad.Effect.Context

livebooks/monad/effect/context.livemd

Funx.Monad.Effect.Context

Mix.install([
  {:funx, "0.8.8"}
])

Overview

Represents the execution context attached to an effect.

This struct carries contextual information such as trace_id, span_name, timeouts, and arbitrary metadata (baggage and metadata). It supports telemetry integration, span linking, and timeout control, and is propagated automatically across composed effects.

Developers can set fields like timeout, trace_id, or span_name when constructing Left and Right effects. The context is merged or promoted as needed when chaining effects to preserve trace continuity and execution scope.

This context is not injected at runtime via run/2—it is bound to the effect when created.

Function Examples

import Funx.Monad.Effect.Context
alias Funx.Monad.Effect.Context

Functions

new/1

Creates a new Funx.Monad.Effect.Context struct for use with effectful computations.

If no :trace_id is provided, a unique one is generated automatically. You may also set optional fields such as :span_name, :timeout, :baggage, and :metadata.

The returned context is intended to be passed into Left and Right effects, where it will be propagated and updated across chained computations.

Examples

ctx = new(span_name: "load-data", timeout: 2000)
ctx.span_name
ctx = new(trace_id: "abc123")
ctx.trace_id

merge/2

Merges two %Funx.Monad.Effect.Context{} structs into one, preferring non-nil values from the first context.

This is used to preserve trace continuity and propagate context across composed effects.

  • Non-nil fields from the first context take precedence.
  • baggage and metadata maps are deeply merged.
  • This operation is idempotent and safe for reuse across nested effect chains.

Examples

c1 = new(trace_id: "a", baggage: %{user: 1})
c2 = new(trace_id: "b", baggage: %{region: "us-west"})
merge(c1, c2).baggage

override/2

Returns a new %Funx.Monad.Effect.Context{} with fields overridden by values from the given keyword list.

  • Direct fields like :trace_id, :parent_trace_id, :span_name, and :timeout are replaced if present.
  • Nested maps :baggage and :metadata are deeply merged, with the keyword list taking precedence.

This is useful for refining or extending an existing context in a specific part of an effect chain.

Examples

ctx = new(trace_id: "abc", baggage: %{x: 1}, metadata: %{debug: false})
updated = override(ctx, span_name: "child", baggage: %{x: 2}, metadata: %{debug: true})
updated.span_name
updated.baggage
updated.metadata

promote_trace/2

Promotes the current context into a child trace by generating a new trace_id and linking to the original.

  • The current trace_id is moved to parent_trace_id.
  • A new trace_id is generated for the child context.
  • The given label is prepended to the existing span_name as "label -> span".

This is typically used to represent a nested span or sub-operation within a larger effect chain, preserving trace lineage across composed effects.

Examples

parent = new(trace_id: "abc123", span_name: "load")
child = promote_trace(parent, "decode")
child.parent_trace_id
child.trace_id != "abc123"
child.span_name

generate_trace_id/0

Generates a random lowercase hexadecimal trace ID.

This function is used internally to ensure each trace is uniquely identifiable.

Examples

id = generate_trace_id()
String.length(id)
id =~ ~r/^[a-f0-9]+$/