Closed gecage952 closed 2 months ago
So for some reason the event doesn't seem to be reaching the event callback, so I was wondering if you had any insight on why. I also still need to add the schemas.
Schemas are added.
So just to explain a little more. I initially didn't want to use events, but since the first service just sends the message and then returns, I needed to use a handler to make sure that the response is only sent once the second service has replied. Thus, I decided to just emit an event back to the client, and have the client print that out for the purposes of the test.
So just to explain a little more. I initially didn't want to use events, but since the first service just sends the message and then returns, I needed to use a handler to make sure that the response is only sent once the second service has replied. Thus, I decided to just emit an event back to the client, and have the client print that out for the purposes of the test.
@gecage952 This is the correct approach based on the current API, as the mechanisms of pub/sub seem to compel a nonblocking API. It would be nice to have a blocking API (where Service 1 doesn't have to use the event handler, but can just wait on Service 2's response before sending its own response) but I'm not sure how we would implement it in the SDK. One possible solution could be to expose a limited view of the ExternalRequest object; maybe this API could use Python's threading.Event
logic. For example, the create_external_request()
interface could look like:
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
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
# 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.
@MichaelBrim @marshallmcdonnell pinging you both because there's some discussion about allowing both a blocking and a nonblocking API
I think it is a great suggestion and honestly, what I thought initially for the service-to-service communication being.
I'm perfectly fine with adding a ticket for the blocking API for service-to-service.
Not top priority but think it is good to capture that + useful eventually to others
I'm perfectly fine with adding a ticket for the blocking API for service-to-service.
Adds an example for service to service communication.