44from typing import Any , Dict , Generator , Literal , Optional , Type
55
66import aiohttp
7+ from aiolimiter import AsyncLimiter
78from loguru import logger
89
910from python_notion_api .async_api .notion_block import NotionBlock
@@ -26,10 +27,17 @@ class AsyncNotionAPI:
2627 Args:
2728 access_token: Notion access token
2829 api_version: Version of the notion API
30+ rate_limit: (number_of_requests, number of seconds). Default
31+ is set at the rate limit of Notion (3 per second), with a longer
32+ interval to allow bursts.
2933 """
3034
3135 def __init__ (
32- self , access_token : str , api_version = "2022-06-28" , page_limit = 20
36+ self ,
37+ access_token : str ,
38+ api_version = "2022-06-28" ,
39+ page_limit = 20 ,
40+ rate_limit = (500 , 200 ),
3341 ):
3442 self ._access_token = access_token
3543 self ._base_url = "https://api.notion.com/v1/"
@@ -40,6 +48,7 @@ def __init__(
4048 status_forcelist = [429 , 500 , 502 , 503 , 504 , 409 ],
4149 )
4250 self ._page_limit = page_limit
51+ self .limiter = AsyncLimiter (* rate_limit )
4352
4453 @property
4554 def request_headers (self ):
@@ -104,13 +113,14 @@ async def _request_attempt(
104113 data: Data to pass to the request.
105114 params: Params to pass to the request.
106115 """
107- return await session .request (
108- method = request_type ,
109- url = url ,
110- headers = self .request_headers ,
111- params = params ,
112- data = data ,
113- )
116+ async with self .limiter :
117+ return await session .request (
118+ method = request_type ,
119+ url = url ,
120+ headers = self .request_headers ,
121+ params = params ,
122+ data = data ,
123+ )
114124
115125 async def _request (
116126 self ,
@@ -166,12 +176,21 @@ async def _request(
166176 )
167177 raise Exception ("Request failed" )
168178
169- delay = min (
170- retry_strategy .backoff_factor * (2 ** (i )),
171- retry_strategy .max_backoff ,
172- )
179+ if response .status == 429 :
180+ delay = int (response .headers ["Retry-After" ])
181+ logger .warning (
182+ f"Request to { url } failed:"
183+ f"\n { response .status } "
184+ f"\n Retry-After: { delay } "
185+ f"\n { decoded_data } "
186+ )
187+ else :
188+ delay = min (
189+ retry_strategy .backoff_factor * (2 ** (i )),
190+ retry_strategy .max_backoff ,
191+ )
173192
174- logger .error (
193+ logger .warning (
175194 f"Notion is busy ({ response .status } )."
176195 f"Retrying ({ i + 1 } ) in { delay } s"
177196 )
0 commit comments