Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

supabase + Next.jsでトランザクションを実装する方法を探った

BPSの協力会社として横浜を拠点に活動しております、株式会社ECNのすぎもです。
今回はsupabaseでトランザクションを行うのにかなり悩んだのでメモがてら記事にしてみました。

余談 supabaseについて軽く

本題に入る前にsupabaseについてです。

参考: The Open Source Firebase Alternative | Supabase

FirebaseやAmplifyなどさまざまある中supabaseは他と違う特徴がいろいろあって一番今後も使っていきたいBaaSの一つです。
ほかのBaaSとの大きな違いはデータベースがRDBでPostgreSQLをデータベースとしていて既存の知識が活かしやすかったりsupabaseクライアントの機能も充実している印象があります。
データベースからTypeScriptの型を自動生成できることもとてもつよつよポイントかなという感じです。

他とも共通でsubscriptionの機能でデータベースの変更を監視してリアルタイムにデータ取得したりストレージサービスもあります。

個人的推しポイント

リレーションとテーブルが従来通りの概念で作れる

データベースがPostgreSQLということで、supabaseのUIからでもテーブル作成とリレーションの設定が可能です。
supabaseクライアントからの操作も簡単で1対多、多対多のデータの扱いもすんなりできます。

RLS(row level security)

Firebaseのセキュリティルールに対応するものでデータベースのセキュリティルールはPostgreSQLのRLSを記述する形となります。

Database Function

supabaseでデータベースのとある操作をトリガーにして発火できるストアドプロシージャを作ることができます。
作成した関数はsupabaseクライアント(Next.jsなど)から直接呼び出すこともできるので、さまざまな用途で使える機能です。
(スケジュール実行もできそう?🤔 調査します・・・)

subscription

WebSocketでデータベースの変更をクライアントに通知することができ、リアルタイム系の処理も簡単にできます。

TypeScript型生成

参考: Supabase CLI reference

テーブル構造からTypeScriptの型を自動生成できます。
無敵です。

などなどポイント高いことがいろいろできある程度の規模までバックエンドを全部こいつで任せられそうだしTypeScriptとの相性も非常に抜群です。

本題: トランザクションについて

扱っててとてつもなく悩んだのがトランザクションについてです。
PostgreSQLを使用しているのでトランザクション機能が使えるはず!と思ってドキュメントを漁りましたがどこにも何もトランザクションについて触れてなかったです・・・🤔

結論:Database Functionsをつかう

一対多、多対多のデータの扱いなどトランザクションが必要な処理の場合database functionsを書いてNext.jsから呼び出せばできました。
おそらくDatabase Functionsの記述は1つのトランザクション内で行われてそうです。

publicスキーマでの作成で
parents_data: jsonbchildren_data: jsonbをArgumensに受け取り

DECLARE
  parent_id int8;
  item jsonb;
BEGIN
    INSERT INTO parent (col1, col2)
    VALUES (parents_data->>'col1', parents_data->>'col2') 
    RETURNING id INTO parent_id;
     IF children_data IS NOT NULL THEN
       FOR item IN SELECT * FROM jsonb_array_elements(children_data::jsonb)
       LOOP
         INSERT INTO parent_children (children_id, parent_id)
         VALUES (uuid(item->>'children_id'), parent_id);
       END LOOP;
     END IF;
END;

上記のように記述します。
今回はparentsテーブルとchildrenテーブルの多対多の登録でparent_childrenを中間テーブルに置いて親テーブルに値を入れるという例で作ってみました。

これをNext.jsで呼び出す時は

const { error } = await supabase.rpc('関数名', {
      parents_data: {
        col1: hogehoge
        col2: hg
      },
      tags_data: {
        children_id: 略   
      }
    });

的な感じで呼び出してエラーハンドリングをすればトランザクション処理ができました。

感想

supabaseとてもいいですが情報が少ないのと(日本語の情報が全然ない)ドキュメントが漁りにくいのがちょっと苦しめです。

が、BaaSによってフロントエンドの知識+@でアプリやある程度のシステムをクオリティも確保した上で作ることができるようになってきている感じがしてもっとキャッチアップしていきたいと思いました。
ある程度の規模までならバックエンドエンジニアの手を借りることなく開発が進められるいいサービスなのでもっと認知されてほしいところです・・・


株式会社ECNはPHP、JavaScriptを中心にお客様のご要望に合わせたwebサービス、システム開発を承っております。
ビジネスの最初から最後までサポートを行い
お客様のイメージに合わせたWebサービス、システム開発、デザインを行います。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。