# 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