# frozen_string_literal: true# Released under the MIT License.# Copyright, 2018-2024, by Samuel Williams.# Copyright, 2018, by Mitsutaka Mimura.require_relative'../server'require_relative'../endpoint'require_relative'../configuration'require_relative'../service/server'require_relative'../environment/rackup'require'async/container'require'async/http/client'require'samovar'moduleFalconmoduleCommand# Implements the `falcon serve` command. Designed for *development*.## Manages a {Controller::Serve} instance which is responsible for running applications in a development environment.classServe<Samovar::Commandself.description="Run an HTTP server for development purposes."# The command line options.# @attribute [Samovar::Options]optionsdooption'-b/--bind <address>',"Bind to the given hostname/address.",default: "https://localhost:9292"option'-p/--port <number>',"Override the specified port.",type: Integeroption'-h/--hostname <hostname>',"Specify the hostname which would be used for certificates, etc."option'-t/--timeout <duration>',"Specify the maximum time to wait for non-blocking operations.",type: Float,default: niloption'-c/--config <path>',"Rackup configuration file to load.",default: 'config.ru'option'--preload <path>',"Preload the specified path before creating containers."option'--cache',"Enable the response cache."option'--forked | --threaded | --hybrid',"Select a specific parallelism model.",key: :container,default: :forkedoption'-n/--count <count>',"Number of instances to start.",default: Async::Container.processor_count,type: Integeroption'--forks <count>',"Number of forks (hybrid only).",type: Integeroption'--threads <count>',"Number of threads (hybrid only).",type: Integeroption'--[no]-restart',"Enable/disable automatic restart.",default: trueoption'--graceful-stop <timeout>',"Duration to wait for graceful stop.",type: Float,default: 1.0enddefcontainer_options@options.slice(:count,:forks,:threads,:restart)enddefendpoint_options@options.slice(:hostname,:port,:timeout)enddefenvironmentAsync::Service::Environment.new(Falcon::Environment::Server).with(Falcon::Environment::Rackup,root: Dir.pwd,verbose: self.parent&.verbose?,cache: @options[:cache],container_options: self.container_options,endpoint_options: self.endpoint_options,rackup_path: @options[:config],preload: [@options[:preload]].compact,url: @options[:bind],name: "server",endpoint: ->{Endpoint.parse(url,**endpoint_options)})enddefconfigurationConfiguration.new.tapdo|configuration|configuration.add(self.environment)endend# The container class to use.defcontainer_classcase@options[:container]when:threadedreturnAsync::Container::Threadedwhen:forkedreturnAsync::Container::Forkedwhen:hybridreturnAsync::Container::Hybridendend# The endpoint to bind to.defendpointEndpoint.parse(@options[:bind],**endpoint_options)end# The endpoint suitable for a client to connect.defclient_endpointAsync::HTTP::Endpoint.parse(@options[:bind],**endpoint_options)end# Create a new client suitable for accessing the application.defclientAsync::HTTP::Client.new(client_endpoint)end# Prepare the environment and run the controller.defcallConsole.logger.info(self)do|buffer|buffer.puts"Falcon v#{VERSION} taking flight! Using #{self.container_class}#{self.container_options}."buffer.puts"- Binding to: #{self.endpoint}"buffer.puts"- To terminate: Ctrl-C or kill #{Process.pid}"buffer.puts"- To reload configuration: kill -HUP #{Process.pid}"endAsync::Service::Controller.run(self.configuration,container_class: self.container_class,graceful_stop: @options[:graceful_stop])endendendend