У меня есть ожидаемый объект, реализующий транзакцию запрос / ответ. Если время транзакции истекло, она будет повторена несколько раз перед тем, как отказаться и вызвать исключение.
Теперь предположим, что время всегда истекло, потому что у меня проблема с этим.
Когда задача запускает эту операцию, а затем отменяется, повторные попытки продолжаются. Это не то, что я хочу. Я хочу полностью отменить операцию.
Я подготовил MCVE и заметил, что будущее, которого ожидает задача, отменяется, когда задача отменяется. Это меня вполне устраивает, это может быть основой для решения, но я не понимаю, почему это будущее отменяется и могу ли я положиться на него.
import asyncio
RETRIES = 2
TIMEOUT = 1.0
class ClientRPC:
def __init__(self):
self._reply = None
self._retries = RETRIES
def __await__(self):
self.start()
return self._reply.__await__()
def start(self):
loop = asyncio.get_event_loop()
if self._reply is None:
self._reply = loop.create_future()
loop.call_later(TIMEOUT, self.handle_timeout)
# send a request
print("REQUEST")
def handle_timeout(self):
print("TIMEOUT")
print("future", repr(self._reply._state))
if self._retries > 0:
self._retries -= 1
self.start()
else:
self._reply.set_exception(RuntimeError("Timeout!"))
def handle_reply(self, reply):
# unused in this example
pass
async def client():
transaction = ClientRPC()
try:
reply = await transaction
except asyncio.CancelledError:
print("--CANCELLED--")
async def test():
loop = asyncio.get_event_loop()
task = loop.create_task(client())
await asyncio.sleep(1.5)
task.cancel()
await asyncio.sleep(3)
asyncio.run(test()) # python 3.7+
Вывод (обратная связь не указана):
REQUEST
TIMEOUT
future 'PENDING'
REQUEST
--CANCELLED--
TIMEOUT
future 'CANCELLED' <-- why?
REQUEST
TIMEOUT
future 'CANCELLED'
Exception in callback ClientRPC.handle_timeout()
handle:
asyncio.base_futures.InvalidStateError: invalid state