class Protocol::HTTP2::Dependency
Attributes
The dependent children.
The connection this stream belongs to.
Stream
ID (odd for client initiated streams, even otherwise).
The parent dependency.
The weight of the stream relative to other siblings.
Public Class Methods
# File lib/protocol/http2/dependency.rb, line 26 def self.create(connection, id, priority = nil) weight = DEFAULT_WEIGHT exclusive = false if priority if parent = connection.dependencies[priority.stream_dependency] exclusive = priority.exclusive end weight = priority.weight end if parent.nil? parent = connection.dependency end dependency = self.new(connection, id, weight) connection.dependencies[id] = dependency if exclusive parent.exclusive_child(dependency) else parent.add_child(dependency) end return dependency end
# File lib/protocol/http2/dependency.rb, line 55 def initialize(connection, id, weight = DEFAULT_WEIGHT) @connection = connection @id = id @parent = nil @children = nil @weight = weight # Cache of any associated stream: @stream = nil # Cache of children for window allocation: @total_weight = 0 @ordered_children = nil end
Public Instance Methods
# File lib/protocol/http2/dependency.rb, line 72 def <=> other @weight <=> other.weight end
# File lib/protocol/http2/dependency.rb, line 113 def add_child(dependency) @children ||= {} @children[dependency.id] = dependency dependency.parent = self self.clear_cache! end
# File lib/protocol/http2/dependency.rb, line 95 def clear_cache! @ordered_children = nil end
Traverse active streams in order of priority and allow them to consume the available flow-control window. @param amount [Integer] the amount of data to write. Defaults to the current window capacity.
# File lib/protocol/http2/dependency.rb, line 206 def consume_window(size) # If there is an associated stream, give it priority: if stream = self.stream return if stream.window_updated(size) end # Otherwise, allow the dependent children to use up the available window: self.ordered_children&.each do |child| # Compute the proportional allocation: allocated = (child.weight * size) / @total_weight child.consume_window(allocated) if allocated > 0 end end
# File lib/protocol/http2/dependency.rb, line 99 def delete! @connection.dependencies.delete(@id) @parent.remove_child(self) @children&.each do |id, child| parent.add_child(child) end @connection = nil @parent = nil @children = nil end
An exclusive flag allows for the insertion of a new level of dependencies. The exclusive flag causes the stream to become the sole dependency of its parent stream, causing other dependencies to become dependent on the exclusive stream. @param parent [Dependency] the dependency which will be inserted, taking control of all current children.
# File lib/protocol/http2/dependency.rb, line 130 def exclusive_child(parent) parent.children = @children @children&.each_value do |child| child.parent = parent end parent.clear_cache! @children = {parent.id => parent} self.clear_cache! parent.parent = self end
# File lib/protocol/http2/dependency.rb, line 193 def ordered_children unless @ordered_children if @children and !@children.empty? @ordered_children = @children.values.sort @total_weight = @ordered_children.sum(&:weight) end end return @ordered_children end
# File lib/protocol/http2/dependency.rb, line 225 def print_hierarchy(buffer, indent: 0) buffer.puts "#{" " * indent}#{self}" @children&.each_value do |child| child.print_hierarchy(buffer, indent: indent+1) end end
The current local priority of the stream.
# File lib/protocol/http2/dependency.rb, line 175 def priority(exclusive = false) Priority.new(exclusive, @parent.id, @weight) end
Change the priority of the stream both locally and remotely.
# File lib/protocol/http2/dependency.rb, line 169 def priority= priority send_priority(priority) process_priority(priority) end
# File lib/protocol/http2/dependency.rb, line 145 def process_priority(priority) dependent_id = priority.stream_dependency if dependent_id == @id raise ProtocolError, "Stream priority for stream id #{@id} cannot depend on itself!" end @weight = priority.weight # We essentially ignore `dependent_id` if the dependency does not exist: if parent = @connection.dependencies[dependent_id] if priority.exclusive @parent.remove_child(self) parent.exclusive_child(self) elsif !@parent.equal?(parent) @parent.remove_child(self) parent.add_child(self) end end end
# File lib/protocol/http2/dependency.rb, line 183 def receive_priority(frame) self.process_priority(frame.unpack) end
# File lib/protocol/http2/dependency.rb, line 122 def remove_child(dependency) @children&.delete(dependency.id) self.clear_cache! end
# File lib/protocol/http2/dependency.rb, line 179 def send_priority(priority) @connection.send_priority(@id, priority) end
# File lib/protocol/http2/dependency.rb, line 91 def stream @stream ||= @connection.streams[@id] end
# File lib/protocol/http2/dependency.rb, line 221 def to_s "\#<#{self.class} id=#{@id} parent id=#{@parent&.id} weight=#{@weight} #{@children&.size || 0} children>" end
# File lib/protocol/http2/dependency.rb, line 187 def total_weight self.orderd_children return @total_weight end