gRPC_python: switching Servicer while gRPC server is running in python ? (simulation - real mode )

22 views
Skip to first unread message

larath...@gmail.com

unread,
Jan 22, 2019, 10:36:08 AM1/22/19
to grpc.io
Hello gRPC_python developers,

for our new, open lab device automation standard (https://gitlab.com/SiLA2/sila_python) we need to run the devices in two modes: a simulation mode and a real mode (with the same set of remote calls, but in the first case it shall just return simulated responses in the second it should communicate with the hardware. 
My first idea was to create two almost identical gRPC servicer python classes in separated modules, like:

in hello_sim.py:
class SayHello(pb2_grpc.SayHelloServicer):
   #... implementation of the simulation servicer
   def SayHello(self, request, context):
     # simulation code ...

in hello_real.py:
class SayHello(pb2_grpc.SayHelloServicer):
   #... implementation of the real servicer
   def SayHello(self, request, context):
     # real hardware code

and then, after creating the gRPC server in server.py I could switch between simulation and real mode by
exchanging re-registration of the servcier at the gRPC server like:

       grpc_server = GRPCServer(ThreadPoolExecutor(max_workers=10)) 

       sh_sim = SayHello_sim.SayHello()
       sh_real = SayHello_real.SayHello()

       SayHell_pb2_grpc.add_SayHelloServicer_to_server(sh_sim, grpc_server)

      grpc_server.run()
  
      ..... and later, still while the same grpc server is running, re-register, like
 
      SayHell_pb2_grpc.add_SayHelloServicer_to_server(sh_real, grpc_server)

     to be able to call the real hardware code or by exchanging the reference to the servicer object, like

       grpc_server = GRPCServer(ThreadPoolExecutor(max_workers=10)) 

       sh_sim = SayHello_sim.SayHello()
       sh_real = SayHello_real.SayHello()

       sh_current = sh_sim

       SayHell_pb2_grpc.add_SayHelloServicer_to_server(sh_current , grpc_server)

      grpc_server.run()
  
      ..... and then later, still while the same grpc server is running, re-register, like
 
     sh_current = sh_real    
     #  so that the server would just use the other servicer object for the next calls ..

     but both strategies are not working :(

My question now is: how can I re-register Servicer code with the same set of calls, but calling different methods carrying the same name while the same gRPC server is running ?
(I know, that I could stop the server, re-register and restart, but then I would loose the connection to the client)

Do you have any suggestions for a clean and elegant solution ?

Thanx a lot in advance, 
Lara

larath...@gmail.com

unread,
Jan 23, 2019, 6:02:44 AM1/23/19
to grpc.io
I colleague of mine provided my with a good suggestion:
One could use the dependency injection concept (s. https://en.wikipedia.org/wiki/Dependency_injection), like:

class SayHello(pb2_grpc.SayHelloServicer):
    def inject_implementation(SayHelloImplmentation):
    self.implementation = SayHelloImplementation;

   def SayHello(self, request, context):
      return self.implementation.sayHello(request, context)

for a full example, see
Reply all
Reply to author
Forward
0 new messages