library
Concurrency
aiogram-input
Wait for the next Telegram message inside a handler without a full FSM — and without stealing unrelated updates.
Python · aiogram · Redis
A Telegram bot handler looks sequential:
await bot.send_message(...)
answer = await input.wait(...)
Updates are not sequential. While one coroutine is waiting, other chats and other handlers still receive events.
The library has to answer:
Which update belongs to which waiting handler?
A phone number or a one-time code does not deserve a full FSM. It does deserve a timeout, a filter, and a guarantee that unrelated messages still reach their handlers.
How a wait is resolved
User ──► Bot ──► Dispatcher
│
├── InputMiddleware
│ │
│ ▼
│ SessionManager.feed()
│ │
│ ├── no local wait → pass through
│ ├── filter reject → pass through
│ └── match wait_id → set_result, stop chain
│
└── InputWaiter injected via DI
setup_input(dispatcher) registers outer middleware and puts an InputWaiter in handler data (same idea as FSMContext).
wait() creates a wait_id, stores a marker, and asyncio.wait_fors a Future. Timeout returns None and always cleans up.
A second wait() on the same chat cancels the previous Future after the new marker is persisted.
Memory vs Redis
Redis does not hold the coroutine, the filter, or the Message.
| Memory | Redis | |
|---|---|---|
| Process-local | Yes | Marker only |
| Multi-worker visibility | No | Yes (markers) |
| Persistence | No | Marker + TTL |
| Awaiting coroutine | Local worker | Still local worker |
Operational note
Redis stores coordination state, not the suspended Python coroutine. Only the worker that called
wait()can resolve it.
pop_if on Redis is a Lua compare-and-delete so a stale wait_id cannot remove someone else’s marker.
Delivery
Published on PyPI (aiogram-input, optional [redis] extra).
| Workflow | Evidence |
|---|---|
| Unit | pytest on Python 3.10–3.14, coverage gate 95%, uv build |
| Redis | Redis 7 service, tests/integration |
| Publish | tag v* → uv publish |
What this demonstrates
Concurrency in an event-driven bot: middleware, in-process futures, marker-only shared storage, and an explicit limit — multi-worker setups share that someone is waiting, not the wait itself.