Convex – チュートリアル:外部サービス連携

はじめに

  • こちらのドキュメントにしたがって、チュートリアルを実行します。
  • 前回作成したアプリに機能を追加します。

 データベースのトランザクションとリアルタイム性を維持するため、Convexのquery関数とmutation関数は、外部へのfetch(データ取得)呼び出しができません。しかし、実際のアプリケーションでは外部サービスと通信する必要があるため、Convexはaction関数を提供しています。action関数を使うと、同期エンジンが外部世界にアクセスできるようになり、その結果をミューテーション関数を通じてデータベースに書き戻すことができます。
 本チュートリアルでは、このaction関数を使って、チャットアプリからWikipedia APIを呼び出し、トピックの要約を取得する機能を実装します。

実装

  • アクション関数 getWikipediaSummary
    • この関数を公開APIとしないようにするため、internalActionを使用。この関数は、指定されたトピックでWikipediaのAPIに単純なfetchを行う。
    • ctx.schedulerで、summaryをchatのsendMessageでチャットに送信する。
  • ヘルパーTypeScript関数 getSummaryFromJSON
    • JSONレスポンスから要約テキストを抜き出す。
  • sendMessage関数の変更
    • /wikiで始まる場合、直後のスペース後の文字列をtopicとする
    • ctx.schedulerで、ミューテーション成功時に、getWikipediaSummaryアクションを非同期に呼び出すように設定する
import { query, mutation, internalAction } from "./_generated/server";
import { v } from "convex/values";

export const sendMessage = mutation({
  args: {
    user: v.string(),
    body: v.string(),
  },
  handler: async (ctx, args) => {
    console.log("This TypeScript function is running on the server.");
    await ctx.db.insert("messages", {
      user: args.user,
      body: args.body,
    });

    // ADD HERE 4 !!!
    if (args.body.startsWith("/wiki")) {
      // Get the string after the first space
      const topic = args.body.slice(args.body.indexOf(" ") + 1);
      await ctx.scheduler.runAfter(0, internal.chat.getWikipediaSummary, {
        topic,
      });
    }

  },
});

// ADD HERE 2 !!!
export const getMessages = query({
  args: {},
  handler: async (ctx) => {
    // Get most recent messages first
    const messages = await ctx.db.query("messages").order("desc").take(50);
    // Reverse the list so that it's in a chronological order.
    return messages.reverse();
  },
});

// ADD HERE 3 !!!
export const getWikipediaSummary = internalAction({
  args: { topic: v.string() },
  handler: async (ctx, args) => {
    const response = await fetch(
      "https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro&explaintext&redirects=1&titles=" +
        args.topic,
    );

    const summary = getSummaryFromJSON(await response.json());
    await ctx.scheduler.runAfter(0, api.chat.sendMessage, {
      user: "Wikipedia",
      body: summary,
    });
  },
});

// ADD HERE 3 !!!
function getSummaryFromJSON(data: any) {
  const firstPageId = Object.keys(data.query.pages)[0];
  return data.query.pages[firstPageId].extract;
}

    ダッシュボード で、getWikipediaSummary関数をテストすることができます。
    Functions > getWikipediaSummaryと選択し、Run Functionをクリック、
    topicに検索ワードを入力し、Run Actionをクリックします。

    Wikipediaにキーワードを送り、サマリーがチャットに返信される。

    ConvexのSchedulerとActionのイメージ

    (出典:https://docs.convex.dev/tutorial/actions#the-scheduler-actions-and-the-sync-engine

    データベース操作はクエリミューテーションのみで行います。スケジューラは、この間にアクションを挟んで複雑なワークフローを構築することを可能にします。

    Convexのバックエンドの役割分担

    • アクション: AWS Lambdaのような通常のサーバーレス関数で、外部APIの呼び出しなど、不確実な外部とのやり取りを担います。
    • クエリとミューテーション: データベースのトランザクションを保証する役割を持ち、高速で機敏な同期エンジンの一部です。データベースとの通信は、必ずこの2つを経由しなければなりません。

    スケールするアプリケーションを構築するには、外部との通信を行うアクションの作業を最小限に抑え、主要なロジックをクエリとミューテーションで処理するのが最善の方法です。これにより、Convexは高いスループットを維持できます。

    関連記事

    カテゴリー

    アーカイブ

    Lang »