Module: FiberAudit::Runtime::ExecutionContext

Defined in:
lib/fiber_audit/runtime/execution_context.rb

Overview

Fiber-local execution context with propagation to child fibers. Uses Ruby Fiber storage (Fiber) for fiber-local state that is inherited by child fibers at creation, enabling automatic context propagation across Fiber boundaries.

Frames are immutable (frozen Data objects) forming a linked list. Each with call creates a new frame pointing to the parent frame.

Semantics:

  • Child fibers inherit the parent fiber's current context at creation
  • Child fiber overrides do not alter parent context
  • clear! removes context for the current fiber only
  • clear! inside nested with is not undone by the enclosing ensure (ensure restores only when its own frame is still the active one)
  • Thread isolation is maintained even though Ruby copies Fiber storage to a newly created Thread's root Fiber
  • PID mismatch (after fork) is treated as empty context
  • MAX_DEPTH overflow exposes :unknown rather than stale outer context

Constant Summary collapse

MAX_DEPTH =
32
FRAME_KEY =
:__fiber_audit_execution_context_frame__

Class Method Summary collapse

Class Method Details

.after_fork!Object

Clear context after fork.



74
75
76
# File 'lib/fiber_audit/runtime/execution_context.rb', line 74

def after_fork!
  clear!
end

.clear!Object



64
65
66
# File 'lib/fiber_audit/runtime/execution_context.rb', line 64

def clear!
  Fiber[FRAME_KEY] = nil
end

.currentObject



35
36
37
38
# File 'lib/fiber_audit/runtime/execution_context.rb', line 35

def current
  frame = current_frame
  frame ? frame.context : Context::UNKNOWN
end

.reset!Object

Compatibility alias for clear!.



69
70
71
# File 'lib/fiber_audit/runtime/execution_context.rb', line 69

def reset!
  clear!
end

.with(context) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/fiber_audit/runtime/execution_context.rb', line 40

def with(context)
  normalized = validate_context(context)
  parent = current_frame

  new_depth = parent ? parent.depth + 1 : 1
  effective = new_depth > MAX_DEPTH ? Context::UNKNOWN : normalized
  frame = Frame.new(
    context: effective,
    parent: parent,
    depth: new_depth,
    pid: Process.pid,
    thread_id: Thread.current.object_id
  )

  Fiber[FRAME_KEY] = frame
  begin
    yield
  ensure
    # Only restore if our frame is still the active one.
    # If clear! was called (or another with replaced it), skip restore.
    Fiber[FRAME_KEY] = parent if Fiber[FRAME_KEY].equal?(frame)
  end
end