Class: LazyInit::DependencyResolver
- Inherits:
-
Object
- Object
- LazyInit::DependencyResolver
- Defined in:
- lib/lazy_init/dependency_resolver.rb
Overview
Handles dependency resolution and circular dependency detection for lazy attributes.
This resolver maintains a dependency graph and provides thread-safe resolution with caching to avoid redundant dependency checking. It prevents circular dependencies and optimizes performance through intelligent caching strategies.
Instance Method Summary collapse
-
#add_dependency(attribute, dependencies) ⇒ void
Add a dependency relationship for an attribute.
-
#initialize(target_class) ⇒ DependencyResolver
constructor
Initialize a new dependency resolver for the given class.
-
#resolution_order_for(attribute) ⇒ Array<Symbol>?
Get the pre-computed resolution order for an attribute.
-
#resolve_dependencies(attribute, instance) ⇒ void
Resolve all dependencies for an attribute on a specific instance.
Constructor Details
#initialize(target_class) ⇒ DependencyResolver
Initialize a new dependency resolver for the given class.
Sets up internal data structures for dependency tracking, resolution caching, and thread safety mechanisms.
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/lazy_init/dependency_resolver.rb', line 23 def initialize(target_class) @target_class = target_class @dependency_graph = {} @resolution_orders = {} @mutex = Mutex.new # per-instance caching to avoid redundant dependency resolution @instance_resolution_cache = {} @cache_mutex = Mutex.new end |
Instance Method Details
#add_dependency(attribute, dependencies) ⇒ void
This method returns an undefined value.
Add a dependency relationship for an attribute.
Records that the given attribute depends on other attributes and pre-computes the resolution order for optimal performance.
42 43 44 45 46 47 48 |
# File 'lib/lazy_init/dependency_resolver.rb', line 42 def add_dependency(attribute, dependencies) @mutex.synchronize do @dependency_graph[attribute] = Array(dependencies) @resolution_orders[attribute] = compute_resolution_order(attribute) invalidate_dependent_orders(attribute) end end |
#resolution_order_for(attribute) ⇒ Array<Symbol>?
Get the pre-computed resolution order for an attribute.
54 55 56 |
# File 'lib/lazy_init/dependency_resolver.rb', line 54 def resolution_order_for(attribute) @resolution_orders[attribute] end |
#resolve_dependencies(attribute, instance) ⇒ void
This method returns an undefined value.
Resolve all dependencies for an attribute on a specific instance.
Uses intelligent caching to avoid redundant resolution and provides thread-safe dependency resolution with circular dependency detection. The resolution is cached per-instance to optimize repeated access.
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 97 98 99 100 101 102 103 |
# File 'lib/lazy_init/dependency_resolver.rb', line 68 def resolve_dependencies(attribute, instance) resolution_order = @resolution_orders[attribute] return unless resolution_order instance_key = instance.object_id cache_key = "#{instance_key}_#{attribute}" # fast path: if already resolved, skip everything return if dependency_resolved_cached?(cache_key) # prevent recursive mutex locking in nested dependency chains current_thread_resolving = Thread.current[:lazy_init_cache_resolving] ||= false if current_thread_resolving # we're already inside a resolution chain, skip caching to avoid deadlocks resolve_dependencies_direct(attribute, instance, resolution_order) return end # thread-safe cache update for top-level calls only @cache_mutex.synchronize do # double-check pattern after acquiring lock return if dependency_resolved_cached?(cache_key) # mark this thread as currently resolving to prevent recursion Thread.current[:lazy_init_cache_resolving] = true begin resolve_dependencies_direct(attribute, instance, resolution_order) mark_dependency_resolved(cache_key) ensure # always clean up thread state Thread.current[:lazy_init_cache_resolving] = false end end end |