Table of Contents
Operation is justice
Thankfully, the number of people using the services we are currently operating has increased, albeit slowly.
https://kindle-unlimited-search.nove-b.dev/
However, there are still some problems, and this time we have resolved one of them: “Status codes are not well defined.”
As for the current service
- No matching author found
- The page sent in the query is out of range
- Unable to respond due to unavailability of requests from Amazon side
All possible errors were returned to the front desk as a 400 server error.
In this case, the front side cannot provide different messages to the user, which is not at all friendly.
Moreover, the front desk continued to make requests even before 400 was returned, which was also a completely unfriendly implementation.
Defined status code
Therefore, we decided to return 404 when the corresponding author is not found, 416 when the page is out of scope, and 429 when the request is restricted.
At the front desk, we decided to divide the processing based on that value.
When 404 is displayed, a snack bar is displayed that says The work of the artist you searched for was not found.'' When `416` is displayed, which means that all pages have been checked, a snack bar is displayed that says The acquisition of works (up to 100 works) has been completed.” When 429 is displayed, a new request is required (up to 5 attempts).
Retry the request
This is the first time I wrote a code that makes a request again like 429 without a plugin, so I will summarize it in a memorandum.
I learned this for the first time, but I decided to use a method called exponential backoff.
What is exponential backoff?
A method to exponentially increase the retry interval
That seems to be the case.
In other words, if the first retry fails, try again 1 second later, if the second fails, try again 2 seconds later, if the third fails, 4 seconds later, and so on.
In addition to this, we decided to retry up to 5 times and interrupt the process if the connection could not be established.
const fetchAPI = async () => { setState("wait"); let page = 1; let retryCount = 0; const maxRetryCount = 5; // 最大リトライ回数
while (true) { // page が 10 を超えた場合はループを終了 if (page > 10) { setState("end"); console.log("成功"); break; }
try { const response = await fetch(`${endpoint}$`);
if (response.ok) { console.log("データ取得に成功しました。"); page++; // 次のページへ retryCount = 0; // リトライ回数をリセット await new Promise((resolve) => setTimeout(resolve, 1000)); // 1秒待機 } else if (response.status === 429 && retryCount < maxRetryCount) { // 429 Too Many Requests が返された場合、リトライ const delay = Math.pow(2, retryCount) * 1000; // 指数バックオフ console.log( `リクエストが多すぎます。${delay / 1000}秒後にリトライします。`, ); await new Promise((resolve) => setTimeout(resolve, delay)); retryCount++; } else { // その他のエラーの場合、エラーログを出力してループを終了 console.error( `エラーが発生しました。ステータスコード: ${response.status}`, ); setState("end"); toast.error("失敗"); break; } } catch (error) { console.error("失敗:", error); setState("end"); break; } }};First, it determines whether the number of pages is 10 or less up to 10 pages.
If the number of pages is greater than 10, processing ends at that point.
If it is less than 10, hit api, and if successful, add 1 to the 1-second wait page and return to the beginning of the loop process.
When 429 is returned, define an exponential backoff value, wait the defined time, add 1 to the retry count, and return to the beginning of the loop.
At this point, the page is not incremented by 1, so you can request the same page again.