🙌

Vercel環境でのNotion API同期機能の実装に成功した

2025/04/04に公開

はじめに

前回の記事では、Next.jsアプリケーションでNotionのデータをSupabaseに同期する機能を実装しようとした際に遭遇した「fetch failed」エラーとその原因究明について詳しく説明しました。今回は、その続編として、Vercel環境での実装成功までの道のりをお伝えします。

※この記事の制作にはAI(Claude-3.7-sonnet)を使用しています。AI訛りにご承知おきください。

問題の振り返り

ローカル開発環境では、以下の問題に直面していました:

  1. Notion APIからのデータ取得は可能でしたが、Supabaseへの保存時に「fetch failed」エラーが発生
  2. node-fetchaxiosなどを使った回避策を試みるも解決せず
  3. ローカル環境のNode.jsバージョンとfetch APIの互換性問題が根本原因と推測

Vercel環境での実行戦略

ローカル環境での問題解決が難しかったため、以下の戦略を立てました:

  1. Vercel環境(本番環境)でのテスト実行
  2. Vercelの関数タイムアウト設定の調整(60秒に延長)
  3. APIルートの実装とテスト

タイムアウト設定の調整

まず、Vercel環境では関数の実行時間に制限があるため、vercel.jsonを以下のように修正しました:

{
  "version": 2,
  "buildCommand": "npm run build",
  "devCommand": "npm run dev",
  "framework": "nextjs",
  "functions": {
    "app/api/sync-notion/route.js": {
      "maxDuration": 60
    }
  },
  "crons": [
    {
      "path": "/api/sync-notion",
      "schedule": "0 0 * * *"
    }
  ]
}

ここでいくつかの困難に直面しました:

  1. 最初は"/api/sync-notion"と指定したが、Vercelからパスにスラッシュを含めないよう指示
  2. 次に"api/sync-notion"と指定したが、実際のServerless Functionのパスと一致しない問題
  3. 最終的に"app/api/sync-notion/route.js"という正確なパスを指定して解決

API実行とエラー解決

Vercel環境でAPIを実行したところ、最初は新たなエラーが発生しました:

Could not find the 'last_edited_time' column of 'notion_pages' in the schema cache

これはSupabaseのデータベーススキーマの問題でした。テーブルには存在するがSupabaseのスキーマキャッシュが正しく更新されていない状態でした。

この問題はSupabase側で解決され、再度APIを実行したところ、見事にデータ同期に成功しました!

同期成功のログ

以下は実際の同期成功時のログです:

Notionデータベース(1c5a2a5cb4ea80f6ab25d8cd39588366)からページ一覧を取得中...
41ページを処理します...
ページ処理中: 1c9a2a5c-b4ea-80d6-95d8-e0cf3040a151
ブロックデータ取得中: 1c9a2a5c-b4ea-80d6-95d8-e0cf3040a151
ページ完了: 1c9a2a5c-b4ea-80d6-95d8-e0cf3040a151 (23ブロック)
ページ処理中: 1c9a2a5c-b4ea-8050-a103-c2e2a092a4a9
ブロックデータ取得中: 1c9a2a5c-b4ea-8050-a103-c2e2a092a4a9
ページ完了: 1c9a2a5c-b4ea-8050-a103-c2e2a092a4a9 (3ブロック)
...

全41ページと合計142ブロックのデータが正常に同期されました。

学んだこと

この実装を通じて得られた重要な知見をまとめます:

  1. 開発環境と本番環境の違い

    • ローカル開発環境ではNode.jsのバージョンやランタイム環境によるfetch APIの挙動の違いが問題になることがある
    • Vercel環境では最新のNode.jsが使用されており、fetch APIがネイティブにサポートされている
  2. Vercel関数の設定

    • Serverless Functionsのパス指定は厳密な形式が必要(app/api/パス名/route.js
    • 長時間実行される処理にはmaxDurationの設定が必須
  3. データベース連携のベストプラクティス

    • スキーマの変更は事前に確認し、適切に更新する
    • バッチ処理は小さな単位に分割すると安全(今回は41ページを一度に処理)
  4. エラー診断の進め方

    • エラーメッセージを正確に解釈し、レイヤー(クライアント、サーバー、データベース)ごとに切り分ける
    • 環境の違いに注目する(開発環境 vs 本番環境)

今後の展望

今回の成功を踏まえて、今後は以下の改善を検討しています:

  1. バッチ処理の最適化

    • 大量データを扱う場合に備えて、ページングやチャンク処理の導入
    • エラー発生時の再試行メカニズムの実装
  2. スケジューリングと自動化

    • Vercelのcron機能を活用した定期的な同期処理の実装
    • 同期ステータスの可視化とモニタリング
  3. エラーハンドリングの強化

    • より詳細なエラーロギングの導入
    • 障害発生時の通知システムの構築

まとめ

ローカル環境では解決が難しかった「fetch failed」エラーも、Vercel環境では問題なく動作することが確認できました。これは、Vercelが提供する最新のNode.jsランタイムと、より安定した実行環境の恩恵と言えるでしょう。

Serverless環境での長時間バッチ処理にはいくつかの制約がありますが、適切な設定と実装アプローチによって、効率的かつ安定した運用が可能です。

APIとデータベースを連携させる際は、環境差異を常に意識し、本番環境を想定したテストと設計が重要であることを改めて学びました。

この記事が、同様の課題に取り組む開発者の参考になれば幸いです。

Discussion