orleans
orleans copied to clipboard
Unable to invoke GrainService from Filter
Hello!
From a a IIncomingGrainCallFilter
implementation, I'm able a IGrainServiceClient
implementation.
However, if I try to invoke any methods on the client I get this NRE:
Exception has occurred: CLR/Orleans.Runtime.OrleansLifecycleCanceledException
An exception of type 'Orleans.Runtime.OrleansLifecycleCanceledException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Lifecycle start canceled due to errors at stage 8000'
Inner exceptions found, see $exception in variables window for more details.
Innermost exception System.NullReferenceException : Object reference not set to an instance of an object.
at Orleans.Runtime.Services.GrainServiceClient`1.MapGrainReferenceToSiloRing(GrainReference grainRef)
at Orleans.Runtime.Services.GrainServiceClient`1.get_GrainService()
at Orleans.Dashboard.AgentServiceClient.ReportProfile() in /Users/guto/dev/repos/OrleansContrib/Orleans.Dashboard/src/Orleans.Dashboard.Agent/AgentServiceClient.cs:line 13
at Orleans.Dashboard.ProfileGrainInvocationFilter.<Invoke>d__3.MoveNext() in /Users/guto/dev/repos/OrleansContrib/Orleans.Dashboard/src/Orleans.Dashboard.Agent/Profiling/ProfileGrainInvocationFilter.cs:line 22
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.GrainMethodInvoker.<Invoke>d__21.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.InsideRuntimeClient.<Invoke>d__62.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Orleans.OrleansTaskExtentions.<<ToTypedTask>g__ConvertAsync|4_0>d`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Orleans.OrleansTaskExtentions.<WithTimeout>d__19`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Orleans.Runtime.MembershipService.SystemTargetBasedMembershipTable.<WaitForTableGrainToInit>d__6.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.MembershipService.SystemTargetBasedMembershipTable.<GetMembershipTable>d__5.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Orleans.Runtime.MembershipService.SystemTargetBasedMembershipTable.<InitializeMembershipTable>d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.MembershipService.MembershipOracle.<Start>d__32.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.Scheduler.AsyncClosureWorkItem.<Execute>d__8.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.OrleansTaskExtentions.<WithTimeout>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.Silo.<>c__DisplayClass72_0.<<OnRuntimeGrainServicesStart>g__StartMembershipOracle|1>d.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.Silo.<StartAsyncTaskWithPerfAnalysis>d__70.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.Silo.<OnRuntimeGrainServicesStart>d__72.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.Runtime.SiloLifecycleSubject.MonitoredObserver.<OnStart>d__9.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Orleans.LifecycleSubject.<WrapExecution>d__10.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Orleans.LifecycleSubject.<OnStart>d__5.MoveNext()
Can someone tell me if it is supported to invoke grain services from a filter? I know we can invoke grains but idk about grain services.
Thanks!
With 3.0 I'm getting NRE from MapGrainReferenceToSiloRing
for any reference to GrainService
in the client class. No filter involved. You don't even have to call a method, just checking whether GrainService
is null trips the exception, so it's apparently some init process in the property getter. I set up a bare-minimum example:
public interface IEchoGrainService : IGrainService
{
Task<string> Echo(string input);
}
public class EchoGrainService : GrainService, IEchoGrainService
{
public EchoGrainService(IConfiguration config, IGrainIdentity id, Silo silo, ILoggerFactory loggerFactory)
: base(id, silo, loggerFactory) { }
public Task<string> Echo(string input)
=> Task.FromResult(input);
}
public interface IEchoClient : IGrainServiceClient<IEchoGrainService>, IEchoGrainService
{ }
public class EchoClient : GrainServiceClient<IEchoGrainService>, IEchoClient
{
public EchoClient(IServiceProvider services)
: base(services) { }
public Task<string> Echo(string input)
=> GrainService.Echo(input); // throws NRE
// => $"null? {GrainService is null}"; // also throws NRE
}
Silo setup:
host.UseOrleans((hostContext, siloBuilder) =>
{
siloBuilder // omitted cluster setup etc.
.ConfigureApplicationParts(parts =>
{
parts.AddApplicationPart(typeof(EchoGrainService).Assembly).WithReferences();
parts.AddApplicationPart(typeof(EchoClient).Assembly).WithReferences();
})
.AddGrainService<EchoGrainService>()
.ConfigureServices((hostCtx, services) =>
services.AddSingleton<IEchoClient, EchoClient>()
);
}
Usage from an API controller:
[Route("[controller]")]
[ApiController]
public class TestController : ControllerBase
{
private readonly IEchoClient EchoClient;
public TestController(IEchoClient echoClient)
{
EchoClient = echoClient;
}
[HttpGet]
public Task<string> Get()
{
return EchoClient.Echo("ping");
}
}
Exception thrown for any reference to GrainService
in the client object:
NullReferenceException: Object reference not set to an instance of an object. Orleans.Runtime.Services.GrainServiceClient<TGrainService>.MapGrainReferenceToSiloRing(GrainReference grainRef) Orleans.Runtime.Services.GrainServiceClient<TGrainService>.get_GrainService() Test.SimpleGrainService.EchoClient.Echo(string input) in EchoClient.cs => GrainService.Echo(input); BTPAPI.Controllers.TestController.Get() in TestController.cs return EchoClient.Echo("ping"); lambda_method(Closure , object , object[] )
Minimal console-based reproduction using v3.0.2
https://github.com/MV10/OrleansGrainServiceTest
After looking at the GrainServiceClient code, it appears they can only be invoked by grains.
https://github.com/dotnet/orleans/blob/master/src/Orleans.Runtime/Services/GrainServiceClient.cs#L45 https://github.com/dotnet/orleans/blob/master/src/Orleans.Runtime/Services/GrainServiceClient.cs#L56
This can be inferred from comments midway through the docs ("Step 3. Create an interface for the GrainServiceClient to be used by other grains..." and "Step 5. Inject the grain service client into the other grains that need it.") but it seems like a pretty important restriction that should be stated up front.
I've replaced the usage of grain services on filters to use Channel<T>
...
@galvesribeiro I'm running into this issue as well. What do you mean by saying to use Channel<T>
?
@joshzngf sorry the long delay, never saw your reply.
I've started using https://docs.microsoft.com/en-us/dotnet/api/system.threading.channels.channel-1?view=net-6.0 instead of the grain service for this case since GrainServices can only be invoked from within a grain context.
We've moved this issue to the Backlog. This means that it is not going to be worked on for the coming release. We review items in the backlog at the end of each milestone/release and depending on the team's priority we may reconsider this issue for the following milestone.