Reputation: 511
How should I register GrainService in Orleans 7.0?
I have GrainService:
public interface IAlfaGrainService : IGrainService
{
Task<IReadOnlyList<AlfaData>> TestMethod();
}
[Reentrant]
public class AlfaGrainService : GrainService, IAlfaGrainService
{
readonly IGrainFactory _grainFactory;
private readonly ILogger<AlfaGrainService> logger;
public AlfaGrainService(
IServiceProvider services,
Silo silo,
ILoggerFactory loggerFactory,
IGrainFactory grainFactory,
ILogger<AlfaGrainService> logger)
: base(GrainId.Create(nameof(AlfaGrainService), Guid.Empty.ToString()), silo, loggerFactory)
{
_grainFactory = grainFactory;
this.logger = logger;
}
public async Task<IReadOnlyList<AlfaData>> TestMethod()
{
logger.LogInformation("TestMethod() hit");
// TODO: custom logic here.
var data = new List<AlfaData> {
new AlfaData
{
Id = 1,
Name = "Test 1"
},
new AlfaData
{
Id = 2,
Name = "Test 2"
}
};
return await Task.FromResult(data);
}
}
GrainServiceClient (because I want to call GrainService from Grain):
public interface IAlfaGrainServiceClient : IGrainServiceClient<IAlfaGrainService>, IAlfaGrainService
{
}
public class AlfaGrainServiceClient : GrainServiceClient<IAlfaGrainService>, IAlfaGrainServiceClient
{
public AlfaGrainServiceClient(
IServiceProvider serviceProvider)
: base(serviceProvider)
{ }
public Task<IReadOnlyList<AlfaData>> TestMethod()
{
// Not sure how to get grainService reference:
var grainId = GrainId.Create(nameof(AlfaGrainService), Guid.Empty.ToString());
var service = GetGrainService(grainId);
// -------------------------------------
return service.TestMethod();
}
}
Grain from which I want to call GrainService (by proxy GrainServiceClient):
public interface IAlfaGrain: IGrainWithStringKey
{
Task<IReadOnlyList<AlfaData>> LoadData();
}
public class AlfaGrain: Grain, IAlfaGrain
{
private readonly IAlfaGrainServiceClient alfaGrainServiceClient;
public AlfaGrain(
IAlfaGrainServiceClient alfaGrainServiceClient)
{
this.alfaGrainServiceClient = alfaGrainServiceClient;
}
public async Task<IReadOnlyList<AlfaData>> LoadData()
{
return await alfaGrainServiceClient.TestMethod();
}
}
But If I register GrainService like this:
siloBuilder
.AddGrainService<AlfaGrainService>() // Register grainService like this ??
.ConfigureServices(services =>
{
services.AddSingleton<IAlfaGrainServiceClient, AlfaGrainServiceClient>();
});
I got error during starting app:
A suitable constructor for type 'GrainServiceApp.GrainServices.AlfaGrainService' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided.
Maybe because the GrainServiceFactory() (Orleans.Hosting.GrainServicesSiloBuilderExtensions) doesn't create instance with all ctor parameters.
Microsoft documentation is only about prev version of Orleans and thus doesn't work in my case.
Does anybody know how register GrainService in Orleans 7.0?
All code is on github
Upvotes: 0
Views: 661
Reputation: 511
I have already found the solution and it was quite simple.
I needed to inject GrainId into GrainService and pass it into the base class:
public AlfaGrainService(
GrainId grainId,
Silo silo,
IServiceProvider services,
ILoggerFactory loggerFactory,
ILogger<AlfaGrainService> logger)
: base(grainId, silo, loggerFactory)
{
this.logger = logger;
}
Then in GrainServiceClient I got GrainService instance by CurrentGrainReference.GrainId like this:
public Task<IReadOnlyList<AlfaData>> TestMethod()
{
var service = GetGrainService(CurrentGrainReference.GrainId);
return service.TestMethod();
}
I have updated the example on GitHub
Upvotes: 3