Module: RactorRailsShim::StorageStrategy::Ractor

Defined in:
lib/ractor_rails_shim/foundation/storage_strategy.rb

Overview

Ractor-mode strategy: direct IES lookup + SHAREABLE_FALLBACK. The key is a fixed Symbol literal (no per-ancestor interpolation); the writer always targets this owner's single key.

Class Method Summary collapse

Class Method Details

.lookup(owner, key, missing_default) ⇒ Object

missing_default is a Ruby source string (inlined into the eval'd heredoc by the caller). The Ractor strategy does NOT consult it — its three tiers (IES → SHAREABLE_FALLBACK → CLASS_ATTR_VALUES) cover the lookup; the missing_default is accepted for contract parity with the Thread strategy but unused. This matches the former _class_attr_ractor_methods reader exactly.



38
39
40
41
42
43
44
# File 'lib/ractor_rails_shim/foundation/storage_strategy.rb', line 38

def lookup(owner, key, missing_default)
  v = RactorRailsShim.storage[key]
  return v if RactorRailsShim.storage.key?(key)
  fb = RactorRailsShim::Registry.shareable_fallback[key]
  return fb unless fb.nil?
  RactorRailsShim::Registry.class_attr_values[key] if ::Ractor.main?
end

.replay_callbacks!(context, kind, &block) ⇒ Object

Shared callback-replay logic used by both the "always" path (Thread mode) and the "on-empty" path (Ractor mode). Walks the SHAREABLE_DECLARED_CALLBACKS table and replays captured symbolic filters (before/after) that apply to the current action.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ractor_rails_shim/foundation/storage_strategy.rb', line 63

def replay_callbacks!(context, kind, &block)
  table = ::RactorRailsShim::SHAREABLE_DECLARED_CALLBACKS
  action = (context.action_name rescue nil)
  action = action.to_sym if action
  entries = []
  k = context.class
  while k && k <= ::ActionController::Base
    rec = table[k.object_id]
    entries = rec + entries if rec
    k = k.superclass
  end
  unless entries.empty?
    applies = lambda do |e|
      next false unless (e[:kind] == :before || e[:kind] == :after)
      in_only = e[:only].nil? || (action && e[:only].include?(action))
      not_except = e[:except].nil? || !(action && e[:except].include?(action))
      in_only && not_except
    end
    result = nil
    halted = false
    entries.each do |e|
      next unless e[:kind] == :before && applies.call(e)
      context.send(e[:filter]) if context.respond_to?(e[:filter], true)
    end
    result = block.call unless halted
    entries.each do |e|
      next unless e[:kind] == :after && applies.call(e)
      context.send(e[:filter]) if context.respond_to?(e[:filter], true)
    end
    result
  else
    block.call
  end
end

.replay_callbacks?(callbacks) ⇒ Boolean

Ractor mode: replay captured callbacks only when __callbacks is empty (the worker-Ractor case — workers get the empty default). In the main Ractor, __callbacks is live and replay is skipped.

Returns:

  • (Boolean)


55
56
57
# File 'lib/ractor_rails_shim/foundation/storage_strategy.rb', line 55

def replay_callbacks?(callbacks)
  callbacks.nil? || callbacks.empty?
end

.store(owner, key, value) ⇒ Object



46
47
48
49
50
# File 'lib/ractor_rails_shim/foundation/storage_strategy.rb', line 46

def store(owner, key, value)
  RactorRailsShim.storage[key] = value
  RactorRailsShim::Registry.class_attr_values[key] = value if ::Ractor.main?
  value
end