async def minecraft_ping(host, port, loop: asyncio.AbstractEventLoop = None) -> PingResult: if loop is None: loop = asyncio.get_event_loop() conn = MinecraftProtocol(loop) try: await loop.create_connection(lambda: conn, host, port) conn.write_packet(packets.handshake(47, host, port)) conn.write_packet(packets.request_status()) await conn.drain() packet = MinecraftIO(await conn.read_packet()) assert packet.read_varint() == 0 status = packet.read_string() ping_id = int(time.time() * 1000) conn.write_packet(packets.ping(ping_id)) await conn.drain() ping_send_time = loop.time() packet = MinecraftIO(await conn.read_packet()) latency = int((loop.time() - ping_send_time) * 1000) assert packet.read_varint() == 1 json_ = json.loads(status) return PingResult(json_, latency) finally: if conn.writer is not None: conn.writer.close()
async def run(argv, hosts, loop: asyncio.AbstractEventLoop): started = loop.time() drift = i = 0 while True: i += 1 interval = argv.interval - drift tasks = [ pingport(loop, host, interval, argv) for host in hosts if host in IP_CACHE ] await asyncio.gather(*tasks) drift = loop.time() - i * argv.interval - started
async def pingport(loop: asyncio.AbstractEventLoop, host: str, interval: int, argv): started = loop.time() elapsed = connected = 0 if host != IP_CACHE[host]: hostname = f"{host}:{argv.port} ({IP_CACHE[host]})" else: hostname = f"{host}:{argv.port}" with async_timeout.timeout(argv.timeout + 1): try: conn = asyncio.open_connection(IP_CACHE[host], argv.port, loop=loop) reader, writer = await asyncio.wait_for(conn, timeout=argv.timeout) except KeyboardInterrupt: print("Ok, boss, lets call it a day.") sys.exit(0) except Exception as e: if argv.verbose: print( f"Ping {hostname} failed... ({e.__class__.__name__}: {str(e)!r})" ) else: if argv.verbose: print(f"Ping {hostname} OK...") conn.close() connected = argv.timeout elapsed = loop.time() - started db = host2filename(argv, host) # Check previous pings if not connected: last_update = rrdtool.lastupdate(db) if 'ds' in last_update and last_update['ds']['connect']: sys.stderr.write(f"{hostname} is flappy\n") else: last = rrdtool.fetch(db, "MIN", "--start", str(-argv.interval * 6)) last_connections = [int(c) for c, t in last[2] if c is not None][-5:] if len(last_connections) == 5 and not any(last_connections): sys.stderr.write(f"{hostname} is down\n") # Record this attempt rrdtool.update( db, f"N:{int(connected)}:{elapsed}", ) return await asyncio.sleep(interval)
def loop2timestamp(loop_time: float, loop: asyncio.AbstractEventLoop = None) -> float: if loop is None: loop = asyncio.get_event_loop() now_loop = loop.time() now_timestamp = utctimestamp(datetime.utcnow()) return now_timestamp + (loop_time - now_loop)
def get_time_accelerator( loop: asyncio.AbstractEventLoop, instant_step: bool = False ) -> typing.Callable[[float], typing.Awaitable[None]]: """ Returns an async advance() function This provides a way to advance() the BaseEventLoop.time for the scheduled TimerHandles made by call_later, call_at, and call_soon. """ original = loop.time _drift = 0 loop.time = functools.wraps(loop.time)(lambda: original() + _drift) async def accelerate_time(seconds: float) -> None: nonlocal _drift if seconds < 0: raise ValueError(f'Cannot go back in time ({seconds} seconds)') _drift += seconds await asyncio.sleep(0) async def accelerator(seconds: float): steps = seconds * 10.0 if not instant_step else 1 for _ in range(max(int(steps), 1)): await accelerate_time(seconds / steps) return accelerator
def __init__(self, *, loop: ALoop): self._subscription_waiters = [] # type: List[Future] self._assignment_waiters = [] # type: List[Future] self._loop = loop # type: ALoop # Fetch contexts self._fetch_count = 0 self._last_fetch_ended = loop.time()
def call_later( cb: Callable[[], Any], timeout: float, loop: asyncio.AbstractEventLoop) -> Optional[asyncio.TimerHandle]: if timeout is not None and timeout > 0: when = loop.time() + timeout if timeout > 5: when = ceil(when) return loop.call_at(when, cb) return None
async def _monitor_lag(self, loop: AbstractEventLoop): log.info("Monitoring async lag started") while loop.is_running(): start = loop.time() await sleep(self._interval) # The closer this gap is to our intended sleep time # the less load the system is under. Large gaps mean # the running loop is dealing with a lot of work time_slept = loop.time() - start self.lag = time_slept - self._interval log.debug(f"Current async lag (ms): {self.lag * 1000}") tasks = [task for task in Task.all_tasks(loop) if not task.done()] self.active_tasks = len(tasks) log.debug(f"Active tasks: {self.active_tasks}") self._warn(tasks) log.info("Monitoring async lag stopped")
def weakref_handle( ob: object, name: str, timeout: float, loop: asyncio.AbstractEventLoop) -> Optional[asyncio.TimerHandle]: if timeout is not None and timeout > 0: when = loop.time() + timeout if timeout >= 5: when = ceil(when) return loop.call_at(when, _weakref_handle, (weakref.ref(ob), name)) return None
def get_time_accelerator( loop: asyncio.AbstractEventLoop, now: typing.Optional[float] = None ) -> typing.Callable[[float], typing.Awaitable[None]]: """ Returns an async advance() function This provides a way to advance() the BaseEventLoop.time for the scheduled TimerHandles made by call_later, call_at, and call_soon. """ _time = now or loop.time() loop.time = functools.wraps(loop.time)(lambda: _time) async def accelerate_time(seconds: float) -> None: nonlocal _time if seconds < 0: raise ValueError(f'Cannot go back in time ({seconds} seconds)') _time += seconds await past_events() await asyncio.sleep(0) async def past_events() -> None: while loop._scheduled: timer: asyncio.TimerHandle = loop._scheduled[0] if timer not in loop._ready and timer._when <= _time: loop._scheduled.remove(timer) loop._ready.append(timer) if timer._when > _time: break await asyncio.sleep(0) async def accelerator(seconds: float): steps = seconds * 10.0 for _ in range(max(int(steps), 1)): await accelerate_time(0.1) return accelerator
async def _exec( self, loop: asyncio.AbstractEventLoop, suppress_exceptions: ExceptionsType = (), ) -> None: self._statistic.call_count += 1 delta: float = -loop.time() try: await self.func(*self.args, **self.kwargs) except suppress_exceptions: self._statistic.fail += 1 return except asyncio.CancelledError: raise except Exception: self._statistic.fail += 1 log.exception("Recurring task error:") else: self._statistic.done += 1 finally: delta += loop.time() self._statistic.sum_time += delta
def get_left_time(task: asyncio.Task = None, loop: asyncio.AbstractEventLoop = None): if loop is None: loop = get_running_loop() if task is None: task = current_task() out_time = getattr(task, _MODULE_TIMEOUT, None) if not out_time: return sys.maxsize now_time = loop.time() left_time = out_time - now_time if left_time < 0: return 0 return left_time
def set_timeout(task: asyncio.Task, timeout: [float, int], loop: asyncio.AbstractEventLoop = None, timeout_cancel=True): assert isinstance(timeout, (float, int)) if loop is None: loop = get_running_loop() now_time = loop.time() out_time = now_time + timeout if timeout_cancel: if timeout <= 0: task.cancel() return unset_timeout(task) handle = loop.call_at(out_time, task.cancel) setattr(task, _MODULE_TIMEOUT_HANDLE, handle) setattr(task, _MODULE_TIMEOUT, out_time)
def __init__(self, loop: AbstractEventLoop, initial_time: int): loop.time = self self._loop = loop self._time = initial_time
def update_screen(self, end_time, loop: asyncio.AbstractEventLoop, screen: Screen): screen.draw_next_frame() if loop.time() < end_time: loop.call_later(0.05, self.update_screen, end_time, loop, screen) else: loop.stop()
def _timeout_to_deadline(loop: asyncio.AbstractEventLoop, timeout: Optional[float]) -> Optional[float]: if timeout is None: return None return loop.time() + timeout