Module: Takagi::Base::ServerLifecycle

Included in:
Takagi::Base
Defined in:
lib/takagi/base/server_lifecycle.rb,
sig/takagi/base/server_lifecycle.rbs

Overview

Manages server lifecycle operations: booting, running, and spawning servers.

Extracted from Base class to follow Single Responsibility Principle. Handles configuration loading, server instantiation, and process management.

Instance Method Summary collapse

Instance Method Details

#boot!(config_path: 'config/takagi.yml') ⇒ Object

Boots the application by loading configuration and running initializers

Parameters:

  • config_path (String) (defaults to: 'config/takagi.yml')

    Path to configuration file

  • config_path: (::String) (defaults to: 'config/takagi.yml')

Returns:

  • (Object)


15
16
17
18
# File 'lib/takagi/base/server_lifecycle.rb', line 15

def boot!(config_path: 'config/takagi.yml')
  Takagi.config.load_file(config_path) if File.exist?(config_path)
  Takagi::Initializer.run!
end

#build_servers(protocols, port, router: nil) ⇒ Array<Server>

Builds server instances for the given protocols

Parameters:

  • protocols (Array<Symbol>)

    Protocol identifiers

  • port (Integer)

    Port to bind to

  • router (Router, CompositeRouter, nil) (defaults to: nil)

    Custom router

  • router: (Router, CompositeRouter, nil) (defaults to: nil)

Returns:

  • (Array<Server>)

    Array of server instances



119
120
121
122
123
124
125
# File 'lib/takagi/base/server_lifecycle.rb', line 119

def build_servers(protocols, port, router: nil)
  threads = Takagi.config.threads
  processes = Takagi.config.processes
  Array(protocols).map(&:to_sym).map do |protocol|
    instantiate_server(protocol, port, threads: threads, processes: processes, router: router)
  end
end

#instantiate_server(protocol, port, threads:, processes:, router: nil) ⇒ Server

Instantiates a server for the given protocol using ServerRegistry

Parameters:

  • protocol (Symbol)

    Protocol identifier (:udp, :tcp, etc.)

  • port (Integer)

    Port to bind to

  • threads (Integer)

    Number of worker threads

  • processes (Integer)

    Number of worker processes (UDP only)

  • router (Router, CompositeRouter, nil) (defaults to: nil)

    Custom router

  • threads: (Object)
  • processes: (Object)
  • router: (Router, CompositeRouter, nil) (defaults to: nil)

Returns:

  • (Server)

    Server instance



135
136
137
138
139
140
141
142
143
144
# File 'lib/takagi/base/server_lifecycle.rb', line 135

def instantiate_server(protocol, port, threads:, processes:, router: nil)
  options = { port: port }
  options[:worker_threads] = threads
  options[:router] = router if router

  # UDP requires worker_processes, TCP doesn't use it
  options[:worker_processes] = processes if protocol == :udp
  Takagi.logger.debug("Instantiating server for #{protocol} on port #{port} with #{options}")
  Server::Registry.build(protocol, **options)
end

#run!(port: nil, config_path: 'config/takagi.yml', protocols: nil, router: nil, banner: true) ⇒ Object

Runs the server in the foreground (blocking)

Parameters:

  • port (Integer, nil) (defaults to: nil)

    Port to bind to (uses config if nil)

  • config_path (String) (defaults to: 'config/takagi.yml')

    Path to configuration file

  • protocols (Array<Symbol>, nil) (defaults to: nil)

    Protocols to enable (uses config if nil)

  • router (Router, CompositeRouter, nil) (defaults to: nil)

    Custom router (uses global if nil)

  • port: (Object, nil) (defaults to: nil)
  • config_path: (::String) (defaults to: 'config/takagi.yml')
  • protocols: (Object, nil) (defaults to: nil)
  • router: (Router, CompositeRouter, nil) (defaults to: nil)

Returns:

  • (Object)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/takagi/base/server_lifecycle.rb', line 27

def run!(port: nil, config_path: 'config/takagi.yml', protocols: nil, router: nil, banner: true)
  boot!(config_path: config_path)
  enable_plugins!(app: self)

  # Show startup banner
  if banner
    print_startup_banner(
      port: port || Takagi.config.port,
      protocols: protocols || Takagi.config.protocols,
      router: router || self.router  # Pass router to banner
    )
  end

  selected_port = port || Takagi.config.port
  servers = build_servers(protocols || Takagi.config.protocols, selected_port, router: router)
  run_servers(servers)
end

#run_servers(servers) ⇒ Object

Runs servers (single or multi-protocol)

Parameters:

  • servers (Array<Server>)

    Server instances to run

Returns:

  • (Object)


149
150
151
152
153
# File 'lib/takagi/base/server_lifecycle.rb', line 149

def run_servers(servers)
  return servers.first.run! if servers.length == 1

  Takagi::Server::Multi.new(servers).run!
end

#spawn!(port: 5683, protocols: nil) ⇒ Server, Multi

Spawns servers in background threads

Parameters:

  • port (Integer) (defaults to: 5683)

    Port to bind to

  • protocols (Array<Symbol>, nil) (defaults to: nil)

    Protocols to enable (uses config if nil)

  • port: (::Integer) (defaults to: 5683)
  • protocols: (Object, nil) (defaults to: nil)

Returns:

  • (Server, Multi)

    The spawned server instance



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/takagi/base/server_lifecycle.rb', line 50

def spawn!(port: 5683, protocols: nil)
  protos = if protocols
             Array(protocols)
           else
             Takagi.config.protocols
           end.map(&:to_sym)

  servers = protos.map do |proto|
    # Temporary backward compatibility - will use registry after transition
    proto == :tcp ? Takagi::Server::Tcp.new(port: port) : Takagi::Server::Udp.new(port: port)
  end

  if servers.length == 1
    server = servers.first
    thread = Thread.new { server.run! }
    # Store thread reference on the server instance for cleanup
    server.instance_variable_set(:@server_thread, thread)
    server
  else
    multi = Takagi::Server::Multi.new(servers)
    thread = Thread.new { multi.run! }
    # Store thread reference on the multi instance for cleanup
    multi.instance_variable_set(:@server_thread, thread)
    multi
  end
end