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 = nil, owned: false, **keyword_fields) ⇒ Object



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

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

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



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

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

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



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

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

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



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

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

#attributes_hashObject



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

def attributes_hash
  current_field_hash(:attributes)
end

#attributes_proxyObject



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

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

#attributes_value(key, default:) ⇒ Object



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

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

#carry_hashObject



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

def carry_hash
  current_field_hash(:carry)
end

#carry_proxyObject



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

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

#carry_value(key, default:) ⇒ Object



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

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

#context_hashObject



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

def context_hash
  current_field_hash(:context)
end

#context_proxyObject



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

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

#context_value(key, default:) ⇒ Object

SectionProxy dispatches these dynamically from the public field readers.



73
74
75
# File 'lib/julewire/core/context_store.rb', line 73

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

#current_scopeObject



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

def current_scope = @scopes.last

#current_scope?Boolean

Returns:

  • (Boolean)


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

def current_scope? = !!current_scope

#current_scope_or_snapshotObject



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

def current_scope_or_snapshot
  current_scope || propagation_scope_snapshot
end

#delete_carry(path) ⇒ Object



101
102
103
104
105
106
107
108
# File 'lib/julewire/core/context_store.rb', line 101

def delete_carry(path)
  path = Fields::Internal.normalize_path(path)
  if current_scope
    current_scope.delete_carry(path)
  else
    @ambient_fields.delete(:carry, path)
  end
end

#neutral_hashObject



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

def neutral_hash
  current_field_hash(:neutral)
end

#reset!Object



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

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

#start_execution(**options) ⇒ Object



179
180
181
182
183
184
185
186
# File 'lib/julewire/core/context_store.rb', line 179

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



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

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

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



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

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

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



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

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

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



110
111
112
# File 'lib/julewire/core/context_store.rb', line 110

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

#with_execution(**options) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/julewire/core/context_store.rb', line 157

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 = nil, owned: false, **keyword_fields) ⇒ Object



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

def with_neutral(fields = nil, 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:, owned:) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/julewire/core/context_store.rb', line 138

def with_propagation(context:, carry:, execution:, link_executions:, owned:, &)
  execution = if owned
                Serialization::DeepFreeze.validate_symbol_hash(execution)
              else
                Fields::FieldSet.deep_symbolize_keys(execution)
              end
  @execution_overlays.push(PropagationOverlay.new(execution: execution, link_executions: link_executions))
  invalidate_propagation_cache!

  begin
    with_carry(carry, owned: owned) do
      with_context(context, owned: owned, &)
    end
  ensure
    @execution_overlays.pop
    invalidate_propagation_cache!
  end
end

#with_scope(scope) ⇒ Object



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

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

#without_carry(path) ⇒ Object

Raises:

  • (ArgumentError)


126
127
128
129
130
131
132
133
134
135
136
# File 'lib/julewire/core/context_store.rb', line 126

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