Class: Takagi::Application

Inherits:
Object
  • Object
show all
Defined in:
lib/takagi/application.rb

Overview

Application class for modular controller-based apps

Application provides a centralized way to mount and manage multiple controllers, auto-load controller files, and run the server.

Examples:

Simple application

class MyApp < Takagi::Application
  configure do
    load_controllers TelemetryController, ConfigController
  end
end

MyApp.run!(port: 5683)

With auto-loading

class MyApp < Takagi::Application
  configure do
    auto_load 'app/controllers/**/*_controller.rb'
  end
end

MyApp.run!

Defined Under Namespace

Classes: ConfigContext, DiscoveryController

Class Method Summary collapse

Class Method Details

.configHash

Get the application’s configuration

Returns:

  • (Hash)

    Configuration hash



73
74
75
76
77
78
79
80
# File 'lib/takagi/application.rb', line 73

def config
  @config ||= {
    controllers: [],
    auto_load_patterns: [],
    allocation_mode: :automatic,  # :manual or :automatic
    total_threads: nil             # For automatic mode
  }
end

.configure { ... } ⇒ Object

Configure the application

Examples:

configure do
  load_controllers TelemetryController, ConfigController
  auto_load 'app/controllers/**/*_controller.rb'
end

Yields:

  • Block for configuration DSL



91
92
93
# File 'lib/takagi/application.rb', line 91

def configure(&block)
  ConfigContext.new(self).instance_eval(&block) if block
end

.controllersArray<Class>

Get all loaded controller classes

Returns:

  • (Array<Class>)

    List of controller classes



188
189
190
# File 'lib/takagi/application.rb', line 188

def controllers
  config[:controllers]
end

.load_controllers!void

This method returns an undefined value.

Load and mount all registered controllers



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/takagi/application.rb', line 98

def load_controllers!
  # Load auto-discovered controllers
  auto_load_controllers! if config[:auto_load_patterns].any?

  # Mount discovery controller first (so it's available at /.well-known/core)
  # Store reference to composite router for discovery endpoint
  DiscoveryController.app_router = router
  router.mount(DiscoveryController)

  # Mount all registered controllers
  config[:controllers].each do |controller_class|
    router.mount(controller_class)
  end
end

.routerCompositeRouter

Get the application’s composite router

Returns:



66
67
68
# File 'lib/takagi/application.rb', line 66

def router
  @router ||= CompositeRouter.new
end

.run!(**options) ⇒ void

This method returns an undefined value.

Run the application server

Examples:

MyApp.run!(port: 5683, protocols: [:udp, :tcp])

Parameters:

  • options (Hash)

    Server options (port, protocols, etc.)



171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/takagi/application.rb', line 171

def run!(**options)
  # Load all controllers
  load_controllers!

  # Start controller worker pools
  start_all_workers!

  # Use the composite router instead of global singleton
  options[:router] = router

  # Delegate to server lifecycle (same as Takagi::Base)
  Base::ServerLifecycle.run!(**options)
end

.shutdown_all_workers!void

This method returns an undefined value.

Shutdown all controller worker thread pools



156
157
158
159
160
161
162
# File 'lib/takagi/application.rb', line 156

def shutdown_all_workers!
  all_controllers = config[:controllers] + [DiscoveryController]

  all_controllers.each do |controller_class|
    controller_class.shutdown_workers! if controller_class.workers_running?
  end
end

.start_all_workers!void

This method returns an undefined value.

Start worker thread pools for all controllers

Allocates thread pool resources based on allocation_mode:

  • :manual - Controllers use their explicit thread_count or profile settings

  • :automatic - Divides total_threads proportionally by profile weights



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/takagi/application.rb', line 120

def start_all_workers!
  # Use app config first, fall back to global config
  mode = config[:allocation_mode] || Takagi.config.allocation.mode
  total_threads = config[:total_threads] || Takagi.config.allocation.total_threads
  controllers_to_allocate = config[:controllers] + [DiscoveryController]

  # Calculate allocations based on mode
  allocations = Controller::ResourceAllocator.allocate(
    controllers: controllers_to_allocate,
    mode: mode,
    total_threads: total_threads,
    protocol: :tcp  # TCP uses threads, UDP uses processes
  )

  # Validate allocations if automatic mode with total_threads specified
  if mode == :automatic && total_threads
    Controller::ResourceAllocator.validate!(allocations, total_threads: total_threads)
  end

  # Start each controller's thread pool
  allocations.each do |controller_class, allocation|
    threads = allocation[:threads]
    next unless threads && threads > 0

    controller_class.start_workers!(
      threads: threads,
      name: controller_class.name.split('::').last
    )

    Takagi.logger.info "Allocated #{threads} threads to #{controller_class.name} (mode: #{mode})"
  end
end