Who is responsible for clean up of grpc::ServerUnaryReactor when using callback grpc service - grpc-c++

I am trying to implement grpc callback service and have derived my callback handler class from ServerUnaryReactor.
class AuthorisationCallbackHandler : public grpc::ServerUnaryReactor
As part of request processing we return grpc::ServerUnaryReactor* to grpc server/service.
grpc::ServerUnaryReactor* NetworkTrustCallbackService::CreateTrust(
::grpc::CallbackServerContext* context,
const ::networktrust::v1::CreateTrustRequest* request,
::networktrust::v1::CreateTrustResponse* responsePtr
)
{
const auto deviceId = request->ed25519_pk();
auto handlerPtr = std::make_unique<AuthorisationCallbackHandler>(_auth, deviceId);
return handlerPtr.release();
}
The destructor for AuthorisationCallbackHandler is never called so I assume we are still responsible for its clean up.
Is this correct and how to we know grpc is finished with it?
Is that what grpc::ServerUnaryReactor::OnDone is for?

Related

How to mock database in flutter

I tried to mock database to test my local api, i search in official document finding mockito which can work with remote api fine, but also can not work with local database out of box, is there any way to work around of it?
In these cases, you have two options (among many others). Even if my examples assume you're making HTTP calls, it doesn't matter. You can use these strategies regardless the specific use case I'm exposing!
The first one is using the "Strategy pattern" to create an interface for the API and then switch between a test and a production API. Here's a simple example:
abstract class HttpRepository {
const HttpRepository();
Future<Something> sendRequest();
}
You can now create 2 concrete classes: one is for the actual API call and the other is just a mock for tests.
/// Use this in your tests
class MockHttpRepository extends HttpRepository {
const MockHttpRepository();
#override
Future<Something> sendRequest() async {
// Simulating the HTTP call
await Future.delayed(const Duration(seconds: 2));
return Something();
}
}
/// Use this in your Flutter code to make the actual HTTP call or whatever else
class ApiHttpRepository extends HttpRepository {
const ApiHttpRepository();
#override
Future<Something> sendRequest() async {
// Doing a real HTTP call
final response = await makeGetOrPost();
return Something.withData(response);
}
}
In this way, you'll use ApiHttpRepository in your Flutter app and MockHttpRepository in tests. Use const constructors whenever possible.
The other way is using mocks to simulate fake HTTP calls or anything else. Basically, you're using when to "trap" a method call and return a fake response you can control.
// 1. "Enable" mocking on your type
class MockRepo extends Mock implements ApiHttpRepository {}
// 2. Mock methods
const ApiHttpRepository repo = MockRepo();
when(repo.sendRequest()).thenAnswer((_) async => Something());
In this case, we're using thenAnswer because the return type of sendRequest() is of type Future<T>. In your case, if you are reading data from a database you just need to:
Make your class "mockable" using extends Mock implements YourClass
Use when on the mockable instance and control the output
Make sure to use thenAnswer if the method returns a Future<T> and thenReturn in all the other cases.

Call not propagating to the service method from Spring Reactive Controller

I am a beginner to the spring webflux. We are currently migrating our application to Spring Webflux. No I have stuck with a problem. The following is my scenario.
The main service class is calling the following service classes for data
StudentService - return Mono<Student>
StaffService - return Mono<Staff>
Here I have a wrapper class StudentWithMentor to store the result from these service classes.
public class StudentWithMentor {
private Student student;
private Staff mentor;
}
Now in controller I am calling the above 2 services and map it into 'StudentWithMentor' in the following way
Mono<StudentWithMentor> studentWithMentorMono = Mono.just(new StudentWithMentor());
return studentWithMentorMono.map(s->{
studentService.getStudentById(id)
.doOnSuccess(s::setStudent)
.doOnSuccess(st->staffService.getStaffByGrade(st.getGrade()));
return s;
});
But when I call this endpoint I am getting the following result in postman
{
"student": null,
"mentor": null
}
Note: I am getting result from the underlying services when I debugg. But the call is returning before it process.
How can I achieve this in a complete non-blocking way.
Appreciates any help.
The easiest way will be to to use a zipWith operator to merge the results into StudentWithMentor object.
See the code below:
Mono<StudentWithMentor> studentWithMentorMono = studentService.getStudentById(id)
.zipWhen(student -> staffService.getStaffByGrade(student.getGrade()), StudentWithMentor::new);

How to implement custom actuator endpoint to check zookeeper health?

