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.MapGrainReferenceToSiloRing(GrainReference grainRef)
Orleans.Runtime.Services.GrainServiceClient.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
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>...
Most helpful comment
I've replaced the usage of grain services on filters to use
Channel<T>...