Class: Archsight::Annotations::ComputedManager

Inherits:
Object
  • Object
show all
Defined in:
lib/archsight/annotations/computed.rb

Overview

ComputedManager orchestrates the computation of all computed annotations. It handles lazy evaluation, caching, and cycle detection.

Instance Method Summary collapse

Constructor Details

#initialize(database) ⇒ ComputedManager

Returns a new instance of ComputedManager.



173
174
175
176
177
# File 'lib/archsight/annotations/computed.rb', line 173

def initialize(database)
  @database = database
  @computed_cache = {}  # { [instance_object_id, key] => value }
  @computing = Set.new  # For cycle detection
end

Instance Method Details

#compute_all!Object

Compute all computed annotations for all instances



180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/archsight/annotations/computed.rb', line 180

def compute_all!
  # Collect all resource classes that have computed annotations
  @database.instances.each do |klass, instances_hash|
    definitions = klass.computed_annotations
    next if definitions.empty?

    instances_hash.each_value do |instance|
      definitions.each do |definition|
        compute_for(instance, definition)
      end
    end
  end
end

#compute_for(instance, definition) ⇒ Object

Compute a specific annotation for an instance



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/archsight/annotations/computed.rb', line 203

def compute_for(instance, definition)
  cache_key = [instance.object_id, definition.key]

  # Return cached value if available
  return @computed_cache[cache_key] if @computed_cache.key?(cache_key)

  # Cycle detection
  raise "Circular dependency detected: #{definition.key} for #{instance.name}" if @computing.include?(cache_key)

  @computing.add(cache_key)
  begin
    evaluator = Archsight::Annotations::ComputedEvaluator.new(instance, @database, self)
    value = evaluator.instance_eval(&definition.block) # steep:ignore BlockTypeMismatch

    # Apply type coercion if specified
    value = coerce_value(value, definition.type) if definition.type

    # Cache the computed value (even if nil, to avoid recomputation)
    @computed_cache[cache_key] = value

    # Only store meaningful values to the instance annotations
    # nil and empty arrays indicate "no data" and should not be stored
    if meaningful_value?(value)
      # Convert arrays to comma-separated strings for consistency with regular annotations
      stored_value = value.is_a?(Array) ? value.join(", ") : value
      instance.set_computed_annotation(definition.key, stored_value)
    end

    value
  ensure
    @computing.delete(cache_key)
  end
end

#compute_for_key(instance, key) ⇒ Object

Compute a specific annotation for an instance by key



195
196
197
198
199
200
# File 'lib/archsight/annotations/computed.rb', line 195

def compute_for_key(instance, key)
  definition = instance.class.computed_annotations.find { |d| d.matches?(key) }
  return nil unless definition

  compute_for(instance, definition)
end