YerMarti
YerMarti

Reputation: 11

How can I implement dynamic connections with gRPC in Python?

I'm working on a project using Docker in which I need to dynamically compile a gRPC protofile and then create the connection and make a request to the server using the method defined in said protofile. I get the info from a Selector service that returns which tool/gRPC service it should be used (this is based on UDDI). The info retrieved contains the following:

message GetServiceResponse {

    string service_name = 1;
    string service_ip = 2;
    string service_port = 3;
    string proto_file = 4; # protofile in base64

}

I get to compile and generate the gRPC files correctly but I don't really know how should I continue from here on.

I tried to create a module this way. The gRPC files are generated at /app/generated/{service_name} and then I try to generate the module.

def _create_grpc_stub(self, service_name: str, service_ip: str, service_port: str):
        module = __import__(f'generated.{service_name}')
        service_class = getattr(module, service_name)
        channel = grpc.insecure_channel(f'{service_ip}:{service_port}')
        config.logger.debug(f"Stub created for '{service_name}'")
        return service_class(channel)

def select_tool(self, query: str):
        #...
        config.logger.debug("Creating service STUB...")
        stub = self._create_grpc_stub(
            service_name=result.service_name,
            service_ip=result.service_ip,
            service_port=result.service_port
        )

I get the following error:

2024-11-05 13:15:28 2024-11-05 12:15:28,980 [ERROR]  Error processing selection of tool: 'module' object is not callable
2024-11-05 13:15:28 2024-11-05 12:15:28,980 [ERROR]  Exception serializing message!
2024-11-05 13:15:28 Traceback (most recent call last):
2024-11-05 13:15:28   File "/usr/local/lib/python3.12/site-packages/grpc/_common.py", line 89, in _transform
2024-11-05 13:15:28     return transformer(message)
2024-11-05 13:15:28            ^^^^^^^^^^^^^^^^^^^^
2024-11-05 13:15:28 TypeError: descriptor 'SerializeToString' for 'google._upb._message.Message' objects doesn't apply to a 'NoneType' object

On top of this, I don't really know if this approach is correct. While looking for ways to implement this, I came across gRPC Reflection and I have been looking at this example and I was wondering if it could be useful for me in any way. Looks easy enough but I can't come across a way to implement this in my project as I need to dynamically add services.

EDIT:

After checking this gRPC client with reflection for a while I think that it could be used for this specific case, the only thing I would need is a way to call said methods, because I don't know how to do that as in the example is not done and checking the docs did not help either. I found a gRPC CLI that does that but I need a way to do it via Python code. Using a CLI seems too hacky for me.

Upvotes: 1

Views: 47

Answers (0)

Related Questions