Class: Hyperion::Http2Handler::SendQueueIO
- Inherits:
-
Object
- Object
- Hyperion::Http2Handler::SendQueueIO
- Defined in:
- lib/hyperion/http2_handler.rb
Overview
IO-shaped wrapper passed to ‘Protocol::HTTP2::Framer` in place of the real socket. Reads are direct passthroughs (the read loop runs on the connection fiber and there’s only one reader). Writes are enqueued onto the connection-wide ‘WriterContext#queue`; the writer fiber owns the real socket and drains the queue.
We deliberately do NOT delegate ‘flush` to the real socket: writes don’t reach it from this object — the writer fiber does that. ‘flush` here is a no-op (the writer flushes after each batch).
‘closed?` reports the real socket’s state so protocol-http2’s read loop sees EOF the same way it always has.
Instance Attribute Summary collapse
-
#real_socket ⇒ Object
readonly
Returns the value of attribute real_socket.
Instance Method Summary collapse
- #close ⇒ Object
-
#closed? ⇒ Boolean
Multi-line on purpose: a single-line ‘def closed?; @real_socket.closed?; end` gets autocorrected to `delegate :closed?, to: :@real_socket` by Rails-aware ruby-lsp formatters, which is wrong here (this is a plain gem, no ActiveSupport on the dependency graph).
- #flush ⇒ Object
-
#initialize(real_socket, writer_ctx) ⇒ SendQueueIO
constructor
A new instance of SendQueueIO.
-
#read(*args) ⇒ Object
Framer’s read path — direct delegation.
-
#write(bytes) ⇒ Object
Framer’s write path — non-blocking handoff into the send queue.
Constructor Details
#initialize(real_socket, writer_ctx) ⇒ SendQueueIO
Returns a new instance of SendQueueIO.
89 90 91 92 |
# File 'lib/hyperion/http2_handler.rb', line 89 def initialize(real_socket, writer_ctx) @real_socket = real_socket @writer_ctx = writer_ctx end |
Instance Attribute Details
#real_socket ⇒ Object (readonly)
Returns the value of attribute real_socket.
87 88 89 |
# File 'lib/hyperion/http2_handler.rb', line 87 def real_socket @real_socket end |
Instance Method Details
#close ⇒ Object
117 118 119 |
# File 'lib/hyperion/http2_handler.rb', line 117 def close @real_socket.close unless @real_socket.closed? end |
#closed? ⇒ Boolean
Multi-line on purpose: a single-line ‘def closed?; @real_socket.closed?; end` gets autocorrected to `delegate :closed?, to: :@real_socket` by Rails-aware ruby-lsp formatters, which is wrong here (this is a plain gem, no ActiveSupport on the dependency graph).
125 126 127 128 |
# File 'lib/hyperion/http2_handler.rb', line 125 def closed? socket = @real_socket socket.closed? end |
#flush ⇒ Object
111 112 113 114 115 |
# File 'lib/hyperion/http2_handler.rb', line 111 def flush # No-op: bytes don't live in this object, they live in the queue. # The writer fiber flushes the real socket as it drains. nil end |
#read(*args) ⇒ Object
Framer’s read path — direct delegation. Single-reader (the conn fiber), so no contention here.
96 97 98 |
# File 'lib/hyperion/http2_handler.rb', line 96 def read(*args) @real_socket.read(*args) end |
#write(bytes) ⇒ Object
Framer’s write path — non-blocking handoff into the send queue. Backpressure is applied here: if pending bytes exceed the cap, the calling fiber parks on the drained notification until the writer has flushed enough to bring us below the threshold.
104 105 106 107 108 109 |
# File 'lib/hyperion/http2_handler.rb', line 104 def write(bytes) return 0 if bytes.nil? || bytes.empty? @writer_ctx.enqueue(bytes) bytes.bytesize end |