Module: Phronomy::WorkflowContext

Defined in:
lib/phronomy/workflow_context.rb

Overview

Module for defining workflow context (the data that travels through a workflow). Include in a class and use the field DSL to declare context fields.

In StateChart terminology this is the "extended state" or "context" — data associated with the current execution that does not affect transitions directly, as opposed to the current phase (which is the machine's state).

Field update policies: :replace (default) -- overwrites with the new value :append -- appends to an Array :merge -- deep-merges into a Hash

Examples:

class ScanContext
  include Phronomy::WorkflowContext
  field :messages, type: :append, default: -> { [] }
  field :query,    type: :replace
  field :metadata, type: :merge,   default: -> { {} }
end

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#thread_idObject (readonly)

Internal workflow metadata accessors (not user-defined fields). These are preserved through merge but excluded from to_h.



46
47
48
# File 'lib/phronomy/workflow_context.rb', line 46

def thread_id
  @thread_id
end

Class Method Details

.included(base) ⇒ Object



24
25
26
27
# File 'lib/phronomy/workflow_context.rb', line 24

def self.included(base)
  base.extend(ClassMethods)
  base.instance_variable_set(:@fields, {})
end

Instance Method Details

#halted?Boolean

Returns true if the workflow is paused mid-execution (not yet completed).

Returns:

  • (Boolean)


60
61
62
# File 'lib/phronomy/workflow_context.rb', line 60

def halted?
  phase != :__end__
end

#initialize(**attrs) ⇒ Object



73
74
75
76
77
78
79
80
# File 'lib/phronomy/workflow_context.rb', line 73

def initialize(**attrs)
  self.class.fields.each do |name, config|
    default = config[:default].is_a?(Proc) ? config[:default].call : config[:default]
    send(:"#{name}=", attrs.fetch(name, default))
  end
  @thread_id = nil
  @phase = :__end__
end

#merge(updates) ⇒ self.class

Immutably updates context fields. Returns a new instance with the applied changes. Internal workflow metadata (thread_id, phase) is preserved.

Parameters:

  • updates (Hash)

    { field_name => new_value }

Returns:

  • (self.class)

    new context instance



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/phronomy/workflow_context.rb', line 86

def merge(updates)
  new_attrs = {}
  self.class.fields.each_key do |name|
    field_config = self.class.fields[name]
    new_attrs[name] = if updates.key?(name)
      case field_config[:type]
      when :append
        Array(send(name)) + Array(updates[name])
      when :merge
        (send(name) || {}).merge(updates[name])
      else
        updates[name]
      end
    else
      send(name)
    end
  end
  new_context = self.class.new(**new_attrs)
  new_context.(
    thread_id: @thread_id,
    phase: @phase
  )
  new_context
end

#phaseSymbol

Returns the current execution phase of the workflow. Encoding: :end — workflow completed (or not yet started) :awaiting_ — halted at a wait_state(:awaiting_) declaration : — resuming at (workflow paused before its execution)

Returns:

  • (Symbol)


54
55
56
# File 'lib/phronomy/workflow_context.rb', line 54

def phase
  @phase || :__end__
end

#set_graph_metadata(thread_id: nil, phase: nil) ⇒ Object

Sets internal workflow metadata. Returns self.

Parameters:

  • thread_id (String, nil) (defaults to: nil)
  • phase (Symbol, nil) (defaults to: nil)


67
68
69
70
71
# File 'lib/phronomy/workflow_context.rb', line 67

def (thread_id: nil, phase: nil)
  @thread_id = thread_id unless thread_id.nil?
  @phase = phase unless phase.nil?
  self
end

#to_hHash

Converts user-defined fields to a Hash (excludes internal workflow metadata).

Returns:

  • (Hash)


113
114
115
116
117
# File 'lib/phronomy/workflow_context.rb', line 113

def to_h
  self.class.fields.keys.each_with_object({}) do |name, h|
    h[name] = send(name)
  end
end