Разбираем Server-Sent Events в ASP.NET Core и .NET 10. Продолжение
Начало
Обработка пропущенных событий
У простой конечной точки, которую мы создали ранее, есть один недостаток: ей не хватает отказоустойчивости.
Одна из самых больших проблем с потоками в реальном времени — это разрывы соединения. К тому времени, когда браузер автоматически переподключится, несколько событий могут быть уже отправлены и потеряны. Для решения этой проблемы в SSE есть встроенный механизм: заголовок Last-Event-ID. Когда браузер переподключается, он отправляет этот ID обратно на сервер.
В .NET 10 мы можем использовать тип SseItem<T> для добавления метаданных к нашим данным (идентификаторы и интервалы повторных попыток).
Можно создать простой буфер OrderEventBuffer в памяти, содержащий объекты типа SseItem<OrderPlacement>, и методом получения всех объектов после Last-Event-ID, который будет предоставляться браузером. Так мы можем «воспроизвести» пропущенные сообщения при переподключении:
app.MapGet("orders/realtime/with-replays", (
ChannelReader<OrderPlacement> reader,
OrderEventBuffer buffer,
[FromHeader(Name = "Last-Event-ID")]
string? lastEventId,
CancellationToken ct) =>
{
async IAsyncEnumerable<SseItem<OrderPlacement>>
StreamEvents()
{
// Повторяем пропущенные события
if (!string.IsNullOrWhiteSpace(lastEventId))
{
var missed = buffer.GetEventsAfter(lastEventId);
foreach (var m in missed)
yield return m;
}
// Выдаём события по мере их поступления в канал
await foreach (var order in
reader.ReadAllAsync(ct))
{
// Буфер назначает уникальный ID
var sseItem = buffer.Add(order);
yield return sseItem;
}
}
return TypedResults.ServerSentEvents(
StreamEvents(), "orders");
});Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/server-sent-events-in-aspnetcore-and-dotnet-10