Class: Raptor::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/raptor/server.rb

Overview

Accepts client connections and dispatches them into the request pipeline. Skips acceptance when the reactor backlog is high so an overloaded process leaves connections for peers that can absorb them (via shared ‘SO_REUSEPORT` listeners).

Supports TCP, Unix, and SSL listeners. SSL handshakes are offloaded to the thread pool so a slow client can’t pin the server thread. For HTTP/1.1 the first request is parsed inline and dispatched straight to the thread pool; HTTP/2 (negotiated via ALPN) is registered with the reactor for frame processing.

Examples:

binder = Binder.new(["tcp://0.0.0.0:3000"])
reactor = Reactor.new(ractor_pool, thread_pool, client_options: {})
request = Request.new(app, 3000)
server = Server.new(binder, reactor, thread_pool, request, client_options: { first_data_timeout: 30 })
server.run
# ... later
server.shutdown

Constant Summary collapse

HTTP_SCHEME =
"http"
HTTPS_SCHEME =
"https"
H2_PROTOCOL =
"h2"
DEFAULT_REMOTE_ADDR =
"127.0.0.1"
DEFAULT_SERVER_NAME =
"localhost"

Instance Method Summary collapse

Constructor Details

#initialize(binder, reactor, thread_pool, request, client_options:) ⇒ void

Creates a new Server instance.

Parameters:

  • binder (Binder)

    the binder managing listening sockets

  • reactor (Reactor)

    the reactor for handling client connections

  • thread_pool (AtomicThreadPool)

    thread pool for application processing

  • request (Request)

    the HTTP/1.1 request handler

  • client_options (Hash)

    client timeout configuration, used to bound TLS handshakes



55
56
57
58
59
60
61
62
# File 'lib/raptor/server.rb', line 55

def initialize(binder, reactor, thread_pool, request, client_options:)
  @binder = binder
  @reactor = reactor
  @thread_pool = thread_pool
  @request = request
  @client_options = client_options
  @running = AtomicBoolean.new(true)
end

Instance Method Details

#runThread

Starts the server’s main accept loop in a new thread.

The accept loop polls listening sockets for ready connections and accepts them when system capacity allows. It checks reactor backlog before accepting to prevent overload. This provides natural load balancing across multiple worker processes through backpressure control.

Returns:

  • (Thread)

    the thread running the accept loop



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/raptor/server.rb', line 74

def run
  Thread.new(@binder.listeners, @reactor, @running) do |server_sockets, reactor, running|
    Thread.current.name = self.class.name

    while running.true?
      begin
        ready_servers, _, _ = IO.select(server_sockets, nil, nil, 1)
      rescue IOError, Errno::EBADF
        break
      end

      next unless ready_servers
      next if @reactor.backlog >= (@thread_pool.size * 1.2).ceil

      ready_servers.each do |listener|
        accept_connection(listener, reactor)
      end
    end
  end
end

#shutdownvoid

This method returns an undefined value.

Gracefully shuts down the server.

Stops accepting new connections and closes all listening sockets. The server thread will exit after handling any in-flight accept operations.



103
104
105
106
# File 'lib/raptor/server.rb', line 103

def shutdown
  @running.make_false
  @binder.close
end