Сцены и диалоги

В Raito два способа вести многошаговый диалог. Они похожи, но по-разному подходят к request-scoped зависимостям. Выбор в основном зависит от того, как ваше приложение выдаёт такие вещи, как сессии БД.

Ключевое различие

Сцена никогда не приостанавливает хендлер, который её начал. Каждый шаг это отдельный, полностью завершающийся хендлер. Между шагами состояние диалога живёт в FSM-хранилище, а корутины уже нет, поэтому любая зависимость на апдейт, которую даёт ваш middleware (сессия, транзакция, открытый файл), поднимается и закрывается вокруг каждого шага, ровно как для обычного сообщения.

Диалог (wait_for) делает наоборот: он приостанавливает текущую корутину хендлера до прихода следующего подходящего сообщения. Хендлер остаётся живым всё время, пока пользователь думает, а значит всё, что он держит (сессия, выданная на этот апдейт, привязанные к ней объекты), тоже остаётся живым.

Scene:         msg1 → [handler runs, returns] … msg2 → [fresh handler runs, returns]
               dependencies released between steps

Conversation:  msg1 → [handler suspends on wait_for] ……… msg2 → [handler resumes]
               dependencies held for the whole wait

Почему это важно

Если шагу нужна сессия БД и вы используете middleware, выдающий сессию на апдейт (частый паттерн SQLAlchemy), сцена даёт каждому шагу свежую сессию и возвращает её в пул, пока пользователь печатает. Диалог же держал бы одну сессию занятой весь диалог: нормально для быстрого обмена в два сообщения, расточительно (и рискованно для пула) для чего-то более длинного.

Как устроен каждый

Сцены построены на StatesGroup из aiogram: каждый шаг это настоящий FSM-стейт, а небольшой типизированный черновик SceneData хранится под FSM-ключом. Навигация (scene.next() / finish() / …) просто сохраняет черновик и переключает строку стейта; в памяти ничего не удерживается.

Диалоги используют asyncio.Future: wait_for регистрирует future, ставит маркерный FSM-стейт и ждёт его. Middleware завершает future, когда следующее сообщение проходит ваши фильтры, возобновляя приостановленную корутину.

Что когда выбирать

Выбирайте сцену, когда:

  • шаг обращается к request-scoped ресурсам (сессии БД, транзакции);

  • в диалоге больше пары шагов, есть ветвления или путь отмены;

  • вы хотите, чтобы каждый шаг был обычным, тестируемым хендлером.

Диалог подойдёт, когда:

  • ожидание короткое и хендлер не держит ничего дорогого;

  • вам нужен максимально простой «спросить одно и продолжить» прямо в хендлере.

API смотрите в руководствах scenes и conversations.