async def request(self, srv, method, *params, req_id=None, timeout=DEFAULT_TIMEOUT_SECS): if not self.connected: raise ConnectionError('websocket closed') method = srv + '::' + method if not req_id: req_id = uuid.uuid4().hex payload = { 'jsonrpc': '2.0', 'id': req_id, 'method': method, 'params': params } channel = Channel(1) self.waiters[req_id] = channel try: await self.ws.send_json(payload) r = await asyncio.wait_for(channel.get(), timeout=timeout) return r except ChannelClosed: raise ConnectionError('websocket closed on sending req') finally: channel.close()
def test_double_close(self): channel = Channel(1, loop=self.loop) self.assertFalse(channel.closed()) channel.close() self.assertTrue(channel.closed()) channel.close() self.assertTrue(channel.closed())
def test_get_nowait_raises_closed(self): channel = Channel(1, loop=self.loop) channel.put_nowait("foo") channel.close() item = channel.get_nowait() self.assertEqual(item, "foo") self.assertRaises(ChannelClosed, lambda: channel.get_nowait())
def test_async_iterator(self): """ Test that we can even construct a Channel """ channel = Channel(loop=self.loop) [channel.put_nowait(i) for i in range(10)] channel.close() async def test(): s = 0 async for item in channel: s += item return s result = self.ruc(test()) self.assertEqual(result, sum(range(10)))
async def request(self, srv, method, *params, req_id=None): if not self.connected: raise ConnectionError('websocket closed') url = urljoin(self.url_prefix, '/jsonrpc/2.0/api') method = srv + '::' + method if not req_id: req_id = uuid.uuid4().hex payload = {'id': req_id, 'method': method, 'params': params} channel = Channel(1) self.waiters[req_id] = channel try: await self.ws.send_json(payload) r = await channel.get() #del self.waiters[req_id] return r except ChannelClosed: raise ConnectionError('websocket closed on sending req') finally: channel.close()
class Worker(): HEALTH_CHECK_INTERVAL = datetime.timedelta(seconds=60) def __init__(self, conn, tm): self.conn = conn self.logger = logging.getLogger('universe') self.last_health_check = now() self.ticks = 0 self.queue = Channel(128) self.tm = tm self.health = [] async def run(self): async with self.conn.acquire() as conn: self.logger.info('Clock fast-forward') await conn.execute('UPDATE objects SET refreshed_at = NOW()') for i in range(min(multiprocessing.cpu_count(), 4)): asyncio.ensure_future(self._dequeue()) try: while True: await self._calc_stats() await self._tick() except asyncio.CancelledError: self.logger.info("Terminating gravity worker") self.queue.close() await self.queue.join() return async def _calc_stats(self): dt = now() - self.last_health_check if dt > Worker.HEALTH_CHECK_INTERVAL: tps = int(self.ticks / Worker.HEALTH_CHECK_INTERVAL.total_seconds()) self.logger.debug('Current TPS: {} ({} ticks)'.format( tps, self.ticks, )) self.health = [tps, self.ticks] self.last_health_check = now() self.ticks = 0 if tps <= Universe.LAG_TPS: await self._solar_flare() async def _solar_flare(self): async with self.conn.acquire() as conn: await conn.execute(''' DELETE FROM objects WHERE id IN (SELECT id FROM objects WHERE created_at < now() - interval '15 minutes' ORDER BY created_at asc)''') async def _dequeue(self): async with self.conn.acquire() as conn: async for obj in self.queue: await conn.execute( ''' UPDATE objects SET position = $2, velocity = $3, mass = $4, refreshed_at = $5 WHERE id = $1 ''', obj.idx, obj.position, obj.velocity, obj.mass, obj.refreshed_at) async def _tick(self): async with self.conn.acquire() as conn: rows = await conn.fetch(''' SELECT * FROM objects ORDER BY refreshed_at asc LIMIT 1024 ''') if len(rows) == 0: await asyncio.sleep(1 / Universe.GOOD_TPS) for row in rows: obj = object_from_row(row) tc = await self.tm.pop(obj.idx) obj.update(tc) await self.queue.put(obj) # avoid dupes in queue while not self.queue.empty(): await asyncio.sleep(1 / Universe.GOOD_TPS) self.ticks += 1
def test_put_when_closed(self): channel = Channel(1, loop=self.loop) channel.close() self.assertRaises(ChannelClosed, lambda: self.ruc(channel.put("foo")))