Class: Wayfarer::Middleware::DependencyGraph
- Inherits:
-
Object
- Object
- Wayfarer::Middleware::DependencyGraph
- Includes:
- TSort
- Defined in:
- lib/wayfarer/middleware/dependency_graph.rb
Overview
Immutable dependency graph that resolves middleware ordering via before:/after: constraints. Every mutation (add, remove, replace) returns a new instance with an eagerly compiled Chain and API module.
Defined Under Namespace
Classes: Entry
Constant Summary collapse
- CyclicDependencyError =
Class.new(StandardError)
Instance Attribute Summary collapse
-
#api ⇒ Module
readonly
Combined API concern for all registered middlewares.
-
#chain ⇒ Chain
readonly
The compiled middleware chain.
-
#entries ⇒ Hash{Class => Entry}
readonly
Middleware entries keyed by class.
-
#insertion_order ⇒ Array<Class>
readonly
Classes in registration order.
Instance Method Summary collapse
-
#add(klass, args = [], before: [], after: []) ⇒ DependencyGraph
Returns a new graph with the middleware added.
-
#initialize(entries: {}, insertion_order: []) ⇒ DependencyGraph
constructor
A new instance of DependencyGraph.
-
#remove(klass) ⇒ DependencyGraph
Returns a new graph with the middleware removed.
-
#replace(old_klass, new_klass, args = []) ⇒ DependencyGraph
Returns a new graph with old_klass swapped for new_klass.
Constructor Details
#initialize(entries: {}, insertion_order: []) ⇒ DependencyGraph
Returns a new instance of DependencyGraph.
31 32 33 34 35 36 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 31 def initialize(entries: {}, insertion_order: []) @entries = entries.freeze @insertion_order = insertion_order.freeze @chain = compile_chain @api = compile_api end |
Instance Attribute Details
#api ⇒ Module (readonly)
Returns combined API concern for all registered middlewares.
27 28 29 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 27 def api @api end |
#chain ⇒ Chain (readonly)
Returns the compiled middleware chain.
24 25 26 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 24 def chain @chain end |
#entries ⇒ Hash{Class => Entry} (readonly)
Returns middleware entries keyed by class.
18 19 20 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 18 def entries @entries end |
#insertion_order ⇒ Array<Class> (readonly)
Returns classes in registration order.
21 22 23 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 21 def insertion_order @insertion_order end |
Instance Method Details
#add(klass, args = [], before: [], after: []) ⇒ DependencyGraph
Returns a new graph with the middleware added. Merges constraints if the middleware is already registered. Auto-registers any middlewares referenced in before:/after: that aren't yet in the graph.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 47 def add(klass, args = [], before: [], after: []) # rubocop:disable Metrics/AbcSize new_entries = entries.transform_values do |entry| Entry.new( klass: entry.klass, args: entry.args, before: entry.before.dup, after: entry.after.dup ) end new_order = insertion_order.dup (before + after).each { |dep| ensure_registered(new_entries, new_order, dep) } if new_entries.key?(klass) entry = new_entries[klass] entry.args = args unless args.empty? entry.before.merge(before) entry.after.merge(after) else new_entries[klass] = Entry.new(klass: klass, args: args, before: Set.new(before), after: Set.new(after)) new_order << klass end self.class.new(entries: new_entries, insertion_order: new_order) end |
#remove(klass) ⇒ DependencyGraph
Returns a new graph with the middleware removed. Prunes all before:/after: references to it from remaining entries.
80 81 82 83 84 85 86 87 88 89 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 80 def remove(klass) raise ArgumentError, "#{klass} not found in graph" unless entries.key?(klass) new_entries = entries.except(klass).transform_values do |entry| Entry.new(klass: entry.klass, args: entry.args, before: entry.before - [klass], after: entry.after - [klass]) end new_order = insertion_order - [klass] self.class.new(entries: new_entries, insertion_order: new_order) end |
#replace(old_klass, new_klass, args = []) ⇒ DependencyGraph
Returns a new graph with old_klass swapped for new_klass. The replacement inherits old_klass's constraints and position. All references in other entries are updated.
100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/wayfarer/middleware/dependency_graph.rb', line 100 def replace(old_klass, new_klass, args = []) raise ArgumentError, "#{old_klass} not found in graph" unless entries.key?(old_klass) new_entries = swap_references(old_klass, new_klass) new_entries[new_klass] = Entry.new( klass: new_klass, args: args, before: entries[old_klass].before.dup, after: entries[old_klass].after.dup ) new_order = insertion_order.map { |k| k == old_klass ? new_klass : k } self.class.new(entries: new_entries, insertion_order: new_order) end |