@ledsun blog

無味の味は佳境に入らざればすなわち知れず

Async::WebSocket gemの素振り その5

Async::WebSocket gemの素振り その4 - @ledsun blog でブロック呼び出しの入れ子が増えてしまったので、再度展開します。 理解しやすくするため、エラー処理も消します。

require 'async/websocket/response'
require 'async/websocket/connection'
require 'protocol/websocket/framer'
require 'protocol/websocket/extensions'
require "protocol/rack/request"
require "protocol/rack/adapter"

class App
  def self.call(env)
    req = ::Protocol::Rack::Request[env]
    res = ::Async::WebSocket::Response.for(req, protocol: nil) do |stream|
      framer = ::Protocol::WebSocket::Framer.new(stream)
      conn = ::Async::WebSocket::Connection.call framer,
                                                 nil,
                                                 ::Protocol::WebSocket::Extensions::Server.default

      # Echo back!
      while message = conn.read
        conn.write message
      end

      res
    end

    Protocol::Rack::Adapter.make_response(env, res)
  end
end

run App

コネクションを開く処理と、メッセージを受け取る処理が一箇所にある点に違和感があります。 一見すると、WebSocket経由のメッセージを全部受け取ってから、コネクション確立のレスポンスを返しそう見えます。

実際に動かすと、レスポンスは即座に返してコネクション確立して、メッセージを待ちます。 ::Async::WebSocket::Response.forの辺りに秘密がありそうです。 次はそこを見ていきます。