INTERSECT-SDK / python-sdk

Interconnected Science Ecosystem - Software Development Kit (INTERSECT-SDK)
https://intersect-python-sdk.readthedocs.io
BSD 3-Clause "New" or "Revised" License
4 stars 1 forks source link

have both a nonblocking and a blocking API for service-to-service communication #15

Open Lance-Drane opened 3 months ago

Lance-Drane commented 3 months ago

Current API for service-to-service communication is nonblocking - this is fine but in many cases we will want a blocking API.

Some ideas include providing a limited exposure of the ExternalRequest object which handles data; one idea could involve using Python's threading.Event logic. For example:

def intersect_sdk_call_service_nonblocking(
        self,
        request: IntersectDirectMessageParams,
        response_handler: INTERSECT_SERVICE_RESPONSE_CALLBACK_TYPE | None = None,
    ) -> list[UUID]: # this is the current interface
        ...

class BlockingCallbackObject:
     set_flag: threading.Event   # this should only be mutated by the SDK but the Capability should listen to it
     response: Any  # the actual message response - you shouldn't check the value for SDK control flow logic, though
     has_timeout: bool  # 

def intersect_sdk_call_service_blocking(self, request: IntersectDirectMessageParams) -> list[BlockingCallbackObject]: # newer API, in most cases this will just be a list with a single threading event in it
    ...

Then you could use it in code like this:

@intersect_message
def my_blocking_function(self, param: str) -> str:
        msg_to_send = IntersectDirectMessageParams(
            destination='example-organization.example-facility.example-system.example-subsystem.service-two',
            operation='ServiceTwo.test_service',
            payload=text,
        )

        # Send intersect message to another service
        callback_obj = self.intersect_sdk_call_service_blocking(msg_to_send, self.service_2_handler)[0]
        while not callback_obj.set_flag.is_set():
            callback_obj.set_flag.wait(10.0)   # you can wait long amounts, and using threading.Event will immediately suspend this wait once the flag is set

       if callback_obj.has_timeout:
            # do something here in the event of an error
             return "Error: timeout"

        # process response according to domain logic, and return it
        return response

You may want to add some level of a maximum timeout regarding a response from the service, this is just an example.