I have the following questions when looking at the 2.0 Docs on the topic of Reentrancy:
When an interface method is attributed [AlwaysInterleave], is it allowed to _be interleaved_ by other methods calls (meaning its execution is "interrupted" by execution of other methods), or can it _interleave into_ any other method calls (meaning that it will cause "interruption" in the execution of other methods). The example in the doc only contains examples of "GoFast only" and "GoSlow only", but not one with "GoFast and GoSlow mixed". For example, in the following case:
await Task.WhenAll(slowpoke.GoSlow(), slowpoke.GoFast());
is GoFast()'s execution started before GoSlow() ends?
what about:
await Task.WhenAll(slowpoke.GoFast(), slowpoke.GoSlow());
is GoSlow()'s execution started before GoFast() ends?
(And also to clarify, such interleaving behavior can only happen if there is asynchronous work in the currently-executing method, basically when the Grain's code is awaiting something else, right? I might be misusing the word "interrupt" as there is no pausing/resuming of currently executing code.)
When using a predicate to dynamically decide whether to allow interleaving of each request, the predicate only received an InvokeMethodRequest argument, which contains InterfaceId and MethodId as ints (I believe these are Orleans' internal data structures?). How do I determine which method on the Grain's interface is being invoked by this request? The example only demonstrates checking attributes on the request argument types. But if I cannot decide which interface method is being invoked, what is the point of checking the arguments? And what about argumentless interface methods?
Those aren't very clear to me as I learn to use Orleans. So could anyone from the team please clarify these and possibly add to the docs? Thanks!
- When an interface method is attributed [AlwaysInterleave], is it allowed to be interleaved by other methods calls (meaning its execution is "interrupted" by execution of other methods), or can it interleave into any other method calls (meaning that it will cause "interruption" in the execution of other methods).
The latter - whether or not interleaving is allowed in this case is determined by the attribute of the incoming request, not of the one currently executing. https://github.com/dotnet/orleans/blob/fb345cc47f56e4539d222e2e87856a22e7993158/src/Orleans.Runtime/Core/Dispatcher.cs#L327
(And also to clarify, such interleaving behavior can only happen if there is asynchronous work in the currently-executing method, basically when the Grain's code is awaiting something else, right?
Correct.
- When using a predicate to dynamically decide whether to allow interleaving of each request, the predicate only received an InvokeMethodRequest argument, which contains InterfaceId and MethodId as ints (I believe these are Orleans' internal data structures?). How do I determine which method on the Grain's interface is being invoked by this request?
InterfaceId and MethodId are hashes calculated at codegen time. One can take the values from generated code or try to reuse the hashing algorithm proprammatically.
Most helpful comment
The latter - whether or not interleaving is allowed in this case is determined by the attribute of the incoming request, not of the one currently executing. https://github.com/dotnet/orleans/blob/fb345cc47f56e4539d222e2e87856a22e7993158/src/Orleans.Runtime/Core/Dispatcher.cs#L327
Correct.
InterfaceIdandMethodIdare hashes calculated at codegen time. One can take the values from generated code or try to reuse the hashing algorithm proprammatically.