こちらの件、なんとかなっていなかった。
具体的には修正前と同様にレンダリング時にエラーが出ていた。ログを適宜出しながらよくよく見ていくとやはりOGP用のメタタグ取得タイミングでエラーになっている。
というのも、以下の箇所でPromise.race()を使ってタイムアウトを実装したのは良いものの、
async function timeout(msec: number) {
return new Promise((_, reject) => setTimeout(reject, msec))
}
const getOgpPromises = []
for (const post of posts) {
const promise = fetch(post.content.link, { redirect: 'follow' })
.then((res) => res.text())
.then((text) => {
const { document } = new JSDOM(text).window;
// メタタグ取得処理
});
getOgpPromises.push(Promise.race([
promise,
timeout(8000 - moment().diff(startMoment))
]));
}
それを解決する以下の箇所のエラーハンドリングをしていなかった。
await Promise.all(getOgpPromises);
すると例えばある一つのサイトのメタタグを取得する際にタイムアウトしてPromiseをreject()すると、このPromise.all()からエラーが投げられてレンダリング処理全体が失敗してしまう。
以下のようにエラーを握りつぶしてみた。特定のサイトのOGP用のメタタグが取得できなかったからといって、全体の処理には影響がない。
try {
await Promise.all(getOgpPromises);
} catch {
}
これにてISR時にレンダリング処理が失敗して更新できなくなる不具合は解消された(はず)。またビルド時にも同様のエラーが発生するのでこの修正をしない状態だとデプロイすらできなくて悲しかった。
ちなみに、ISR時にエラーが発生すると前回のレンダリング内容が表示され、また次回のレンダリング時に再トライしてくれる。ランタイムエラーになるのでハンドリングしなくていいのかと思いつつも公式のドキュメントにエラーになった場合の記述があるので想定されている様子。というわけでISR時のエラーは、リトライで解消される可能性があるならランタイムに投げてしまってOKという解釈になった。