BLOG

R3 Cloud Journey

AWS

Amplify DataStore に新機能 "Selective Sync" が追加されました!

2020-11-03

Amplify DataStore を使っていますか?

Amplify DataStore を使うと、クラウドと連携するアプリケーションを容易に開発することができます。

例えば POS のようにオフラインでも高速に動作する必要があるが、定期的にサーバーサイド(物理サーバーを使用しないので何と表現するのが良いでしょうか・・クラウド側というかバックエンドというかマネージドデータベースというか)へデータを送り、複数の端末で共有したいアプリケーションには Amplify DataStore がまさにオススメです。POSのデータ同期の仕組みをイチから開発するような時代ではないのです。

また、入退室管理のような仕組みにも Amplify DataStore はオススメです。カードキーをかざした人を入室させて良いかはローカルで高速に判定しつつ、履歴はクラウドへ即座に・継続的に同期する、まさにそんな仕組みを作る際には Amplify DataStore の有り難みが身に染みるはずです。

他にも Amplify DataStore が有効なユースケースは多数考えられます。localStorage や Redux を使っているなら、それを Amplify DataStore に置き換えることを検討してみてください。そうです。Amplify DataStore はあらゆる state に適用できる可能性があります。

そんな Amplify DataStore に "Selective Sync" という新機能が追加されました。

Selective Sync は何を解決するのでしょうか? Amplify DataStore についておさらいしながら考えていこうと思います。

まず基本的な Webアプリを作成します。

このブログでも以前に Amplify DataStore の基本について説明した記事を書いたのですが、なぜか Ionic を使ってしまいました。(実際には中身はただの React なのですが)

Amplify DataStore (や AWS AppSync, Amplify)のワークショップ(サンプル)が https://amplify.aws/community/resources にまとめられています。

Angular でも React でも Vue でも好きなものを選んでください。私は今回 Vue を使用することにしました。

そして Amplify DataStore が動作するところまで ワークショップを進めたファイルを https://github.com/r3-yamauchi/amplify-datastore-chatty-vue/tree/DataStore に置いています。amplify init や amplify add api は各々の環境で行う必要がありますが、参考にはなると思います。

この状態で Webアプリを実行すると、DataStore の読み書き、AWS側(DynamoDB)との同期が行えるようになっています。(この記事の状態)

どのようなユーザーでログインしても、全ての人が書き込んだ全てのデータが流れてくるようになっています。

それぞれのユーザー、ブラウザで書き込んだ内容が他方へも即座に反映される

自分が書き込んだ情報を自分にしか見られない(他人が書き込んだ情報は参照できない)ようにするにはどうすれば良いでしょうか。

GraphQL Transformer内で @auth ディレクティブを使う方法があります。

以下のように schema.graphql で model に @auth ディレクティブを付けると オーナー認可することができます。

type Chatty
  @model
  @auth(
    rules: [
      { allow: owner, ownerField: "user", operations: [create, update, delete, read] },
    ])
{
  id: ID!
  user: String!
  message: String!
  createdAt: AWSDateTime
}

このうえで amplify codegen models して amplify push すると、同じユーザーでログインした書き込みのみ参照でき、subscribe されるようになります。

この状態のコードを https://github.com/r3-yamauchi/amplify-datastore-chatty-vue/tree/auth に置きましたので参考にしてください。

(以前の状態との差分は https://github.com/r3-yamauchi/amplify-datastore-chatty-vue/compare/DataStore...r3-yamauchi:auth )

以上は、従来でも実現できました。

"Selective Sync" (以降では syncExpression と呼ぶことにします)を使用すると DynamoDB を条件検索して、一部のデータのみを Amplify DataStore と同期することができるようになりました。

(なお、https://docs.amplify.aws/lib/datastore/conflict/q/platform/js#example で示されている通り、DataStore.configure で maxRecordsToSync や fullSyncInterval というパラメータを渡して DataStore と同期するレコード数に上限をかけたり、同期する間隔を指定することができたようです・・)

syncExpression を試した例が https://github.com/r3-yamauchi/amplify-datastore-chatty-vue/commit/93e4a1386fa99f2e50491c080b946f79c07bb597 です。

モデルに rate という Int 型の項目を追加し、 syncExpression で rate に 5以上 7以下の値を指定した場合のみ クラウド(DynamoDB)と同期するように指示しています。

DataStore.configure({
  syncExpressions: [
    syncExpression(Chatty, () => {
      return (c) => c.rate('gt', 5).rate('lt', 7);
    }),
  ]
});

クラウド(DynamoDB)と同期しないデータは他の端末へは伝搬されません。

この機能はどのようなユースケースで使用できるのでしょうか?

RicardoTwitter に書いていたように @auth ディレクティブではカバーしきれない「マルチテナント」(データの分離)で使用することが思い浮かびます。

また、古いデータは同期せず、直近のデータのみを同期してレスポンスを上げるためにも使用できます。

従来は Amplify DataStore と同期させている DynamoDB テーブルには あまり長期間データを置くことはせず、DynamoDB Streams を使用して他へ書き出し、TTLを設定して一定期間後に削除するのがお決まりのパターンでした。

相変わらず TTLを設定するケースが多いとは思いますが、そのうえで ページ送りや無限スクロールを実装する際に syncExpression を使用できそうです。

Reevaluate expressions at runtime の項で説明されている通り、syncExpression の内容を切り替えることができるからです。

let rating = 5;

DataStore.configure({
  syncExpressions: [
    syncExpression(Chatty, () => {
      return (c) => c.rate('gt', rating);
    }),
  ]
});

    async changeSync() {
      rating = 1;
      await DataStore.stop();
      await DataStore.start();
      this.loadMessages();
    }

また @key ディレクティブを指定すれば DynamoDB に GSI を付け、scan を避けることもできるようです。

Amplify DataStore のパフォーマンスに悩まされていた方はぜひ "Selective Sync" を試してみる価値がありそうです。

ページ送りや無限スクロールを GraphQLクエリ(で AWS AppSyncにアクセスする)で実装するのは、定形パターンではありますが手間がかかります。

Amplify DataStore の方が圧倒的にラクなのではないでしょうか?

Amplify DataStore は決して GraphQL(AWS AppSync)を置き換えるものではないので、まずは Amplify DataStore を使って実装することを考え、足りない部分を DynamoDB Stream や AppSync で補うように考えるのが良いように思います。

AWS
vuejs

アールスリーインスティテュートで、これまでになかった画期的な kintoneカスタマイズサービス gusuku Customine(カスタマイン) を開発しています。 kintone認定アプリデザイン/カスタマイズ スペシャリスト

R3のご提供サービス
自社のシステム開発・移行などをご依頼したい方
お客様とともに作りながら考える
新しいシステム開発
kintone導入・アプリ開発・カスタマイズにお困りの方
kintoneをもっと使いやすくする
gusukuシリーズ