Class: Julewire::Core::ContextStore

Inherits:
Object
  • Object
show all
Defined in:
lib/julewire/core/context_store.rb

Overview

Fiber-local context stack used by the runtime facade. Use Julewire.context and Julewire.with_execution instead of reaching into this class directly.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeContextStore

Returns a new instance of ContextStore.



21
22
23
# File 'lib/julewire/core/context_store.rb', line 21

def initialize
  reset!
end

Class Method Details

.currentObject



13
14
15
# File 'lib/julewire/core/context_store.rb', line 13

def current
  LocalStorage.context_store
end

.reset_current!Object

Reset only clears the caller’s current thread/fiber context.



18
# File 'lib/julewire/core/context_store.rb', line 18

def reset_current! = LocalStorage.reset_context_store!

Instance Method Details

#add_attributes(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



96
97
98
# File 'lib/julewire/core/context_store.rb', line 96

def add_attributes(fields = EMPTY_HASH, owned: false, **keyword_fields)
  add_field(:attributes, field_input(fields, keyword_fields), owned: owned)
end

#add_carry(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



92
93
94
# File 'lib/julewire/core/context_store.rb', line 92

def add_carry(fields = EMPTY_HASH, owned: false, **keyword_fields)
  add_field(:carry, field_input(fields, keyword_fields), owned: owned)
end

#add_context(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



88
89
90
# File 'lib/julewire/core/context_store.rb', line 88

def add_context(fields = EMPTY_HASH, owned: false, **keyword_fields)
  add_field(:context, field_input(fields, keyword_fields), owned: owned)
end

#add_neutral(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



100
101
102
# File 'lib/julewire/core/context_store.rb', line 100

def add_neutral(fields = EMPTY_HASH, owned: false, **keyword_fields)
  add_field(:neutral, field_input(fields, keyword_fields), owned: owned)
end

#attributes_hashObject



67
68
69
# File 'lib/julewire/core/context_store.rb', line 67

def attributes_hash
  current_field_hash(:attributes)
end

#attributes_proxyObject



51
52
53
# File 'lib/julewire/core/context_store.rb', line 51

def attributes_proxy
  @attributes_proxy ||= Fields::AttributesProxy.new(self)
end

#attributes_value(key, default:) ⇒ Object



84
85
86
# File 'lib/julewire/core/context_store.rb', line 84

def attributes_value(key, default:)
  current_field_stack(:attributes).value_for(key, default: default)
end

#carry_hashObject



63
64
65
# File 'lib/julewire/core/context_store.rb', line 63

def carry_hash
  current_field_hash(:carry)
end

#carry_proxyObject



47
48
49
# File 'lib/julewire/core/context_store.rb', line 47

def carry_proxy
  @carry_proxy ||= Fields::CarryProxy.new(self)
end

#carry_value(key, default:) ⇒ Object



80
81
82
# File 'lib/julewire/core/context_store.rb', line 80

def carry_value(key, default:)
  current_field_stack(:carry).value_for(key, default: default)
end

#context_hashObject



59
60
61
# File 'lib/julewire/core/context_store.rb', line 59

def context_hash
  current_field_hash(:context)
end

#context_proxyObject



43
44
45
# File 'lib/julewire/core/context_store.rb', line 43

def context_proxy
  @context_proxy ||= Fields::ContextProxy.new(self)
end

#context_value(key, default:) ⇒ Object

SectionProxy dispatches these dynamically from the public field readers.



76
77
78
# File 'lib/julewire/core/context_store.rb', line 76

def context_value(key, default:)
  current_field_stack(:context).value_for(key, default: default)
end

#current_scopeObject



35
# File 'lib/julewire/core/context_store.rb', line 35

def current_scope = @scopes.last

#current_scope?Boolean

Returns:

  • (Boolean)


37
# File 'lib/julewire/core/context_store.rb', line 37

def current_scope? = !!current_scope

#current_scope_or_snapshotObject



39
40
41
# File 'lib/julewire/core/context_store.rb', line 39

def current_scope_or_snapshot
  current_scope || propagation_scope_snapshot
end

#delete_carry(path) ⇒ Object



104
105
106
107
108
109
110
111
112
113
# File 'lib/julewire/core/context_store.rb', line 104

def delete_carry(path)
  path = Fields::Internal.normalize_path(path)
  return if path.empty?

  if current_scope
    current_scope.delete_carry(path)
  else
    @ambient_fields.delete(:carry, path)
  end
end

#neutral_hashObject



71
72
73
# File 'lib/julewire/core/context_store.rb', line 71

def neutral_hash
  current_field_hash(:neutral)
