Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial example for service to service communication #14

Merged
merged 4 commits into from
Aug 21, 2024

Conversation

gecage952
Copy link
Collaborator

Adds an example for service to service communication.

@gecage952 gecage952 requested a review from Lance-Drane August 20, 2024 19:26
@gecage952
Copy link
Collaborator Author

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.

@gecage952 gecage952 marked this pull request as draft August 20, 2024 19:27
@gecage952
Copy link
Collaborator Author

Schemas are added.

@gecage952
Copy link
Collaborator Author

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.

Copy link
Collaborator

@Lance-Drane Lance-Drane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed to fix a small issue with how the service was cleaning up these external requests and fix some very minor test issues. Otherwise LGTM

@Lance-Drane Lance-Drane marked this pull request as ready for review August 21, 2024 15:37
@Lance-Drane Lance-Drane merged commit 0f4e093 into svc2svc Aug 21, 2024
1 check passed
@Lance-Drane Lance-Drane deleted the e2e-test branch August 21, 2024 15:37
@Lance-Drane
Copy link
Collaborator

Lance-Drane commented Aug 21, 2024

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

@marshallmcdonnell
Copy link
Collaborator

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

@Lance-Drane
Copy link
Collaborator

I'm perfectly fine with adding a ticket for the blocking API for service-to-service.

#15

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants