Advertisement

Dec 08, 2023 3 mins

Retry in Python aiohttp async requests

ARetry in Python aiohttp async requests ARetry in Python aiohttp async requests

Retry in Python aiohttp is the action of automatically resubmitting unsuccessful async HTTP requests. Async HTTP requests can be failed because of many reasons. Server failure, network issues, and rate limitations are a few reasons that make request failures.

Python aiohttppackage is a famous third-party library to make asynchronous HTTP requests. But, it doesn’t have in-built functionality to make retries whenever async requests are getting failed. Therefore we are using aiohttp-retry client to make retries on async requests in Python. Because aiohttp-retry library has been built on top of aiohttp library, the client session is the same as aiohttp client session. The only difference is, aiohttp-retry client session takes a few more additional parameters to handle the retry operation.

What is the backoff factor in Python aiohttp-retry?

So let’s take an example to figure out what is backoff factory in aiohttp-retry. Assume you want to retry on failed async HTTP request a maximum of 5 times with a backoff factor of 2s. Then once the request is failed, python aiohttp-retry will trigger retry the after each following second. The first retry will start just after the initial request is get failed.

  • First retry → After 2*0 → 0s, 
  • Second retry → After 2*2 → 4s 
  • Third retry → After 2*4 → 8s
  • Fourth retry → After 2*8 → 16s
  • Fifth retry → After 2*16 → 32S

If the async request is still failed, it will throw an error after 0s+4s+8s+16s+32s → 60s

Retry in Python aiohttp example

To demonstrate GET, POST, PUT, and DELETE operations,  we are using a publicly available API endpoint. This API will return user details as JSON. Also, we are using the Python aiohttp client library to trigger retries automatically. In Each example, we are feeding the number of total retries and the backoff factor.

GET in Python aiohttp

# retry on get
import json
import asyncio
import requests
from aiohttp_retry import RetryClient, ExponentialRetry

REQUEST_RETRY = 3
BACKOFF_FACTOR = 1

async def get():
    url = "https://gorest.co.in/public/v2/users"
    headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try:
        retry_options = ExponentialRetry(attempts=REQUEST_RETRY)

        async with RetryClient(retry_options=retry_options) as session:

            async with session.get(
                    url, headers=headers, ssl=False
            ) as response:
                respstr = str(await response.text())
                if response.status != 200:
                    raise Exception(
                        "Request failed: Response http code {}, response {}".format(
                            response.status, respstr
                        )
                    )
            json_res = json.loads(respstr)
            print(json.dumps(json_res, indent=4))

    except Exception as e:
        raise Exception("Error while request: {}".format(e))

if __name__ == "__main__":
    futures = [get()]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(futures))

POST in Python aiohttp

# retry on post
import json
import asyncio
import requests
from aiohttp_retry import RetryClient, ExponentialRetry

REQUEST_RETRY = 3
BACKOFF_FACTOR = 1


async def post():
    url = "https://gorest.co.in/public/v2/users"
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer <ACCESS-TOKEN>",
        "Accept": "application/json"
    }

    payload = {
        "name": "Tenali Ramakrishna",
        "gender": "male",
        "email": "tenali.ramakrishna@15ce.com",
        "status": "active"
    }

    payload = json.dumps(payload)

    try:
        retry_options = ExponentialRetry(attempts=REQUEST_RETRY)

        async with RetryClient(retry_options=retry_options) as session:

            async with session.post(
                    url, data=payload, ssl=False, headers=headers
            ) as response:
                respstr = str(await response.text())

                if response.status != 200:
                    raise Exception(
                        "Request failed: Response http code {}, response {}".format(
                            response.status, respstr
                        )
                    )

            json_res = json.loads(respstr)

            print(json.dumps(json_res, indent=4))

    except Exception as e:
        raise Exception("Error while request: {}".format(e))

if __name__ == "__main__":
    futures = [post()]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(futures))

PUT in Python aiohttp

# retry on put
import json
import asyncio
import requests
from aiohttp_retry import RetryClient, ExponentialRetry

REQUEST_RETRY = 3
BACKOFF_FACTOR = 1


async def put():
    url = "https://gorest.co.in/public/v2/users/547"
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer <ACCESS-TOKEN>",
        "Accept": "application/json"
    }

    payload = {
        "name": "Tenali Ramakrishna",
        "gender": "male",
        "email": "tenali.ramakrishna@15ce.com",
        "status": "active"
    }

    payload = json.dumps(payload)

    try:
        retry_options = ExponentialRetry(attempts=REQUEST_RETRY)

        async with RetryClient(retry_options=retry_options) as session:

            async with session.put(
                    url, data=payload, ssl=False, headers=headers
            ) as response:
                respstr = str(await response.text())

                if response.status != 200:
                    raise Exception(
                        "Request failed: Response http code {}, response {}".format(
                            response.status, respstr
                        )
                    )

            json_res = json.loads(respstr)

            print(json.dumps(json_res, indent=4))

    except Exception as e:
        raise Exception("Error while request: {}".format(e))

if __name__ == "__main__":
    futures = [put()]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(futures))

DELETE in Python aiohttp

# retry on delete
import json
import asyncio
import requests
from aiohttp_retry import RetryClient, ExponentialRetry

REQUEST_RETRY = 3
BACKOFF_FACTOR = 1


async def delete():
    url = "https://gorest.co.in/public/v2/users/547"
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer <ACCESS-TOKEN>",
        "Accept": "application/json"
    }

    try:
        retry_options = ExponentialRetry(attempts=REQUEST_RETRY)

        async with RetryClient(retry_options=retry_options) as session:

            async with session.delete(
                    url, ssl=False, headers=headers
            ) as response:
                respstr = str(await response.text())

                if response.status != 200:
                    raise Exception(
                        "Request failed: Response http code {}, response {}".format(
                            response.status, respstr
                        )
                    )

            json_res = json.loads(respstr)

            print(json.dumps(json_res, indent=4))

    except Exception as e:
        raise Exception("Error while request: {}".format(e))

if __name__ == "__main__":
    futures = [delete()]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(futures))

Conclusion

Python aiohttp library doesn’t have a way to trigger retries on failure async HTTP requests. Therefore we can use aiohttp client library.


Comments


There are no comments yet.

Write a comment

You can use the Markdown syntax to format your comment.

  • Tags:
  • python aiohttp retry
  • Share: