Я хочу регистрировать каждый запрос на получение/выпуск в пуле asyncpg. Для этой цели я написал следующее
class CntPoolLogger:
def __init__(self) -> None:
self.conn_cnt = 0
self.event_cnt = 0
self.log_filename = "pool_usage.log"
self.file = open(self.log_filename, "a")
def log(self, event: str) -> None:
self.file.write(f"{self.event_cnt},{event},{self.conn_cnt}\n")
self.file.flush()
def acquire(self) -> None:
self.event_cnt += 1
self.conn_cnt += 1
self.log("acquire")
def release(self) -> None:
self.event_cnt += 1
self.conn_cnt -= 1
self.log("release")
def __del__(self):
self.file.close()
class LoggingPoolAcquireContext:
def __init__(self, pool_acquire_context: asyncpg.pool.PoolAcquireContext, cnt_logger: CntPoolLogger):
self.pool_acquire_context = pool_acquire_context
self.cnt_logger = cnt_logger
async def __aenter__(self, *args, **kwargs):
res = await self.pool_acquire_context.__aenter__(*args, **kwargs)
self.cnt_logger.acquire()
return res
async def __aexit__(self, *args, **kwargs):
await self.pool_acquire_context.__aexit__(*args, **kwargs)
self.cnt_logger.release()
def awaitable_wraper(self, awaitable):
??????
def __await__(self, *args, **kwargs):
self.cnt_logger.acquire()
return self.pool_acquire_context.__await__(*args, **kwargs)
class LoggingAsyncPGPool:
def __init__(self, pool, cnt_logger: CntPoolLogger):
self._pool = pool
self.cnt_logger = cnt_logger
def acquire(self, *args, **kwargs):
res = LoggingPoolAcquireContext(self._pool.acquire(*args, **kwargs), cnt_logger=self.cnt_logger)
return res
async def release(self, *args, **kwargs):
await self._pool.release(*args, **kwargs)
self.cnt_logger.release()
async def close(self, *args, **kwargs):
await self._pool.close()
Я хочу, чтобы счетчик обновлялся только после того, как соединение было фактически установлено/освобождено. Поэтому я обновляю счетчик только после операторов ожидания. Однако в этом методе
def __await__(self, *args, **kwargs):
self.cnt_logger.acquire()
return self.pool_acquire_context.__await__(*args, **kwargs)
мы возвращаем что-то ожидаемое, что следует ожидать где-то еще. Поэтому я обновляю счетчик, не зная, было ли на самом деле установлено соединение или нет.
Мой вопрос: есть ли способ как-то обернуть
self.pool_acquire_context.__await__(*args, **kwargs)
То есть, когда мы ожидаем его где-то в будущем, он обновляет счетчик только после установления соединения?






Как вы обнаружили, __await__ должен вернуть генератор. Итак, напишите одно:
def __await__(self, *args, **kwargs):
self.cnt_logger.acquire()
try:
return yield from self.pool_acquire_context.__await__(*args, **kwargs)
finally:
self.cnt_logger.release()