I would like to implement a custom endpoint class to check Zookeeper health:
http://localhost:8080/actuator/health/zookeeper
PROBLEM: Do I extend AbstractHealthIndicaitor or implement HealthIndicator class?
HealthIndicator class
public class CustomHealth implements HealthIndicator {
#Override
public Health health() {
int errorCode = check(); // perform some specific health check
if (errorCode != 0) {
return Health.down()
.withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
public int check() {
// Our logic to check zookeeper health
return 0;
}
}
AbstractHealthIndicator class
public class CustomHealth extends AbstractHealthIndicator {
#Override
protected void doHealthCheck(Health.Builder builder) throws Exception
{
// Our logic to check zookeeper health
}
}
I'm confused on which approach to use. I believe the logic to check zookeeper health is to simply declare an CuratorFramework object then do curator.getState() and return builder from there and for endpoint, attach #RestControllerEndPoint to declare the path. Please help!
It is up to you which one to choose, the difference is that AbstractHealthIndicator:
Provides you with the Health.Builder instance so you don't need to create one manually
Wraps doHealthCheck(builder) call with try-catch, that returns status DOWN if your healthcheck has failed with exception.
So in general the AbstractHealthIndicator is more convenient to use as you can skip error handling. Choose implementing raw HealthIndicator when you need to provide custom status details on exception.
For example of Zookeeper Health Indicator please refer to existing one provided with spring-cloud-zookeeper https://github.com/spring-cloud/spring-cloud-zookeeper/blob/master/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperHealthIndicator.java
Regarding the endpoint /actuator/health/zookeeper, I suggest you to use new feature introduced in SpringBoot 2.2.0 called Health Indicator Groups https://spring.io/blog/2019/10/16/spring-boot-2-2-0#health-indicator-groups
In short, if you use component scan and named custom health indicator MyZookeeperHealthIndicator, then add following properties to register it under custom zookeeper group:
management.endpoint.health.group.zookeeper.include=myZookeeper
After that, custom health details will be displayed under myZookeeper component at /actuator/health/zookeeper
Check following docs for more information:
Writing Custom HealthIndicators https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#writing-custom-healthindicators
Health Groups https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#health-groups

Locally cached stateManager... any risk in Service Fabric?

What seems to be just common practice could be the wrong thing to do in Service Fabric. I suspect the below code where stateManager is saved as local cache could cause a potential issue when the 'Startup' class is instantiated within the return statement of 'CreateServiceReplicaListeners()' method in 'SomeService' stateful service.
The situation that can happen is when the state manager is somehow re-instantiated. I need more explanation as to whether the below practice is the right thing to do or not. If not, what could be the best practice instead?
internal class SomeService : StatefulService
{
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new[]{
new ServiceReplicaListener(
initParams =>
new OwinCommunicationListener("SomeService", new Startup(this.StateManager), initParams))
};
}
}
}
public class Startup : IOwinAppBuilder
{
private readonly IReliableStateManager stateManager;
public Startup(IReliableStateManager stateManager)
{
this.stateManager = stateManager;
}
public void Configuration(IAppBuilder appBuilder)
{
// other initialization codes..
...
...
UnityConfig.RegisterComponents(config, this.stateManager);
appBuilder.UseWebApi(config);
}
}
Whenever a Stateful Service change roles it triggers a IStatefulServiceReplica.ChangeRoleAsync(ReplicaRole newRole, CancellationToken cancellationToken).
ChangeRoleAsync(..) ensure that the new role uses the correct communications doing the following:
Call CloseCommunicationListenersAsync(CancellationToken cancellationToken) to close any listeners open
Call OpenCommunicationListenersAsync(newRole, cancellationToken) for Primary or ActiveSecondary roles
The method OpenCommunicationListenersAsync() will call CreateServiceReplicaListeners() to get the listeners and call CreateCommunicationListener(serviceContext) for each returned listener to open the related endpoints.
Change of Roles is very common to happen during upgrades and Load Balancing, so this is a very common event.
In Summary,
Every time a Change of Role happens, CreateServiceReplicaListeners() will be called, ChangeRole does not shutdown the service, so it might have side effects, for example if you register dependencies in a DI container, you might face duplicate registrations.

Calling services from other application in the cluster

Is it possible to call services or actors from one application to another in a Service Fabric Cluster ? When I tryed (using ActorProxy.Create with the proper Uri), I got a "No MethodDispatcher is found for interface"
Yes, it is possible. As long as you have the right Uri to the Service (or ActorService) and you have access to the assembly with the interface defining your service or actor the it should not be much different than calling the Service/Actor from within the same application. It you have enabled security for your service then you have to setup the certificates for the exchange as well.
If I have a simple service defined as:
public interface ICalloutService : IService
{
Task<string> SayHelloAsync();
}
internal sealed class CalloutService : StatelessService, ICalloutService
{
public CalloutService(StatelessServiceContext context)
: base(context) { }
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
yield return new ServiceInstanceListener(this.CreateServiceRemotingListener);
}
public Task<string> SayHelloAsync()
{
return Task.FromResult("hello");
}
}
and a simple actor:
public interface ICalloutActor : IActor
{
Task<string> SayHelloAsync();
}
[StatePersistence(StatePersistence.None)]
internal class CalloutActor : Actor, ICalloutActor
{
public CalloutActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId) {}
public Task<string> SayHelloAsync()
{
return Task.FromResult("hello");
}
}
running in a application like this:
Then you can call it from another application within the same cluster:
// Call the service
var calloutServiceUri = new Uri(#"fabric:/ServiceFabric.SO.Answer._41655575/CalloutService");
var calloutService = ServiceProxy.Create<ICalloutService>(calloutServiceUri);
var serviceHello = await calloutService.SayHelloAsync();
// Call the actor
var calloutActorServiceUri = new Uri(#"fabric:/ServiceFabric.SO.Answer._41655575/CalloutActorService");
var calloutActor = ActorProxy.Create<ICalloutActor>(new ActorId(DateTime.Now.Millisecond), calloutActorServiceUri);
var actorHello = await calloutActor.SayHelloAsync();
You can find the right Uri in the Service Fabric Explorer if you click the service and look at the name. By default the Uri of a service is: fabric:/{applicationName}/{serviceName}.
The only tricky part is how do you get the interface from the external service to your calling service? You could simply reference the built .exe for the service you wish to call or you could package the assembly containing the interface as a NuGet package and put on a private feed.
If you don't do this and you instead just share the code between your Visual Studio solutions the Service Fabric will think these are two different interfaces, even if they share the exact same signature. If you do it for a Service you get an NotImplementedException saying "Interface id '{xxxxxxxx}' is not implemented by object '{service}'" and if you do it for an Actor you get an KeyNotfoundException saying "No MethodDispatcher is found for interface id '-{xxxxxxxxxx}'".
So, to fix your problem, make sure you reference the same assembly that is in the application you want to call in the external application that is calling.