using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
#nullable enable
namespace OpenAI;
/// <summary>
/// Represents a collection of SSE events that can be enumerated as a C# async stream.
/// </summary>
internal class AsyncServerSentEventEnumerable : IAsyncEnumerable<ServerSentEvent>
{
private readonly Stream _contentStream;
public AsyncServerSentEventEnumerable(Stream contentStream)
{
Argument.AssertNotNull(contentStream, nameof(contentStream));
_contentStream = contentStream;
LastEventId = string.Empty;
ReconnectionInterval = Timeout.InfiniteTimeSpan;
}
public string LastEventId { get; private set; }
public TimeSpan ReconnectionInterval { get; private set; }
public IAsyncEnumerator<ServerSentEvent> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new AsyncServerSentEventEnumerator(_contentStream, this, cancellationToken);
}
private sealed class AsyncServerSentEventEnumerator : IAsyncEnumerator<ServerSentEvent>
{
private readonly ServerSentEventReader _reader;
private readonly AsyncServerSentEventEnumerable _enumerable;
private readonly CancellationToken _cancellationToken;
public ServerSentEvent Current { get; private set; }
public AsyncServerSentEventEnumerator(Stream contentStream,
AsyncServerSentEventEnumerable enumerable,
CancellationToken cancellationToken = default)
{
_reader = new(contentStream);
_enumerable = enumerable;
_cancellationToken = cancellationToken;
}
public async ValueTask<bool> MoveNextAsync()
{
ServerSentEvent? nextEvent = await _reader.TryGetNextEventAsync(_cancellationToken).ConfigureAwait(false);
_enumerable.LastEventId = _reader.LastEventId;
_enumerable.ReconnectionInterval = _reader.ReconnectionInterval;
if (nextEvent.HasValue)
{
Current = nextEvent.Value;
return true;
}
Current = default;
return false;
}
public ValueTask DisposeAsync()
{
// The creator of the enumerable has responsibility for disposing
// the content stream passed to the enumerable constructor.
#if NET6_0_OR_GREATER
return ValueTask.CompletedTask;
#else
return new ValueTask();
#endif
}
}
}openai/openai-dotnet
Publicmirrored from https://github.com/openai/openai-dotnetAvailable
src/Utility/AsyncServerSentEventEnumerable.cs
82lines · modepreview