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.
86 87 88 89 |
# File 'lib/hyperion/http2_handler.rb', line 86 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.
84 85 86 |
# File 'lib/hyperion/http2_handler.rb', line 84 def real_socket @real_socket end |
Instance Method Details
#close ⇒ Object
114 115 116 |
# File 'lib/hyperion/http2_handler.rb', line 114 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).
122 123 124 125 |
# File 'lib/hyperion/http2_handler.rb', line 122 def closed? socket = @real_socket socket.closed? end |
#flush ⇒ Object
108 109 110 111 112 |
# File 'lib/hyperion/http2_handler.rb', line 108 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.
93 94 95 |
# File 'lib/hyperion/http2_handler.rb', line 93 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.
101 102 103 104 105 106 |
# File 'lib/hyperion/http2_handler.rb', line 101 def write(bytes) return 0 if bytes.nil? || bytes.empty? @writer_ctx.enqueue(bytes) bytes.bytesize end |