class Capsium::Reactor
Constants
- DEFAULT_CACHE_CONTROL
- DEFAULT_PORT
- PACKAGE_SAVE_PATTERN
Attributes
cache_control
[R]
String?
mounts
[R]
Array[Mount]
package
[R]
Package
package_path
[R]
String
port
[R]
Integer
registry
[R]
(Capsium::Registry | String)?
routes
[R]
Package::Routes
server
[R]
untyped
server_thread
[R]
Thread?
started_at
[R]
Time
store
[R]
(Package::Store | String)?
workdir
[R]
String
Public Class Methods
(?package: (Package | String)? package, ?mounts: Array[Mount]? mounts, ?port: Integer port, ?cache_control: String? cache_control, ?do_not_listen: bool do_not_listen, ?store: (Package::Store | String)? store, ?deploy: (Hash[String, untyped] | String)? deploy, ?registry: (Capsium::Registry | String)? registry, ?workdir: String? workdir) → void
Source
# File lib/capsium/reactor.rb, line 63 def initialize(package: nil, mounts: nil, port: DEFAULT_PORT, cache_control: DEFAULT_CACHE_CONTROL, do_not_listen: false, store: nil, deploy: nil, registry: nil, workdir: nil) @store = store @registry = registry @workdir = workdir || Dir.mktmpdir("capsium-reactor-") @own_workdir = workdir.nil? @mounts = mounts || [Mount.new(path: Mount::ROOT_PATH, package: package, store: store, registry: registry)] @mounts.each { |mount| mount.attach_workdir(@workdir) } @port = port @cache_control = cache_control @started_at = Time.now @metrics = Metrics.new @log_buffer = Capsium::LogBuffer.new @deploy_config = Deploy.load(deploy) setup_server(do_not_listen) load_state mount_routes @log_buffer.add("reactor started: " \ "#{@mounts.map(&:summary).join(', ')} on port #{@port}") end
Serves one or more packages: either a single package (directory, .cap file or Package, mounted at “/”) or a list of mounts (Reactor::Mount) resolved by longest-prefix matching. workdir holds the writable overlays (ARCHITECTURE.md section 5a) and saved packages; it defaults to a temporary directory the reactor removes on cleanup.
(String own, String theirs) → bool
Source
# File lib/capsium/reactor/htpasswd.rb, line 149 def self.secure_compare(own, theirs) own.bytesize == theirs.bytesize && OpenSSL.fixed_length_secure_compare(own, theirs) end
Constant-time string comparison (length-check first).
Public Instance Methods
() → void
Source
# File lib/capsium/reactor.rb, line 124 def cleanup @mounts.each { |mount| mount.package.cleanup } FileUtils.remove_entry(@workdir) if @own_workdir && File.directory?(@workdir) end
Cleans up every mounted package (Package#cleanup for all) and the workdir when the reactor created it.
(untyped request, untyped response) → untyped
Source
# File lib/capsium/reactor.rb, line 94 def handle_request(request, response) dispatch_request(request, response) ensure record_request(request, response) end
Entry point for every mounted path: dispatches the request, then records it in the request metrics and the log buffer.
() → void
Source
# File lib/capsium/reactor.rb, line 100 def mount_routes paths = Introspection::PATHS + Introspection::REACTOR_PATHS + @authenticator.endpoints paths.concat(@mounts.flat_map(&:server_paths)) paths.each do |path| @server.mount_proc(path.to_s) { |req, res| handle_request(req, res) } end # WEBrick longest-prefix matching: catches every "/package/...". @server.mount_proc(Introspection::PACKAGE_MOUNT) do |req, res| handle_request(req, res) end end
() → Thread
Source
# File lib/capsium/reactor.rb, line 113 def restart_server @server.shutdown @server_thread&.join load_packages setup_server(false) mount_routes @server_thread = start_server end
() → untyped
Source
# File lib/capsium/reactor.rb, line 86 def serve trap("INT") { shutdown_server } @server_thread = start_server start_listener end