class OpenUI::Rails::Stream::Accumulator
Client-side (Ruby) sequence accumulator mirroring what the browser must do: apply ordered deltas, ignore duplicates, and treat a missing sequence as “fetch the authoritative snapshot” rather than executing a malformed partial. Used by server tests and by hosts that consume their own stream.
Attributes
message_id[R]
source[R]
Public Class Methods
new(message_id:)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 14 def initialize(message_id:) @message_id = message_id @source = +"" @next_sequence = 0 @completed = false @error = nil @needs_snapshot = false end
Public Instance Methods
apply(envelope)
click to toggle source
@return [Symbol] one of :applied, :duplicate, :snapshot, :completed,
:error, :ignored
# File lib/openui/rails/stream/accumulator.rb, line 25 def apply(envelope) return :ignored unless envelope.message_id == message_id unless envelope.snapshot? return :duplicate if envelope.sequence < @next_sequence return :ignored if @completed || error? return :gap if @needs_snapshot if envelope.sequence > @next_sequence @needs_snapshot = true return :gap end end case envelope.type when Envelope::DELTA then apply_delta(envelope) when Envelope::SNAPSHOT then apply_snapshot(envelope) when Envelope::COMPLETED then apply_completed(envelope) when Envelope::ERROR then apply_error(envelope) else :ignored end end
apply_completed(envelope)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 72 def apply_completed(envelope) @completed = true @next_sequence = [ @next_sequence, envelope.sequence + 1 ].max :completed end
apply_delta(envelope)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 54 def apply_delta(envelope) @source << envelope.delta @next_sequence += 1 :applied end
apply_error(envelope)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 78 def apply_error(envelope) @error = envelope @next_sequence += 1 :error end
apply_snapshot(envelope)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 60 def apply_snapshot(envelope) minimum = @needs_snapshot ? @next_sequence - 1 : @next_sequence return :duplicate if envelope.sequence < minimum @source = +envelope.response.dup @next_sequence = envelope.sequence + 1 @needs_snapshot = false @completed = !envelope.streaming? @error = nil :snapshot end
completed?(= @completed)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 47 def completed? = @completed def error? = !@error.nil? def needs_snapshot? = @needs_snapshot def error = @error private def apply_delta(envelope) @source << envelope.delta @next_sequence += 1 :applied end def apply_snapshot(envelope) minimum = @needs_snapshot ? @next_sequence - 1 : @next_sequence return :duplicate if envelope.sequence < minimum @source = +envelope.response.dup @next_sequence = envelope.sequence + 1 @needs_snapshot = false @completed = !envelope.streaming? @error = nil :snapshot end def apply_completed(envelope) @completed = true @next_sequence = [ @next_sequence, envelope.sequence + 1 ].max :completed end def apply_error(envelope) @error = envelope @next_sequence += 1 :error end end end end end
error(= @error)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 50 def error = @error private def apply_delta(envelope) @source << envelope.delta @next_sequence += 1 :applied end def apply_snapshot(envelope) minimum = @needs_snapshot ? @next_sequence - 1 : @next_sequence return :duplicate if envelope.sequence < minimum @source = +envelope.response.dup @next_sequence = envelope.sequence + 1 @needs_snapshot = false @completed = !envelope.streaming? @error = nil :snapshot end def apply_completed(envelope) @completed = true @next_sequence = [ @next_sequence, envelope.sequence + 1 ].max :completed end def apply_error(envelope) @error = envelope @next_sequence += 1 :error end end
error?(= !@error.nil?)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 48 def error? = !@error.nil? def needs_snapshot? = @needs_snapshot def error = @error private def apply_delta(envelope) @source << envelope.delta @next_sequence += 1 :applied end def apply_snapshot(envelope) minimum = @needs_snapshot ? @next_sequence - 1 : @next_sequence return :duplicate if envelope.sequence < minimum @source = +envelope.response.dup @next_sequence = envelope.sequence + 1 @needs_snapshot = false @completed = !envelope.streaming? @error = nil :snapshot end def apply_completed(envelope) @completed = true @next_sequence = [ @next_sequence, envelope.sequence + 1 ].max :completed end def apply_error(envelope) @error = envelope @next_sequence += 1 :error end end end end
needs_snapshot?(= @needs_snapshot)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 49 def needs_snapshot? = @needs_snapshot def error = @error private def apply_delta(envelope) @source << envelope.delta @next_sequence += 1 :applied end def apply_snapshot(envelope) minimum = @needs_snapshot ? @next_sequence - 1 : @next_sequence return :duplicate if envelope.sequence < minimum @source = +envelope.response.dup @next_sequence = envelope.sequence + 1 @needs_snapshot = false @completed = !envelope.streaming? @error = nil :snapshot end def apply_completed(envelope) @completed = true @next_sequence = [ @next_sequence, envelope.sequence + 1 ].max :completed end def apply_error(envelope) @error = envelope @next_sequence += 1 :error end end end
next_sequence(= @next_sequence)
click to toggle source
# File lib/openui/rails/stream/accumulator.rb, line 46 def next_sequence = @next_sequence def completed? = @completed def error? = !@error.nil? def needs_snapshot? = @needs_snapshot def error = @error private def apply_delta(envelope) @source << envelope.delta @next_sequence += 1 :applied end def apply_snapshot(envelope) minimum = @needs_snapshot ? @next_sequence - 1 : @next_sequence return :duplicate if envelope.sequence < minimum @source = +envelope.response.dup @next_sequence = envelope.sequence + 1 @needs_snapshot = false @completed = !envelope.streaming? @error = nil :snapshot end def apply_completed(envelope) @completed = true @next_sequence = [ @next_sequence, envelope.sequence + 1 ].max :completed end def apply_error(envelope) @error = envelope @next_sequence += 1 :error end end end end