Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"sdk": {
"rollForward": "major",
"version": "11.0.100-rc.2.26504.105"
"version": "11.0.100-rc.3.26522.148"
},
"test": {
"runner": "Microsoft.Testing.Platform"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace Orleans.Runtime;

/// <summary>
/// Indicates that an observer is no longer reachable.
/// </summary>
/// <remarks>
/// Thrown when a call is made to an observer that is not (or is no longer) reachable,
/// for example because it was deregistered, garbage collected, or its hosting extension was disposed.
/// This exception is terminal: retrying the same call will not succeed!
/// </remarks>
[Serializable]
[GenerateSerializer]
#pragma warning disable RCS1194 // Implement exception constructors.
public sealed class ObserverNotReachableException : OrleansException
#pragma warning restore RCS1194 // Implement exception constructors.
{
/// <summary>
/// Initializes a new instance of the <see cref="ObserverNotReachableException"/> class.
/// </summary>
/// <param name="message">
/// The exception message.
/// </param>
internal ObserverNotReachableException(string message)
: base(message)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ObserverNotReachableException"/> class.
/// </summary>
/// <param name="message">
/// The message.
/// </param>
/// <param name="innerException">
/// The inner exception.
/// </param>
internal ObserverNotReachableException(string message, Exception innerException)
: base(message, innerException)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,3 @@ protected OrleansMessageRejectionException(SerializationInfo info, StreamingCont
}
}
}

14 changes: 12 additions & 2 deletions src/Orleans.Core/Runtime/AsyncEnumerableGrainExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ bool MarkAndCheck(Guid requestId)
/// <inheritdoc/>
public ValueTask<(EnumerationResult Status, object? Value)> StartEnumeration<T>(Guid requestId, [Immutable] IAsyncEnumerableRequest<T> request, CancellationToken cancellationToken)
{
if (request.MaxBatchSize <= 0)
{
return ThrowInvalidBatchSize(request);
}

ref var entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_enumerators, requestId, out bool exists);
if (exists)
{
Expand All @@ -130,10 +135,15 @@ bool MarkAndCheck(Guid requestId)
entry.Enumerator = enumerator;
entry.MaxBatchSize = request.MaxBatchSize;
entry.CancellationTokenSource = cts;
Debug.Assert(entry.MaxBatchSize > 0, "Max batch size must be positive.");
return MoveNextCore(ref entry, requestId, enumerator, cancellationToken);

static ValueTask<(EnumerationResult Status, object? Value)> ThrowAlreadyExists() => ValueTask.FromException<(EnumerationResult Status, object? Value)>(new InvalidOperationException("An enumerator with the same id already exists."));
static ValueTask<(EnumerationResult Status, object? Value)> ThrowAlreadyExists() =>
ValueTask.FromException<(EnumerationResult Status, object? Value)>(
new InvalidOperationException("An enumerator with the same id already exists."));

static ValueTask<(EnumerationResult Status, object? Value)> ThrowInvalidBatchSize(IAsyncEnumerableRequest<T> request) =>
ValueTask.FromException<(EnumerationResult Status, object? Value)>(
new ArgumentOutOfRangeException(nameof(request), request.MaxBatchSize, "Max batch size must be positive."));
}

/// <inheritdoc/>
Expand Down
Loading