jeudi 15 septembre 2022

Make Bulk Requests API Client Programming Pattern / Design

I am writing an API client for a REST API that allows for requests the be batched together in and send as one request

I am struggling to figure out how to structure the client. I've come up with two designs so far (pseudo Python code):

  1. Async Method

    When calls to the api are made (make_api_request), the method waits for the bulk request to be made. Once the bulk request is made by calling the resolve coroutine, the request coroutine releases control back to he make_api_request method which processes the response for that specific request and returns it

    import asyncio 
    
    class FakeAPIClient:
        def __init__(self):
            """
            """
            pass
    
        async def make_api_request(self):
            """
            returns response after request is made 
            """
            resp = await self.request()
            #response processing 
            return resp 
    
    
        async def request(self):
            """
            I block until the bulk request is made 
            Once it is make, I return the response from the single request 
            """
            return "RESPONSE AFTER DONE BLOCKING "
    
    
        async def resolve(self):
            """
            Make the bulk request and release the make_api_request calls and return the assocaited responses 
            """
            return None
    
    
    async def example():
        api = FakeAPIClient()
    
        future1 = api.make_api_request()
        future2 = api.make_api_request()
        future3 = api.make_api_request()
    
        #3 requests are sent in bulk
    
        response1, response2, response3, _ = asyncio.gather(
            future1,
            future2, 
            future3, 
            api.resolve()
        )
    
    
    asyncio.run(example())
    
  2. Lookup method

    When calls to the api are made (make_api_request), a lookup ID is returned and the request is put into storage. When the resolve method is called, the bulk request is called, the requests in storage are sent as a bulk request and an object is returned that can be used to find the lookup id's corresponding response.

    class FakeAPIClient:
        def __init__(self):
            pass
    
        def make_api_request(self):
            """
            adds request to a queue of requests that will be resolved when resolve method is called
            also provide a callback for post request processing  
    
            returns a unique id of the request
            """
            return "UNIQUE ID"
    
    
        def resolve(self):
            """
            makes the bulk request 
            takes the responses and associates them with the request id 
            calls the callback associated with the response for post request processing 
    
            returns an object with a method that returns the responses when provided the request id 
            """
            return "RESPONSE LOOKUP"
    
    
    
    api = FakeAPIClient()
    
    lookup_id1 = api.make_api_request()
    lookup_id2 = api.make_api_request()
    lookup_id3 = api.make_api_request()
    
    lookup_object = api.resolve()
    
    response1 = lookup_object.get(lookup_id1)
    response2 = lookup_object.get(lookup_id2)
    response3 = lookup_object.get(lookup_id3)
    

I don't really love either of these solutions, but I can't think of any alternatives. I'd assume there are known patterns for solving this problem, what are they?

Aucun commentaire:

Enregistrer un commentaire