async def _timeout_force_close(self): try: await asyncio.wait_for(self.wait_for_ended(), timeout=self._timeout) except asyncio.TimeoutError: logger.info(f"Timeout - force-ending {self}") self.close()
async def stop_all(self): logger.info("Stopping all replays") self._closing = True replays = self._replays.values() for replay in replays: replay.close() await self._replays.wait_until_empty()
async def close_all(self): logger.info("Closing all connections") for c in self._connections: c.close(immediate=True) if self._connections: await asyncio.wait( [connection.wait_closed() for connection in self._connections])
async def start(self): self._connection_pool = await self._pool_builder( host=self._config.host, port=self._config.port, user=self._config.user, password=self._config.password, db=self._config.name) logger.info("Initialized database connection pool")
async def handle_connection(self, connection): self._connections.add(connection) try: header = await self._handle_initial_data(connection) await self._pass_control_to_replays(connection, header) metrics.served_conns.labels(result="Success").inc() except BadConnectionError as e: logger.info(f"Bad connection was dropped; {e.__class__}: {str(e)}") metrics.served_conns.labels(result=e.type_name()).inc() finally: self._connections.remove(connection) connection.close()
async def _write_replay(self, connection): position = 0 while True: dlen = await self._stream.wait_for_data(position) if dlen == 0: break data = self._stream.data[position:position + dlen] position += dlen conn_open = await connection.write(data) if not conn_open: break logger.info((f"Finished writing to {connection}, " f"sent {position} data bytes total"))
async def _lifetime(self): await self.merger.wait_for_ended() canon_stream = self.merger.canonical_stream logger.info((f"{self} write phase ended, " f"data length: {len(canon_stream.data)}")) await self.bookkeeper.save_replay(self._game_id, self.merger.canonical_stream) await self.sender.wait_for_ended() self.merger.canonical_stream.discard_all() for coro in self._lifetime_coroutines: coro.cancel() self._ended.set() logger.debug(f"Lifetime of {self} ended")
def main(): logger.info(f"FAF replay server version {VERSION} starting") try: config = get_program_config() except ConfigurationError: logger.exception("Invalid configuration was provided!") return 1 try: logger.setLevel(config.log_level) server = Server.build(config=config) loop = asyncio.get_event_loop() setup_signal_handler(server, loop) loop.run_until_complete(server.run()) loop.close() return 0 except Exception: logger.exception("Critical server error!") return 1
async def handle_connection(self, connection): conn_gauge = metrics.ConnectionGauge() conn_gauge.set_initial() self._connections.add(connection) try: header = await self._handle_initial_data(connection) conn_gauge.set_active(header.type) await self._replays.handle_connection(header, connection) metrics.successful_conns.inc() # Ignore empty connections, these happen often and are not errors except EmptyConnectionError as e: pass except BadConnectionError as e: if not connection.closed_by_us(): logger.info((f"Connection was dropped: {connection}\n" f"Reason: {short_exc(e)}")) metrics.failed_conns(e).inc() else: # Error from connections we force-closed don't matter metrics.successful_conns.inc() finally: await self._cleanup_connection(connection) conn_gauge.clear()
async def _force_closing(self, timeout): await asyncio.sleep(timeout) logger.info(f"Timeout - force-ending {self}") self.close()
def close_all(self): logger.info("Closing all connections") for connection in self._connections: connection.close()
async def stop(self): self._server.close() await self._server.wait_closed() logger.info(f"Stopped listening on {self._server_port}")
async def start(self): self._connection_pool = await self._pool_starter() logger.info("Initialized database connection pool")
async def _remove_replay_when_done(self, game_id, replay): await replay.wait_for_ended() self._replays.pop(game_id, None) logger.info(f"Replay removed: id {game_id}") metrics.running_replays.dec() metrics.finished_replays.inc()
def _create(self, game_id): replay = self._replay_builder(game_id) self._replays[game_id] = replay asyncio.ensure_future(self._remove_replay_when_done(game_id, replay)) logger.info(f"New Replay created: id {game_id}") metrics.running_replays.inc()
async def stop(self): self._connection_pool.close() await self._connection_pool.wait_closed() self._connection_pool = None logger.info("Closed database connection pool")
async def start(self): self._server = await asyncio.streams.start_server( self._make_connection, port=self._server_port) logger.info(f"Started listening on {self._server_port}")