Server Actionが断続的に実行されない問題

🌐

この記事は DeepL によって翻訳されました。誤訳があれば教えてください!

問題点

サーバーサイドで下記のようなMixpanelトラッキングコードを実行した時、イベントが断続的にしか記録されない現象が発生しました。

mixpanel.track(event, { distinct_id: userId, properties }, err => {
  if (err) { {
    reject(err);
  } else { } else
    resolve("success");
  }
});

ローカル環境では全てのイベントが正常に記録されましたが、Vercel配布環境では一部のイベントだけが記録される問題がありました。

原因

原因を見る前にVercel Functionについて説明します。VercelではVercelに配布された環境に対してVercel Functionという機能を提供しています。

Vercel Functionについて簡単に説明すると、Vercelにデプロイされた全てのサーバーサイドでのコード実行はVercelのインフラ環境下で実行されるということです。 つまり、FaaSが適用されるということです。

FaaSはFunction as a Serviceの略で、サーバーレスコンピューティングを実装する方法の一つです。ここでFunctionは、私たちが開発時に使用するそのFunctionであり、このような関数をクラウドサービスに載せて、必要な時だけ呼び出すという概念である。 つまり、FaaSを使用すると、サーバーを開発する必要がなく、関数だけを作成して実行することができます。 Vercelのこのような機能のおかげで、私たちがサーバー設定を特にしなくてもAPI Routesや、SSRなどを利用することができるのです。

✏️Good to KnowVercelのServerless architectureはAWSのLambdaを利用しています。

問題が発生したコードも**サーバーアクション(Server Action)**に設定されてサーバーで実行され、Vercelがサーバーレスに基づいて動作するため、コードがサーバーレス関数として登録されました。

しかし、サーバーレス関数は実行中にプロセスが終了する可能性があり、この場合、非同期作業が完了する前に関数が終了する可能性がありました。 つまり、callback関数が実行されず、イベントが正常に送信されなかったのです。

解決方法

したがって、コードを下記のようにPromiseで包んで、全てのイベントが正常に送られてきました。

return new Promise((resolve, reject) => { { mixpanel.track(event, reject)
    mixpanel.track(event, { distinct_id: userId、properties }, (err) => {
      if (err) { {
        reject(err)
      } else { }, (resolve('success')
        resolve('success')
      }
    })
  })

Tracking Codeをサーバーサイドで実行した理由

そしたら、なぜmixpanel.trackのようなトラッキングコードをクライアントサイドで実行させなかったのか?

  • データの整合性:クライアントから直接イベントを送信する場合、ユーザーのブラウザ設定(例えば、広告ブロッカー)やネットワークの問題により、イベントが欠落する可能性があります。サーバーサイドで実行することで、このような外部要因を減らし、より信頼性の高いデータ収集が可能になります。
  • ビジネスロジックとの統合:トラッキングイベントがサーバーサイドのロジック(決済処理、ユーザー認証など)と密接に関連している場合、サーバーで直接処理する方が自然で効率的です。例えば、決済完了後のイベントを記録するには、サーバーで決済が成功したかどうかを確認した後にトラッキングするのが適切です。
  • パフォーマンスの最適化:クライアントでトラッキングリクエストを処理すると、追加のネットワーク呼び出しが発生し、ページの読み込み時間が長くなる可能性があります。サーバーサイドで処理することで、クライアントの負担を軽減し、ユーザーエクスペリエンスを向上させることができます。

これらの理由から、可能であれば、クライアントではなくサーバーサイドで実行する方が、より正確で安定した指標を得ることができます。

参考文献