withBacklog(CONCURRENCY_LIMIT) ->withReusePort() ->withTcpNoDelay() ) ]; $router = new Router; $config = Amp\Mysql\ConnectionConfig::fromString( 'host='.DB_HOST.' user=benchmarkdbuser password=benchmarkdbpass db=hello_world' ); $connector = new Amp\Mysql\CancellableConnector( new class implements Amp\Socket\Connector { public function connect( string $uri, ?Amp\Socket\ConnectContext $context = null, ?Amp\CancellationToken $token = null ): Amp\Promise { $context = $context ?? new Amp\Socket\ConnectContext; $context = $context->withTcpNoDelay(); return Amp\Socket\connector()->connect($uri, $context, $token); } } ); $mysql = new Amp\Mysql\Pool($config, 512, 300, $connector); // Case 1 - JSON $router->addRoute('GET', '/json', new class implements RequestHandler { public function handleRequest(Request $request): Promise { return new Success(new Response(200, [ 'Content-Type' => 'application/json', 'Server' => 'amphp', ], \json_encode([ 'message' => 'Hello, World!', ]))); } }); // Case 2 - Single Query $router->addRoute('GET', '/db', new class ($mysql) implements RequestHandler { private $mysql; public function __construct($mysql) { $this->mysql = $mysql; } public function handleRequest(Request $request): Promise { return new Coroutine($this->doHandleRequest($request)); } private function doHandleRequest($request) { $statement = yield $this->mysql->prepare('SELECT * FROM World WHERE id = ?'); $result = yield $statement->execute([mt_rand(1, 10000)]); yield $result->advance(); return new Response(200, [ 'Content-Type' => 'application/json', 'Server' => 'amphp', ], \json_encode($result->getCurrent())); } }); // Case 3 - Multiple Queries $router->addRoute('GET', '/queries', new class ($mysql) implements RequestHandler { private $mysql; public function __construct($mysql) { $this->mysql = $mysql; } public function handleRequest(Request $request): Promise { return new Coroutine($this->doHandleRequest($request)); } private function doHandleRequest($request) { $query = $request->getUri()->getQuery(); \parse_str($query, $queryParams); $queries = (int) ($queryParams['q'] ?? 1); if ($queries < 1) { $queries = 1; } elseif ($queries > 500) { $queries = 500; } $items = []; $statement = yield $this->mysql->prepare('SELECT * FROM World WHERE id = ?'); while ($queries--) { $items[] = new Coroutine($this->execute($statement)); } return new Response(200, [ 'Content-Type' => 'application/json', 'Server' => 'amphp', ], \json_encode(yield $items)); } private function execute($statement) { $result = yield $statement->execute([mt_rand(1, 10000)]); yield $result->advance(); return $result->getCurrent(); } }); // Case 4 - Fortunes $router->addRoute('GET', '/fortunes', new class ($mysql) implements RequestHandler { private $mysql; public function __construct($mysql) { $this->mysql = $mysql; } public function handleRequest(Request $request): Promise { return new Coroutine($this->doHandleRequest($request)); } private function doHandleRequest($request) { $result = yield $this->mysql->query('SELECT * FROM Fortune'); $items = []; while (yield $result->advance()) { $item = $result->getCurrent(); $items[$item['id']] = $item['message']; } $items[0] = 'Additional fortune added at request time.'; \asort($items); \ob_start(); require __DIR__ . '/fortunes.php'; return new Response(200, [ 'Content-Type' => 'text/html; charset=utf-8', 'Server' => 'amphp', ], \ob_get_clean()); } }); // Case 6 - Plaintext $router->addRoute('GET', '/plaintext', new class implements RequestHandler { public function handleRequest(Request $request): Promise { return new Success(new Response(200, [ 'Content-Type' => 'text/plain', 'Server' => 'amphp', ], 'Hello, World!')); } }); $logger = new Logger('Worker-' . Cluster::getId()); $logger->pushHandler(Cluster::createLogHandler()); $logger->info('Using ' . get_class(Amp\Loop::get())); $options = (new Options) ->withoutCompression() ->withConnectionLimit(CONCURRENCY_LIMIT) ->withConnectionsPerIpLimit(CONCURRENCY_LIMIT); $server = new Server($sockets, $router, $logger, $options); yield $server->start(); Amp\Loop::onSignal(\SIGINT, function (string $watcherId) use ($server) { Amp\Loop::cancel($watcherId); yield $server->stop(); }); });