=head1 NAME Sarze - An HTTP server =head1 SYNOPSIS XXX =head1 DESCRIPTION B<Sarze> is an HTTP server in Perl for L<AnyEvent>-aware applications providing L<Promise>-based API. The C<Sarze> module has the server class. =head1 METHODS There are following methods: =over 4 =item $p = Sarze->run (...) Run the server and return a promise that is resolved when the server is stopped. XXX =item $p = Sarze->start (...) Run the server and return a promise that is resolved with the server object when the server is ready to accept connections. XXX $p = $server->stop Schedule the server to stop and return a promise that is resolved when the server is stopped. XXX $p = $server->completed XXX Promise must be resolved with an object that is XXX =back =head1 OPTIONS Following options can be specified to C<start> and C<run> methods: =over 4 =item hostports => [[$host, $port], ...] (required) An array reference of zero or more host/port pair array references. A host/port pair must be either a pair of IP address and port (for TCP socket) or a pair of string C<unix/> and path to the file (for UNIX domain socket). =item psgi_file_name XXX If the PSGI script file C<psgi_file_name> is not found, or does not return a code reference, the promise returned by the C<start> or C<run> method is to be rejected with an error. If this option is specified, the C<eval> option must not be specified. =item eval XXX If the code throws, or if the code does not define the C<&main::psgi_app>, the promise returned by the C<start> or C<run> method is to be rejected with an error. If this option is specified, the C<psgi_file_name> option must not be specified. =item [DEPRECATED] worker_background_class => $class Specify the Perl class package name of the worker background class. If omitted, no worker background class is used. See L</WORKER BACKGROUND CLASS>. Use of this option is B<deprecated>. =item worker_state_class => $class, Specify the Perl class package name of the worker state class. If omitted, no worker state class is used. See L</WORKER STATE CLASS>. =item worker_state_params => $value Specify a C<worker_state_class> dependent value, typically a hash reference representing parameters. If omitted, defaulted to C<undef>. A copy of this value is accessible from the worker state class's C<start> method. See L</WORKER STATE CLASS>. As a clone of the value is transferred to forked worker processes, it must not contain any blessed object. =item max_worker_count => $non_negative_integer (Default: 3) Specify the number of the concurrent HTTP worker processes. =item max_counts => {custom => $non_negative_integer} (Default: 0) Specify the number of the concurrent custom worker processes. =item connections_per_worker XXX =item seconds_per_worker => $seconds (default: 60*10) After the seconds specified by this option has elapsed, a worker is switched to the shutdowning mode, where no incoming request is accepted anymore and any running handlers are expected to be stopped as far as possible. =item shutdown_timeout => $seconds (default: 60*1) After the seconds specified by this option has elapsed from it was switched to the shutdowning mode, a worker is uncleanly terminated even when there is a running handler. =back =head1 SERVER APPLICATION Sarze is a preforking HTTP server. It creates worker processes which handle coming HTTP connections. Sarze first loads the server code, as specified by C<eval> or C<psgi_file_name> option, and then forks that as workers. This means that any variable value initialized at loading is shared among the workers executed by a server. For example, ## Bad example! eval => q{ my $number = rand; ## This line is executed only once. return sub { return [200, [], [$number]]; }; }, ... always returns the same number. =head1 WORKERS A server instance consist of multiple worker processes. There are two types of workers: HTTP worker - An HTTP worker is expected to handle incoming HTTP connections. It can also handle any other application-specific jobs coming from application-dependent sources. Custom worker - A custom worker is expected to handle any application-specific jobs coming from application-dependent sources. The worker state class of an application that enables custom workers must implement the C<custom> method. =head1 WORKER STATE CLASS When a worker process is created, the B<worker state class>, as specified by the C<worker_state_class>, is instantiated. The class, if any, must be loaded as part of the server. That is, the code specified by the C<eval> or C<psgi_file_name> option must define the class either directly or by C<require>ing or C<use>ing other module. The class must have the B<C<start>> method. It is invoked when a worker process is created, before accepting connections. The method is invoked with arguments, given as following key/value pairs: =over 4 =item params => $value The value specified by the C<worker_state_params> option. =item signal => $signal An L<AbortSignal> object. The signal is aborted when the worker process is shutting down. =item state => $worker_state The worker process state object of the worker process. See L</WORKER PROCESS STATE OBJECT>. =back The C<start> method must return an array reference of two items: a worker state class dependent value and a promise (e.g. L<Promise>). The method can instead return a promise, which is to be resolved with an array reference. As no connection is handled before the C<start> method is returned (and the returned promise is resolved), the method can be used to run an application-dependent per-worker initialization steps. If the C<start> method throws or the returned promise is rejected, the worker process is terminated immediately. The first (index 0) item of the array reference returned by the C<start> method is set to the C<data> method's value of the worker process state object, such that it is accessible from PSGI application invocations. The C<signal> is signaled just before the worker is shutting down, after the completion of handling of all requests. This can be used to run an application-dependent per-worker cleanup steps. The second (index 1) item of the array reference returned by the C<start> method must be resolved when the application is ready to shutdown the worker process. The worker process delays the termination until the promise is resolved. Note that the promise can be resolved even before the C<signal>'s invocation in case there is no additional cleanup steps. The C<start> method is invoked before accepting any HTTP connections or invoking the C<custom> method. The C<custom> method is expect to run an application-dependent custom worker steps. It is invoked only once when a custom worker process is ready. It is invoked with an argument: The worker process state object of the worker process (See L</WORKER PROCESS STATE OBJECT>). The method may or may not return a promise. If it returns a promise, it may resolve the promise at any time. It should not throw. If it returns a promise, it should not be rejected. Note that when the method returns (or the promise is resolved) is irrelevant to the lifecycle of the custom worker process. =item WORKER PROCESS STATE OBJECT A worker process has a single B<worker process state object>. The C<start> method of a worker state class is invoked with C<state> option. A PSGI application is invoked with C<manakai.server.state> in the PSGI environment (see manakai PSGI extensions specification <https://wiki.suikawiki.org/n/manakai%20PSGI%20extensions> for details). The application can access to per worker process states and can control the worker process through this object. It has following methods: =over 4 =item $value = $state->data An application-specific value in the array reference returned by the C<start> method of the worker state class, defaulted to C<undef>. Though the value cannot be changed, by using a hash reference as the value, it can hold application specific states which can be get or set by the PSGI application. =item $state->abort ($reason?) Ask the worker process to terminate. The worker process then stops as soon as possible. If a non-C<undef> argument is specified, it is the "reason" exception object of abortion. This method should only be used in an exceptional situation, e.g. when the worker state class has detected a non-recoverable error. =item $state->features->{http} Returns whether it is an HTTP worker or not. Note that this flag is not initialized when the C<start> method is invoked. =item $state->features->{custom} Returns whether it is a custom worker or not. Note that this flag is not initialized when the C<start> method is invoked. =back =head1 WORKER BACKGROUND CLASS B<DEPRECATED>. When a worker state class is specified, the worker background class cannot be used. When a worker process is created, the B<worker background class>, as specified by the C<worker_background_class> option, is instantiated. The class, if any, must be loaded as part of the server. That is, the code specified by the C<eval> or C<psgi_file_name> option must define the class. The class must have the B<C<start>> method. It is invoked when a worker process is created. It must return an object, which is referred to as B<worker background object>. It may instead return a promise (e.g. L<Promise>) object, which must be resolved with an object. The C<start> method can be used to run any per-worker initialization steps. The worker will not accept any connection until the method returns an object (directly or indirectly through a promise). The method can also used to dispatch "background" steps running concurrently with HTTP connection processing. A worker background object must have a C<stop> method, which is invoked when the worker process is expected to be terminated. If there is any "background" steps, it should be terminated as soon as possible. This method might be invoked even when there are ongoing HTTP connections. A worker background object must have a C<completed> method, which must return a promise object. The promise must not be resolved until the worker background object is ready to be discarded. After the promise is resolved and all HTTP connections have been closed, the worker process exits. This can also be used by the worker background object to ask the worker to not accept incoming connections anymore. A worker background object may have a C<destory> method, which is invoked after all HTTP connections have been closed and the "background" steps have stopped and just before the termination of the worker process. This method can be used to run the shutdown steps for the worker process. It can return a promise object, which will delay the termination of the worker process until the resolution. A worker background object may have any other application specific methods. The worker background object of the worker process can be obtained from a PSGI application by invoking the C<background> method of the C<manakai.server.state> object (see manakai PSGI extensions specification <https://wiki.suikawiki.org/n/manakai%20PSGI%20extensions> for details) of the PSGI environment. If there is no worker background object, the C<background> method returns C<undef>. =head1 SIGNALS While the Sarze server is running, it receives signals. When it receives one of C<SIGINT>, C<SIGTERM>, or C<SIGQUIT>, it stops (as if the C<stop> method were invoked). It might not immediately terminate the server when it is still in the process of generating and sending a response. Once it receives a signal, it uninstalls the signal handler. By sending the second signal, which is processed by Perl's default handler, the entire application exits and Sarze's graceful termination process is aborted. =head1 DEPENDENCY The C<Sarze> module requires Perl 5.12 or later. It requires modules L<AnyEvnet::Socket> and L<AnyEvent::Fork>. It also requires following Perl modules (submodules of this Git repository): <https://github.com/wakaba/perl-promise> (which has L<Promise>, L<AbortController>, and L<AbortSignal>), <https://github.com/manakai/perl-streams>, <https://github.com/manakai/perl-web-datetime>, <https://github.com/manakai/perl-web-encodings>, <https://github.com/manakai/perl-web-resource>, and <https://github.com/manakai/perl-web-url>. =head1 HISTORY This module is available as a Git repository at <https://github.com/manakai/sarze>. It was transferred to the manakai project from <https://github.com/wakaba/sarze> on 26 April 2022. =head1 AUTHOR Wakaba <wakaba@suikawiki.org>. =head1 LICENSE Copyright 2016-2022 Wakaba <wakaba@suikawiki.org>. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut