fix(telegram): final message waits for the draft push in flight
This commit is contained in:
@@ -52,6 +52,7 @@ class Draft:
|
|||||||
self._broken = False
|
self._broken = False
|
||||||
self._last_sent = 0.0
|
self._last_sent = 0.0
|
||||||
self._task: asyncio.Task[None] | None = None
|
self._task: asyncio.Task[None] | None = None
|
||||||
|
self._inflight: asyncio.Future[None] | None = None
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
if self._task is None:
|
if self._task is None:
|
||||||
@@ -68,17 +69,26 @@ class Draft:
|
|||||||
self._dirty = True
|
self._dirty = True
|
||||||
|
|
||||||
async def stop(self) -> None:
|
async def stop(self) -> None:
|
||||||
|
"""Stop pushing and wait for the push in flight.
|
||||||
|
|
||||||
|
The final ``sendMessage`` must reach Telegram after the last draft,
|
||||||
|
or the draft lands on top of the message and lingers for its 30 s.
|
||||||
|
"""
|
||||||
if self._task is None:
|
if self._task is None:
|
||||||
return
|
return
|
||||||
self._task.cancel()
|
self._task.cancel()
|
||||||
with contextlib.suppress(asyncio.CancelledError):
|
with contextlib.suppress(asyncio.CancelledError):
|
||||||
await self._task
|
await self._task
|
||||||
self._task = None
|
self._task = None
|
||||||
|
if self._inflight is not None:
|
||||||
|
with contextlib.suppress(Exception):
|
||||||
|
await self._inflight
|
||||||
|
|
||||||
async def _run(self) -> None:
|
async def _run(self) -> None:
|
||||||
while not self._broken:
|
while not self._broken:
|
||||||
if self._dirty or time.monotonic() - self._last_sent > _KEEPALIVE:
|
if self._dirty or time.monotonic() - self._last_sent > _KEEPALIVE:
|
||||||
await self._push()
|
self._inflight = asyncio.ensure_future(self._push())
|
||||||
|
await asyncio.shield(self._inflight)
|
||||||
await asyncio.sleep(self._interval)
|
await asyncio.sleep(self._interval)
|
||||||
|
|
||||||
async def _push(self) -> None:
|
async def _push(self) -> None:
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class FakeBot:
|
|||||||
self.reactions: list[tuple[int, list[Any]]] = []
|
self.reactions: list[tuple[int, list[Any]]] = []
|
||||||
self.fail_sends = 0
|
self.fail_sends = 0
|
||||||
self.reject_html = False
|
self.reject_html = False
|
||||||
|
self.order: list[tuple[str, int | None]] = []
|
||||||
self._message_id = 100
|
self._message_id = 100
|
||||||
self.session = SimpleNamespace(close=self._close)
|
self.session = SimpleNamespace(close=self._close)
|
||||||
|
|
||||||
@@ -64,6 +65,7 @@ class FakeBot:
|
|||||||
message="Bad Request: can't parse entities",
|
message="Bad Request: can't parse entities",
|
||||||
)
|
)
|
||||||
self._message_id += 1
|
self._message_id += 1
|
||||||
|
self.order.append(("message", message_thread_id))
|
||||||
self.sent.append(
|
self.sent.append(
|
||||||
{
|
{
|
||||||
"chat_id": chat_id,
|
"chat_id": chat_id,
|
||||||
@@ -77,7 +79,9 @@ class FakeBot:
|
|||||||
return SimpleNamespace(message_id=self._message_id)
|
return SimpleNamespace(message_id=self._message_id)
|
||||||
|
|
||||||
async def send_message_draft(self, **kwargs: Any) -> bool:
|
async def send_message_draft(self, **kwargs: Any) -> bool:
|
||||||
|
await asyncio.sleep(0.08)
|
||||||
self.drafts.append(kwargs)
|
self.drafts.append(kwargs)
|
||||||
|
self.order.append(("draft", kwargs.get("message_thread_id")))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def create_forum_topic(self, chat_id, name, **_: Any) -> Any:
|
async def create_forum_topic(self, chat_id, name, **_: Any) -> Any:
|
||||||
@@ -244,6 +248,9 @@ async def test_general_is_master_and_reply_has_no_thread(stack: Stack) -> None:
|
|||||||
)
|
)
|
||||||
assert master is not None and master.kind == "master"
|
assert master is not None and master.kind == "master"
|
||||||
assert stack.bot.drafts and stack.bot.drafts[0]["chat_id"] == USER
|
assert stack.bot.drafts and stack.bot.drafts[0]["chat_id"] == USER
|
||||||
|
await asyncio.sleep(0.2)
|
||||||
|
final = max(i for i, o in enumerate(stack.bot.order) if o[0] == "message")
|
||||||
|
assert all(o[0] != "draft" for o in stack.bot.order[final:])
|
||||||
rows = await stack.world.conversations.queue.recent(master.id)
|
rows = await stack.world.conversations.queue.recent(master.id)
|
||||||
assert [r.origin for r in rows] == ["telegram"]
|
assert [r.origin for r in rows] == ["telegram"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user