Cancellation¶
TeleFlow передаёт cancellation через пайплайн обновлений. Хэндлер может принимать token текущего обновления, а Telegram-хелперы, привязанные к context, используют этот token автоматически, если ты не передал другой token явно.
Токены в хэндлерах¶
[Command("start")]
public Task Start(MessageContext ctx, CancellationToken ct)
{
return ctx.Message.AnswerAsync("Ready.");
}
Оставляй CancellationToken в async хэндлере, даже если маленький хэндлер пока его не использует. Хэндлер - это граница, где прикладные сервисы, репозитории, HTTP-клиенты, очереди и другая I/O-логика должны получать cancellation явно.
[Command("report")]
public async Task Report(MessageContext ctx, IReportService reports, CancellationToken ct)
{
var report = await reports.BuildAsync(ctx.Sender?.Id, ct);
await ctx.Message.AnswerAsync(report.Title);
}
Telegram-хелперы из context¶
Хелперы, которые TeleFlow отдаёт через context, привязаны к текущему обновлению:
await ctx.Message.AnswerAsync("Saved.");
await ctx.Callback.AnswerAsync();
await ctx.Callback.EditTextAsync("Done.");
await ctx.Chat.ActionAsync(ChatAction.Typing);
Если token не передан, эти helpers используют cancellation token текущего обновления. Token, который нельзя отменить, например CancellationToken.None, в этих Telegram-хелперах трактуется так же. Если ты передал cancelable token явно, он переопределит token обновления.
Вызовы через ctx.Bot¶
Сгенерированные методы клиента тоже принимают cancellation tokens, но ctx.Bot внутри хэндлера является update-scoped:
using TeleFlow.Telegram.Schema.Abstractions;
await ctx.Bot.SendMessageAsync(
chatId: IntegerString.From(ctx.TelegramChat.Id),
text: "Processing complete.");
Тот же generated method, вызванный на root ITelegramClient из DI, уже не привязан к обновлению. Вне context хэндлера передавай token явно.
public sealed class BroadcastService(ITelegramClient bot)
{
public Task SendAsync(long chatId, string text, CancellationToken ct)
{
return bot.SendMessageAsync(
chatId: IntegerString.From(chatId),
text: text,
cancellationToken: ct);
}
}
Рекомендуемое правило¶
Держи правило таким:
- оставляй
CancellationToken ctв async хэндлерах; - передавай
ctв свою I/O-логику: database calls, HTTP calls, очереди, storage, EF Core и background work; - не передавай
ctвctx.Message,ctx.Callback,ctx.Chatиctx.Botвнутри хэндлера, если тебе нужен token текущего обновления; - передавай явный token только если тебе намеренно нужны другие cancellation semantics;
- не прячь cancellation в application services через ambient state или static accessors.
Так маленький бот остаётся читаемым, а production code не начинает зависеть от скрытой магии.