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.
88 89 90 91 |
# File 'lib/hyperion/http2_handler.rb', line 88 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.
86 87 88 |
# File 'lib/hyperion/http2_handler.rb', line 86 def real_socket @real_socket end |
Instance Method Details
#close ⇒ Object
116 117 118 |
# File 'lib/hyperion/http2_handler.rb', line 116 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).
124 125 126 127 |
# File 'lib/hyperion/http2_handler.rb', line 124 def closed? socket = @real_socket socket.closed? end |
#flush ⇒ Object
110 111 112 113 114 |
# File 'lib/hyperion/http2_handler.rb', line 110 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.
95 96 97 |
# File 'lib/hyperion/http2_handler.rb', line 95 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.
103 104 105 106 107 108 |
# File 'lib/hyperion/http2_handler.rb', line 103 def write(bytes) return 0 if bytes.nil? || bytes.empty? @writer_ctx.enqueue(bytes) bytes.bytesize end |