|
2 | 2 | import contextlib |
3 | 3 | import logging |
4 | 4 | import re |
| 5 | +import time |
5 | 6 |
|
6 | 7 | import httpx |
7 | 8 | import jwt |
@@ -372,7 +373,7 @@ def delete(self, path: str, params: dict = None) -> dict: |
372 | 373 | params: query parameters, as dictionary |
373 | 374 |
|
374 | 375 | Returns: |
375 | | - Sumo JSON resposne as a dictionary |
| 376 | + Sumo JSON response as a dictionary |
376 | 377 |
|
377 | 378 | Examples: |
378 | 379 | Deleting object:: |
@@ -401,6 +402,46 @@ def _delete(): |
401 | 402 |
|
402 | 403 | return retryer(_delete) |
403 | 404 |
|
| 405 | + def _get_retry_details(self, response_in): |
| 406 | + assert response_in.status_code == 202, ( |
| 407 | + "Incorrect status code; expcted 202" |
| 408 | + ) |
| 409 | + headers = response_in.headers |
| 410 | + location = headers.get("location") |
| 411 | + assert location is not None, "Missing header: Location" |
| 412 | + assert location.startswith(self.base_url) |
| 413 | + retry_after = headers.get("retry-after") |
| 414 | + assert retry_after is not None, "Missing header: Retry-After" |
| 415 | + location = location[len(self.base_url) :] |
| 416 | + retry_after = int(retry_after) |
| 417 | + return location, retry_after |
| 418 | + |
| 419 | + def poll( |
| 420 | + self, response_in: httpx.Response, timeout=None |
| 421 | + ) -> httpx.Response: |
| 422 | + """Poll a specific endpoint until a result is obtained. |
| 423 | +
|
| 424 | + Args: |
| 425 | + response_in: httpx.Response from a previous request, with 'location' and 'retry-after' headers. |
| 426 | +
|
| 427 | + Returns: |
| 428 | + A new httpx.response object. |
| 429 | + """ |
| 430 | + location, retry_after = self._get_retry_details(response_in) |
| 431 | + expiry = time.time() + timeout if timeout is not None else None |
| 432 | + while True: |
| 433 | + time.sleep(retry_after) |
| 434 | + response = self.get(location) |
| 435 | + if response.status_code != 202: |
| 436 | + return response |
| 437 | + if expiry is not None and time.time() > expiry: |
| 438 | + raise httpx.TimeoutException( |
| 439 | + "No response within specified timeout." |
| 440 | + ) |
| 441 | + location, retry_after = self._get_retry_details(response) |
| 442 | + pass |
| 443 | + return None # should never get here. |
| 444 | + |
404 | 445 | def getLogger(self, name): |
405 | 446 | """Gets a logger object that sends log objects into the message_log |
406 | 447 | index for the Sumo instance. |
@@ -642,7 +683,7 @@ async def delete_async(self, path: str, params: dict = None) -> dict: |
642 | 683 | params: query parameters, as dictionary |
643 | 684 |
|
644 | 685 | Returns: |
645 | | - Sumo JSON resposne as a dictionary |
| 686 | + Sumo JSON response as a dictionary |
646 | 687 |
|
647 | 688 | Examples: |
648 | 689 | Deleting object:: |
@@ -670,3 +711,29 @@ async def _delete(): |
670 | 711 | retryer = self._retry_strategy.make_retryer_async() |
671 | 712 |
|
672 | 713 | return await retryer(_delete) |
| 714 | + |
| 715 | + async def poll_async( |
| 716 | + self, response_in: httpx.Response, timeout=None |
| 717 | + ) -> httpx.Response: |
| 718 | + """Poll a specific endpoint until a result is obtained. |
| 719 | +
|
| 720 | + Args: |
| 721 | + response_in: httpx.Response from a previous request, with 'location' and 'retry-after' headers. |
| 722 | +
|
| 723 | + Returns: |
| 724 | + A new httpx.response object. |
| 725 | + """ |
| 726 | + location, retry_after = self._get_retry_details(response_in) |
| 727 | + expiry = time.time() + timeout if timeout is not None else None |
| 728 | + while True: |
| 729 | + await asyncio.sleep(retry_after) |
| 730 | + response = await self.get_async(location) |
| 731 | + if response.status_code != 202: |
| 732 | + return response |
| 733 | + if expiry is not None and time.time() > expiry: |
| 734 | + raise httpx.TimeoutException( |
| 735 | + "No response within specified timeout." |
| 736 | + ) |
| 737 | + location, retry_after = self._get_retry_details(response) |
| 738 | + pass |
| 739 | + return None # should never get here. |
0 commit comments