Class: Ask::Graph::Context
- Inherits:
-
Object
- Object
- Ask::Graph::Context
- Defined in:
- lib/ask/graph/context.rb
Overview
Shared state that flows through every step of a graph execution.
Stores input, output, and intermediate data produced by steps.
Accessed by step classes via context.data_key or context[:data_key].
Thread-safe by design — each context is scoped to one graph run.
Instance Attribute Summary collapse
-
#graph ⇒ Ask::Graph
readonly
The graph this context belongs to.
-
#item ⇒ Object?
readonly
The current item when iterating via #each.
-
#resume_input ⇒ Object?
Input provided on resume for approval steps.
Instance Method Summary collapse
-
#[](key) ⇒ Object?
Access a stored value by key.
-
#[]=(key, value) ⇒ Object
Store a value by key.
-
#each(items) {|item| ... } ⇒ Object
Iterate over items with per-item checkpointing.
-
#export_data ⇒ Hash
Unlike #to_h, this returns the actual Ruby objects without serialization.
-
#import(other) ⇒ Object
Merge data from another context (or hash) into this one.
-
#initialize(graph, input = nil) ⇒ Context
constructor
A new instance of Context.
-
#method_missing(name, *args, &block) ⇒ Object
Access a stored value by method name.
- #respond_to_missing?(name, include_private = false) ⇒ Boolean
-
#run(graph_class) ⇒ Ask::Graph::Context
Run an Ask::Graph as a sub-graph, merging its context back.
-
#to_h ⇒ Hash
All keys and values are converted to JSON-safe types (string keys, symbols converted to strings, arrays recursed).
Constructor Details
#initialize(graph, input = nil) ⇒ Context
Returns a new instance of Context.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/ask/graph/context.rb', line 26 def initialize(graph, input = nil) @graph = graph @store = {} @each_index = nil @each_items = nil @item = nil @mutex = Mutex.new @resume_input = nil if input.is_a?(Hash) @store[:input] = input @store.merge!(input) elsif input @store[:input] = input end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
Access a stored value by method name.
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/ask/graph/context.rb', line 46 def method_missing(name, *args, &block) if name.to_s.end_with?("=") key = name.to_s.chomp("=").to_sym @mutex.synchronize { @store[key] = args.first } elsif args.empty? && !block @mutex.synchronize { @store[name] } else super end end |
Instance Attribute Details
#graph ⇒ Ask::Graph (readonly)
Returns the graph this context belongs to.
21 22 23 |
# File 'lib/ask/graph/context.rb', line 21 def graph @graph end |
#item ⇒ Object? (readonly)
Returns the current item when iterating via #each.
24 25 26 |
# File 'lib/ask/graph/context.rb', line 24 def item @item end |
#resume_input ⇒ Object?
Returns input provided on resume for approval steps.
43 44 45 |
# File 'lib/ask/graph/context.rb', line 43 def resume_input @resume_input end |
Instance Method Details
#[](key) ⇒ Object?
Access a stored value by key.
65 66 67 |
# File 'lib/ask/graph/context.rb', line 65 def [](key) @mutex.synchronize { @store[key.to_sym] } end |
#[]=(key, value) ⇒ Object
Store a value by key.
72 73 74 |
# File 'lib/ask/graph/context.rb', line 72 def []=(key, value) @mutex.synchronize { @store[key.to_sym] = value } end |
#each(items) {|item| ... } ⇒ Object
Iterate over items with per-item checkpointing.
Each iteration is checkpointed so that if the process crashes, it resumes from the last completed item rather than starting over.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/ask/graph/context.rb', line 84 def each(items, &block) @each_index = graph.runner.resume_index_for(items) || 0 @each_items = items items.each_with_index do |item, idx| break if idx < @each_index @item = item block.call(item) graph.runner.checkpoint_each!(idx) end ensure @each_index = nil @each_items = nil @item = nil end |
#export_data ⇒ Hash
Unlike #to_h, this returns the actual Ruby objects without serialization. Useful for passing state to sub-graphs.
113 114 115 |
# File 'lib/ask/graph/context.rb', line 113 def export_data @mutex.synchronize { @store.dup } end |
#import(other) ⇒ Object
Merge data from another context (or hash) into this one. Existing keys in this context are overwritten.
121 122 123 124 |
# File 'lib/ask/graph/context.rb', line 121 def import(other) data = other.is_a?(Context) ? other.export_data : other @mutex.synchronize { @store.merge!(data) } end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
57 58 59 60 |
# File 'lib/ask/graph/context.rb', line 57 def respond_to_missing?(name, include_private = false) clean = name.to_s.sub(/=$/, "").to_sym @store.key?(clean) || super end |
#run(graph_class) ⇒ Ask::Graph::Context
Run an Ask::Graph as a sub-graph, merging its context back.
Exports the current context data, creates the sub-graph with it, runs it, and merges any results back into this context.
140 141 142 143 144 145 |
# File 'lib/ask/graph/context.rb', line 140 def run(graph_class) sub = graph_class.new(export_data) sub_ctx = sub.call import(sub_ctx) sub_ctx end |
#to_h ⇒ Hash
All keys and values are converted to JSON-safe types (string keys, symbols converted to strings, arrays recursed).
104 105 106 107 108 |
# File 'lib/ask/graph/context.rb', line 104 def to_h @mutex.synchronize do deep_json_safe(@store) end end |