public function update(Server $server) : Promise { switch ($this->state = $server->state()) { case Server::STARTING: $result = $this->application->onStart($this->proxy); if ($result instanceof \Generator) { return resolve($result); } break; case Server::STARTED: $f = (new \ReflectionClass($this))->getMethod("timeout")->getClosure($this); $this->timeoutWatcher = \Amp\repeat($f, 1000); break; case Server::STOPPING: $result = $this->application->onStop(); if ($result instanceof \Generator) { $promise = resolve($result); } elseif ($result instanceof Promise) { $promise = $result; } else { $promise = new Success(); } $promise->when(function () { $code = Code::GOING_AWAY; $reason = "Server shutting down!"; foreach ($this->clients as $client) { $this->close($client->id, $code, $reason); } }); \Amp\cancel($this->timeoutWatcher); $this->timeoutWatcher = null; return $promise; case Server::STOPPED: $promises = []; // we are not going to wait for a proper self::OP_CLOSE answer (because else we'd need to timeout for 3 seconds, not worth it), but we will ensure to at least *have written* it foreach ($this->clients as $client) { // only if we couldn't successfully send it in STOPPING $code = Code::GOING_AWAY; $reason = "Server shutting down!"; $result = $this->doClose($client, $code, $reason); if ($result instanceof \Generator) { $promise[] = resolve($result); } if (!empty($client->writeDeferredControlQueue)) { $promise = end($client->writeDeferredControlQueue)->promise(); if ($promise) { $promises[] = $promise; } } } $promise = any($promises); $promise->when(function () { foreach ($this->clients as $client) { $this->unloadClient($client); } }); return $promise; } return new Success(); }