end

#reset!Object



25
26
27
28
29
30
31
32
33
# File 'lib/julewire/core/context_store.rb', line 25

def reset!
  @scopes = []
  @ambient_fields = Fields::StackSet.new
  @execution_overlays = []
  @execution_lineage_overlays = []
  @propagation_execution_hash = nil
  @propagation_scope_snapshot = nil
  @linked_propagation_scope_snapshot = nil
end

#start_execution(**options) ⇒ Object



193
194
195
196
197
198
199
200
# File 'lib/julewire/core/context_store.rb', line 193

def start_execution(**options)
  scope = build_scope(options)
  Execution::Handle.new(
    scope: scope,
    on_finish: options[:on_finish],
    on_finish_failure: options[:on_finish_failure]
  )
end

#summary_proxyObject



55
56
57
# File 'lib/julewire/core/context_store.rb', line 55

def summary_proxy
  @summary_proxy ||= Fields::SummaryProxy.new(self)
end

#with_attributes(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



123
124
125
# File 'lib/julewire/core/context_store.rb', line 123

def with_attributes(fields = EMPTY_HASH, owned: false, **keyword_fields, &)
  with_scope_or_ambient_overlay(:attributes, field_input(fields, keyword_fields), owned: owned, &)
end

#with_carry(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



119
120
121
# File 'lib/julewire/core/context_store.rb', line 119

def with_carry(fields = EMPTY_HASH, owned: false, **keyword_fields, &)
  with_scope_or_ambient_overlay(:carry, field_input(fields, keyword_fields), owned: owned, &)
end

#with_context(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



115
116
117
# File 'lib/julewire/core/context_store.rb', line 115

def with_context(fields = EMPTY_HASH, owned: false, **keyword_fields, &)
  with_scope_or_ambient_overlay(:context, field_input(fields, keyword_fields), owned: owned, &)
end

#with_execution(**options) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/julewire/core/context_store.rb', line 171

def with_execution(**options)
  scope = build_scope(options)
  active_exception = nil

  @scopes.push(scope)
  begin
    yield Execution::View.new(scope)
  rescue Exception => e # rubocop:disable Lint/RescueException
    active_exception = e
    raise
  ensure
    scope.record_error(active_exception) if active_exception
    @scopes.pop
    finish_scope(
      scope,
      options[:on_finish],
      options[:on_finish_failure],
      active_exception: active_exception
    )
  end
end

#with_neutral(fields = EMPTY_HASH, owned: false, **keyword_fields) ⇒ Object



127
128
129
# File 'lib/julewire/core/context_store.rb', line 127

def with_neutral(fields = EMPTY_HASH, owned: false, **keyword_fields, &)
  with_scope_or_ambient_overlay(:neutral, field_input(fields, keyword_fields), owned: owned, &)
end

#with_propagation(context: {}, carry: {}, execution: {}, link_executions: false, owned: false) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/julewire/core/context_store.rb', line 143

def with_propagation(context: {}, carry: {}, execution: {}, link_executions: false, owned: false, &)
  scope = current_scope
  execution = if owned
                Fields::FieldSet.deep_symbolize_owned_keys(execution)
              else
                Fields::FieldSet.deep_symbolize_keys(execution)
              end
  @execution_overlays.push(execution)
  @execution_lineage_overlays.push(link_executions ? Execution::Lineage.from_execution_hash(execution) : nil)
  invalidate_propagation_cache!

  begin
    if scope
      scope.with_carry(carry, owned: owned) do
        scope.with_context(context, owned: owned, &)
      end
    else
      @ambient_fields.with(:carry, carry, owned: owned) do
        @ambient_fields.with(:context, context, owned: owned, &)
      end
    end
  ensure
    @execution_overlays.pop
    @execution_lineage_overlays.pop
    invalidate_propagation_cache!
  end
end

#with_scope(scope) ⇒ Object



202
203
204
205
206
207
# File 'lib/julewire/core/context_store.rb', line 202

def with_scope(scope)
  @scopes.push(scope)
  yield Execution::View.new(scope)
ensure
  @scopes.pop
end

#without_carry(path) ⇒ Object

Raises:

  • (ArgumentError)


131
132
133
134
135
136
137
138
139
140
141
# File 'lib/julewire/core/context_store.rb', line 131

def without_carry(path, &)
  scope = current_scope
  normalized_path = Fields::Internal.normalize_path(path)
  raise ArgumentError, "carry path is required" if normalized_path.empty?

  if scope
    scope.without_carry(normalized_path, &)
  else
    @ambient_fields.without(:carry, normalized_path, &)
  end
end