top

Cartesian Theater

Powered by NotionAPI

20220206

Date: 2022-02-06
Last Edited: 2022-02-06 08:07:00

以下のようなリンクの埋め込み表示を追加したら、CMSに使っているNotion上でページを更新してもサイト上に反映されないことがあった。

Heavy (feat. Your Smith) [Remixes], by Flight Facilities
4 track album
https://flightfacilities.bandcamp.com/album/heavy-feat-your-smith-remixes
Heavy (feat. Your Smith) [Remixes], by Flight Facilities

Vercelのログを見に行くとNext.jsのサーバサイドレンダリング処理でタイムアウトが発生している。無料版のVercelはサーバレス関数の処理時間に制限がある。(ドキュメントを見ると5秒と書いてあるけど自分の環境では10秒だった。謎)

Limits
This reference covers a list of all the limits and limitations that apply on Vercel.
https://vercel.com/docs/concepts/limits/overview

サーバサイドレンダリングに失敗するとページは更新されない。ただしISRにしているので前回のレンダリング結果である更新前のページが表示される。

原因としては、リンク先からOGP画像のリンクなどを取得する処理でHTTP通信とHTMLのパースに時間がかかっているようだ。リンク先によっては応答が遅い場合があるので、全体の処理を制限時間内に間に合わせるにはそうしたリンクに対する処理は適度なところで切り上げる必要がある。

以下の記事を参考にPromise.race()を使って処理をタイムアウトさせる機構を追加した。

非同期処理をタイムアウトする : (*x).b=z->a+y/c
◆ これまで使ったことが全くなかった Promise.race を使う時が来た
http://var.blog.jp/archives/77441509.html
非同期処理をタイムアウトする : (*x).b=z->a+y/c

次のような、引数に与えた時間を過ぎたらrejectされるPromiseを返す関数を用意しておく。

async function timeout(msec: number) {
    return new Promise((_, reject) => setTimeout(reject, msec))
}

メタタグを取得する処理で、ページにある各リンクにリクエストを送ってパースする処理を非同期で実行している。Promiseの配列を作ってPromise.all()で待っているので、その配列に入れるPromiseをPromise.race()と上の関数を使ってタイムアウトするようにしておく。(startMomentはNext.jsのgetStaticProps()を開始したタイミング。10秒制限から計算して適当に8秒以上経過していたらタイムアウトにする)

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);
notion-blog/lib/util/notion.ts at main · yuki-oshima-revenant/notion-blog
Contribute to yuki-oshima-revenant/notion-blog development by creating an account on GitHub.
https://github.com/yuki-oshima-revenant/notion-blog/blob/main/lib/util/notion.ts
notion-blog/lib/util/notion.ts at main · yuki-oshima-revenant/notion-blog

これにてひとまずタイムアウトはせず、ページが更新されるようになった。

©︎2021 Yuki Oshima