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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



188
189
190
191
192
193
194
195
# File 'lib/julewire/core/context_store.rb', line 188

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



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

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



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

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



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

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



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/julewire/core/context_store.rb', line 166

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



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

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) ⇒ Object



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

def with_propagation(context: {}, carry: {}, execution: {}, link_executions: false, &)
  scope = current_scope
  execution = Fields::FieldSet.deep_symbolize_keys(execution)
  @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) do
        scope.with_context(context, &)
      end
    else
      @ambient_fields.with(:carry, carry) do
        @ambient_fields.with(:context, context, &)
      end
    end
  ensure
    @execution_overlays.pop
    @execution_lineage_overlays.pop
    invalidate_propagation_cache!
  end
end

#with_scope(scope) ⇒ Object



197
198
199
200
201
202
# File 'lib/julewire/core/context_store.rb', line 197

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

#without_carry(path) ⇒ Object

Raises:

  • (ArgumentError)


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

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