-
Notifications
You must be signed in to change notification settings - Fork 446
Allow CancellationToken in streaming hub methods #2818
Changes from 5 commits
bde9383
52f5ace
9974b5d
218735d
bd3c6e1
9e6f0a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,8 +22,6 @@ internal class HubMethodDescriptor | |
public HubMethodDescriptor(ObjectMethodExecutor methodExecutor, IEnumerable<IAuthorizeData> policies) | ||
{ | ||
MethodExecutor = methodExecutor; | ||
ParameterTypes = methodExecutor.MethodParameters.Select(p => p.ParameterType).ToArray(); | ||
Policies = policies.ToArray(); | ||
|
||
NonAsyncReturnType = (MethodExecutor.IsMethodAsync) | ||
? MethodExecutor.AsyncResultType | ||
|
@@ -34,6 +32,25 @@ public HubMethodDescriptor(ObjectMethodExecutor methodExecutor, IEnumerable<IAut | |
IsChannel = true; | ||
StreamReturnType = channelItemType; | ||
} | ||
|
||
// Take out synthetic arguments that will be provided by the server, this list will be given to the protocol parsers | ||
ParameterTypes = methodExecutor.MethodParameters.Where(p => | ||
{ | ||
// Only streams can take CancellationTokens currently | ||
if (IsStreamable && p.ParameterType == typeof(CancellationToken)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we put this check into the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disregard this comment now. |
||
{ | ||
HasSyntheticArguments = true; | ||
return false; | ||
} | ||
return true; | ||
}).Select(p => p.ParameterType).ToArray(); | ||
|
||
if (HasSyntheticArguments) | ||
{ | ||
OriginalParameterTypes = methodExecutor.MethodParameters.Select(p => p.ParameterType).ToArray(); | ||
} | ||
|
||
Policies = policies.ToArray(); | ||
} | ||
|
||
private Func<object, CancellationToken, IAsyncEnumerator<object>> _convertToEnumerator; | ||
|
@@ -42,6 +59,8 @@ public HubMethodDescriptor(ObjectMethodExecutor methodExecutor, IEnumerable<IAut | |
|
||
public IReadOnlyList<Type> ParameterTypes { get; } | ||
|
||
public IReadOnlyList<Type> OriginalParameterTypes { get; } | ||
|
||
public Type NonAsyncReturnType { get; } | ||
|
||
public bool IsChannel { get; } | ||
|
@@ -52,6 +71,8 @@ public HubMethodDescriptor(ObjectMethodExecutor methodExecutor, IEnumerable<IAut | |
|
||
public IList<IAuthorizeData> Policies { get; } | ||
|
||
public bool HasSyntheticArguments { get; private set; } | ||
|
||
private static bool IsChannelType(Type type, out Type payloadType) | ||
{ | ||
var channelType = type.AllBaseTypes().FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ChannelReader<>)); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Channels; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
|
@@ -165,6 +166,10 @@ public Task ProtocolError() | |
return Clients.Caller.SendAsync("Send", new string('x', 3000), new SelfRef()); | ||
} | ||
|
||
public void InvalidArgument(CancellationToken token) | ||
{ | ||
} | ||
|
||
private class SelfRef | ||
{ | ||
public SelfRef() | ||
|
@@ -547,6 +552,51 @@ public async Task<ChannelReader<string>> LongRunningStream() | |
return Channel.CreateUnbounded<string>().Reader; | ||
} | ||
|
||
public ChannelReader<int> CancelableStream(CancellationToken token) | ||
{ | ||
var channel = Channel.CreateBounded<int>(10); | ||
|
||
Task.Run(() => | ||
{ | ||
_tcsService.StartedMethod.SetResult(null); | ||
token.WaitHandle.WaitOne(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turn this into a TCS and await it instead. Having spent a large part of the past few weeks fighting legacy SignalR tests that use WaitHandles, I don't want to start a precedent :). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest an making an extension method that does the conversion: |
||
channel.Writer.TryComplete(); | ||
_tcsService.EndMethod.SetResult(null); | ||
}); | ||
|
||
return channel.Reader; | ||
} | ||
|
||
public ChannelReader<int> CancelableStream2(int ignore, int ignore2, CancellationToken token) | ||
{ | ||
var channel = Channel.CreateBounded<int>(10); | ||
|
||
Task.Run(() => | ||
{ | ||
_tcsService.StartedMethod.SetResult(null); | ||
token.WaitHandle.WaitOne(); | ||
channel.Writer.TryComplete(); | ||
_tcsService.EndMethod.SetResult(null); | ||
}); | ||
|
||
return channel.Reader; | ||
} | ||
|
||
public ChannelReader<int> CancelableStreamMiddle(int ignore, CancellationToken token, int ignore2) | ||
{ | ||
var channel = Channel.CreateBounded<int>(10); | ||
|
||
Task.Run(() => | ||
{ | ||
_tcsService.StartedMethod.SetResult(null); | ||
token.WaitHandle.WaitOne(); | ||
channel.Writer.TryComplete(); | ||
_tcsService.EndMethod.SetResult(null); | ||
}); | ||
|
||
return channel.Reader; | ||
} | ||
|
||
public int SimpleMethod() | ||
{ | ||
return 21; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep this concept. It's cleaner than having the property called "HasCancellationToken"