API(Graphql)に関する参考URL

AWS ログインから利用まで

■EC2インスタンスの設置からファイアーウォール設定まで全体の流れ

  1. EC2インスタンスを設置

    ーAMIの選択

    インスタンスタイプの選択

    インスタンスの詳細の設定

    ーストレージの追加

    ータグの追加

    ーセキュリティグループの設定

    SSHキーペアの設定

  2. Apacheをインストール

    SSHでサーバーにログイン

    Apacheをインストール

  3. ファイアーウォールを設定

    ーセキュリティグループのポート80番を開ける

  4. ElasticIPアドレスの設定

SSHで(macから)サーバーにログイン

  1. EC2インスタンス作成での、「手順7.確認」で生成するキーペアを、デスクトップとかにダウンロード(秘密鍵。○○.pem)。
  2. SSH接続の準備。ダウンロードした秘密鍵パーミッションを600に変更。

    ターミナルで

    chmod 600 ~/Desktop/aws-and-infra-ssh-key.pem

    など。

  3. AWSのEC2のダッシュボードに移動。メニューから「インスタンス」→「(鍵とあっている)インスタンス」にチェックを入れる。

  4. 「詳細」タブの、パブリック IPv4 アドレスをコピー。

  1. ターミナルで

    ssh -i  ~/Desktop/aws-and-infra-ssh-key.pem ec2-user@3.85.232.201

    Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

  1. ターミナルで

    exit

    でログアウト。作業が終わったら、サーバーとの接続は切るようにする。

  2. ポート番号を念の為確認。EC2に再度接続したら、ターミナルで

    sudo lsof -i -n -P

    でenterすると、どのポート番号でどのプログラムが待ち受けているか確認できる。-iはネットワークソケットファイルを表示するオプションで、サーバーの待機コードとプロセスを一覧にして表示。-nはIPアドレスをホスト名に変換しないオブション、-Pはポート番号をサービス名に変換しないオブション。これで、どのプログラムがどのポート番号で待ち受けているか知ることができる。

■(SSHmacからAWSに接続し)Apacheをインストール

  1. ターミナルで

    sudo yum update -y

    で、ルート権限でLinuxのライブラリをアップデートする、を実行。

  2. Apacheをインストール。

    sudo yum -y install httpd

  3. インストール完了後、Apacheを起動。

    sudo systemctl start httpd.service

  4. 問題なければ、起動したか確認。

    sudo systemctl status httpd.service

  1. (補足)プロセスを確認するコマンド。

    ps -axu

  2. (補足)プロセスの絞り込み

    ps -axu | grep httpd

  3. サーバーを起動した時、Apacheも一緒に起動するよう設定。

    sudo systemctl enable httpd.service

    enable:自動設定の起動をする、という意味。

  4. 確認。

    sudu systemctl is-enabled httpd.service

    enableと出たら成功。

■(SSHmacからAWSに接続し)Apacheをインストール

  1. 管理画面 - EC2 - インスタンス - 対象にチェック - 詳細タブから、パブリックIPアドレスをコピー。

  1. セキュリティタブから、セキュリティグループの該当リンクをクリック。
  2. 画面右下あたりの「Edit inbound rules」をクリック

  1. インバウンドルールを編集 から「ルールの追加」をクリック。

  1. パブリックIPv4でうまくアパッチの画面が出たらOK

■Elastic IPアドレスの設定

  1. Elastic IP から「Elastic IPアドレスの割り当て」をクリック

  1. 次の画面で何も設定せずに「割り当て」をクリック
  2. Ec2インスタンスに割り当てていく。

    「アクション」から「アクションの関連づけ」をクリック

  1. 次の画面で インスタンス を選び、セレクトではクリックすれば自動的に関連するデータが出てくるので、それを選択し「関連づける」をクリック

  1. 設定完了したら、割り当てられたIPアドレスをブラウザのURLにコピペして確認

  1. 問題なければ完了。ただし、インスタンスに紐付けていなかったり自動停止した場合課金されてしまうので、終了したら「アクション」- 「Elastic IPアドレス 関連づけの解除」をクリック、さらに「アドレスの開放」をクリック。そうすると課金されなくなる。

■Route53設定後の関連づけ

  1. ホストゾーンの作成まで完了していることが前提。
  2. 関連づけるIPv4アドレスをコピーし、ターミナルでEC2にSSH接続。
  3. ターミナルで

    dig 対象ドメイン NS +short

    で、お名前.comのネームサーバーが表示される。これはゾーンが委任されているから。IPアドレスを聞いたら、お名前.comが知っているよ、と返事したということ。

  1. このことから、お名前.comでネームサーバーをRoute53へ変更しなくてはならない、ということがわかる。
  2. お名前.comのネームサーバーの設定画面から「その他」を選び、Route53のネームサーバーの情報を出して置いて、一つ一つコピペして変更。72時間以内に反映されるらしい。。。

  1. 反映中の間に他のAレコードの設定をする。「レコードを作成」をクリック。
  2. 設定は以下のような感じ。

AWS 使い方の基本

■立ち上げ確認

  1. EC2にアクセスして、インスタンスが起動しているか確認する。
  2. Elastic IPを確認して、関連づけされているか確認する。
  3. RDSにアクセスして、データベースのステータスが利用可能になっているか確認する。

SSHでアクセス

  1. ターミナルで

    ssh -i ~/.ssh/aws-and-infra-ssh-key.pem ユーザーネーム@00.000.00.000

    ssh接続。

  2. ターミナルで

    mysql -h aws-and-infra-web.cr2moxdp4vzk.ap-northeast-1.rds.amazonaws.com -u root -p

    でデータベース接続。

■データベース作成

  1. ターミナルで

    CREATE DATABASE aws_and_infra DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

    で新規データベース作成。

  2. ターミナルで

    SHOW DATABASES;

    で作成したデータベースの一覧を表示。

  3. ターミナルで

    CREATE USER 'aws_and_infra'@'%' IDENTIFIED BY 'password';

    で、作りたいデータベース用のユーザーを作成。

    @以降が接続元のホストを指しているが『%』でなんでもいいことを示している。

    ユーザー名はaws_and_infra である。

    IDENTIFIED BY で接続時のパスワードを示している。

    パスワードはpassword である。

  4. 今作成したユーザーにデータベースを操作できる権限を付与。

    ターミナルで、

    GRANT ALL ON aws_and_infra.* TO 'aws_and_infra'@'%';

    全ての権限を全てのテーブルに指定のユーザーに付与、という意味になる。

  5. ここまでの設定はまだ反映されていない。

    ターミナルで

    FLUSH PRIVILEGES;

    で設定が反映される。

  6. 設定が反映されたか確認。

    ターミナルで

    SELECT user , host FROM mysql.user;

    で設定が反映されたか確認できる。

  7. MySQLに接続できるか確認。

    ターミナルで

    exit;

    で一度出る。

    そして、ターミナルで

    mysql -h aws-and-infra-web.cr2moxdp4vzk.ap-northeast-1.rds.amazonaws.com -u aws_and_infra -p

    で、新しいユーザー名で接続。

  8. 使用しない時は接続を切断すること。

    ターミナルで

    exit;

    MySQLとEC2からログアウトしておく。

Cognito にユーザーがプールされたら、DynamoDBのUserテーブルにユーザー情報が追加され、AppSyncでクエリできるようにするには

要件は

  1. ユーザー閲覧機歴機能 (No.1) ユーザーとMovieのデータベースを紐づける
  2. ユーザー閲覧機歴機能 (No.2) ユーザーが閲覧したら、該当のサイドナビゲーションにチェックが付く
  3. ユーザー閲覧機歴機能 (No.3) ユーザーが閲覧したら、プロフィールに閲覧記録が書かれる

まずは、「1」の作成に必要な、全体工程は以下。

■「1. ユーザー閲覧機歴機能 (No.1) ユーザーとMovieのデータベースを紐づける工程の全体感

  1. Bitbucketへ、新たな空のリポジトリ「applat_release03」を作り、作業ディレクトリにクローンする。
  2. Cognito -Lambda - DynamoDB - AppSync のトリガーフローが通った、新しい開発(公開)環境「applat-release03」を、新しいプロファイル「dev00003」で構築する。3. の環境に新しいnextプロジェクトと共に構築。

    イベントは2つ。認証後とログイン後。

  3. 現在の開発環境「applat-release02」のデータベースのエクスポート先を、S3のパケットに作る。

    1. の「Movie」「Caption」(各言語分)のテーブルを全てエクスポート。
      1. で作成したパケットから、3. で新たに作った環境のDynamoDBへ、各言語のMovieとCaptionのデータをインポートする。
    1. で作った新しいローカル環境へ、「applat-release02」のフロントエンド部分を移行する。バックエンドに関わるsrcフォルダやAmplifyフォルダは絶対移動させないこと。
    1. で作った新しいリポジトリにpushする
  4. 全体をamplify push、そしてamplify publishする。

ここまでで、要件1 が完了する。

ここからは、

  • -

Cognito -Lambda - DynamoDB - AppSync のトリガーフローが通った、新しい開発(公開)環境「applat-release03」を、新しいプロファイル「dev00003」で構築する。3. の環境に新しいnextプロジェクトと共に構築。

イベントは2つ。認証後とログイン後。

  • -

について、記録していく。

■「2」Cognito -Lambda - DynamoDB - AppSync のトリガーフローについて

1. Amplify プロファイル設定

Amplify を使ったプロジェクト用のI AMユーザを、以下のコマンドで生成する。

amplify configure

そして、プロファイル名を設定。

2. Next.jsのインストール

next.jsフレームワークの新規作成

npx create-next-app .

3. 初期化

プロジェクトの初期化

amplify init

4. 最低限必要な依存関係のインストール

yarn add @aws-amplify/ui-react aws-amplify

参考URL

4. AppSyncとUserテーブルほか必要なテーブルの作成

amplify add api

スキーマのコードは以下。

ここでauthを仕込んでおけば、次のamplify pushでauthのフローが始まる。

type User @model
@auth(
  rules: [
    {allow: groups, groups: ["Admin"]},
    {allow: owner, ownerField: "username", operations: [read]}
  ]
){
  id: ID!
  username: String
  email: String
  moviecheck: MovieCheck @hasOne
}
type MovieCheck @model
{
  id: ID!
  user: User @belongsTo
  checkuser: String
  checklist:[CheckList] @hasMany
}
type CheckList @model
{
  id: Int!
  lang: String!
  module: String!
  part: String!
  page: String!
  check: Boolean
  moviecheck: MovieCheck @belongsTo
}
type MovieEn @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionEn] @hasMany
  outurl: String
  outurltitle: String
  movieEnPlaymovieId: String!
}
type MovieInd @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionInd] @hasMany
  outurl: String
  outurltitle: String
  movieIndPlaymovieId: String!
}
type MovieVn @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionVn] @hasMany
  outurl: String
  outurltitle: String
  movieVnPlaymovieId: String!
}
type MovieTha @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionTha] @hasMany
  outurl: String
  outurltitle: String
  movieThaPlaymovieId: String!
}
type MovieTgl @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionTgl] @hasMany
  outurl: String
  outurltitle: String
  movieTglPlaymovieId: String!
}
type MovieRus @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionRus] @hasMany
  outurl: String
  outurltitle: String
  movieRusPlaymovieId: String!
}
type MovieNep @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionNep] @hasMany
  outurl: String
  outurltitle: String
  movieNepPlaymovieId: String!
}
type MovieKhm @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionKhm] @hasMany
  outurl: String
  outurltitle: String
  movieKhmPlaymovieId: String!
}
type MovieBur @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionBur] @hasMany
  outurl: String
  outurltitle: String
  movieBurPlaymovieId: String!
}
type MovieBen @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  url: String!
  pagetitle: String!
  playalltime: String!
  captions: [CaptionBen] @hasMany
  outurl: String
  outurltitle: String
  movieBenPlaymovieId: String!
}
type CaptionEn @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieEn @belongsTo
  movieEnCaptionsId: String!
}
type CaptionInd @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieInd @belongsTo
  movieIndCaptionsId: String!
}
type CaptionVn @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieVn @belongsTo
  movieVnCaptionsId: String!
}
type CaptionTha @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieTha @belongsTo
  movieThaCaptionsId: String!
}
type CaptionTgl @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieTgl @belongsTo
  movieTglCaptionsId: String!
}
type CaptionRus @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieRus @belongsTo
  movieRusCaptionsId: String!
}
type CaptionNep @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieNep @belongsTo
  movieNepCaptionsId: String!
}
type CaptionKhm @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieKhm @belongsTo
  movieKhmCaptionsId: String!
}
type CaptionBur @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieBur @belongsTo
  movieBurCaptionsId: String!
}
type CaptionBen @model
{
  id: ID!
  lang: String!
  module: String!
  part: String!
  page: String!
  content: Int
  startTime: String
  endTime: String
  body: String
  movie: MovieBen @belongsTo
  movieBenCaptionsId: String!
}

3. プッシュとauth

amplify push

すると、authのフローが始まる。

? Are you sure you want to continue?

Yes
Do you want to use the default authentication and security configuration?

Manual configuration
Select the authentication/authorization services that you want to use:

User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analyti
cs, and more)
Provide a friendly name for your resource that will be used to label this category in the project:

(そのままenter)
Enter a name for your identity pool.

(そのままenter)
Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM)

No
 Do you want to enable 3rd party authentication providers in your identity pool?

No
Provide a name for your user pool:

(そのままenter)
 How do you want users to be able to sign in?

Username
Do you want to add User Pool Groups?

Yes
? Provide a name for your user pool group:

Admin
? Do you want to add another User Pool Group

No
✔ Sort the user pool groups in order of preference ·

Admin
Do you want to add an admin queries API?

No
Multifactor authentication (MFA) user login options:

OFF
Email based user registration/forgot password:

Enabled (Requires per-user email entry at registration)
Specify an email verification subject:

Your verification code
Specify an email verification message:

Your verification code is {####}
 Do you want to override the default password policy for this User Pool?

No
What attributes are required for signing up?

Email
Specify the app's refresh token expiration period (in days):

7
 Do you want to specify the user attributes this app can read and write?

No
Do you want to enable any of the following capabilities?

(何も選ばずそのままenter)
Do you want to use an OAuth flow?

No

ここでやっとLambdaとの連携話が登場!

? Do you want to configure Lambda Triggers for Cognito?

Yes
? Which triggers do you want to enable for Cognito

Post Confirmation
? What functionality do you want to use for Post Confirmation

Create your own module
? Do you want to edit your custom function now?

Yes

これで、Lambda用のcustom.jsが立ち上がるので、以下の通り入れる。

 var aws = require('aws-sdk');
 var ddb = new aws.DynamoDB();
 exports.handler = async (event, context) => {

     let date = new Date();
     if (event.request.userAttributes.sub) {
         let params = {
             Item: {
                 'id': {S: event.request.userAttributes.sub},
                 '__typename': {S: 'User'},
                 'username': {S: event.userName},
                 'email': {S: event.request.userAttributes.email},
                 'createdAt': {S: date.toISOString()},
                 'updatedAt': {S: date.toISOString()},
             },
             TableName: process.env.USERTABLE
         };
         // Call DynamoDB
         try {
             await ddb.putItem(params).promise()
             console.log("Success");
         } catch (err) {
             console.log("Error", err);
         }
         console.log("Success: Everything executed correctly");
         context.done(null, event);
     } else {
         // Nothing to do, the user's email ID is unknown
         console.log("Error: Nothing was written to DynamoDB");
         context.done(null, event);
     }
 };

上記が立ち上がると

? Do you want to generate code for your newly created GraphQL API

Yes

GraphQL endpoint: https://5oessai6vbfgdfwc7kcgmydika.appsync-api.ap-northeast-1.amazonaws.com/graphql

GraphQL API KEY: da2-w7uygek4yjhutlsyyuqbq2uihq

4. Amplifyのコンソール画面から

amplify console

「AppSyncで表示」をクリック

DynamoDBの基本文法

参考URL

https://www.wakuwakubank.com/posts/639-aws-dynamodb-introduction/

特徴

  • Key-Value型のNoSQLデータベースサービス
  • 事実上無制限のスループットとストレージ
  • 管理作業をまかせられる
  • DynamoDBストリーム をトリガーとしたLambadaの実行
    • 項目の追加、変更、削除をイベントとして検出
  • キャパシティーユニット による利用量の事前に設定が可能
    • 1秒あたりの 読み込み 書き込み の回数上限を決めて料金が決定される

構成要素( Table, Item, Attribute )

RDSと比較すると以下のようになります。

DynamoDB RDS
テーブル(Table) テーブル
項目(Item) レコード
属性(Attribute) カラム

プライマリキー

セカンダリインデックス

  • プライマリキー以外の属性で、データに効率的にアクセスできるようにする
  • 2種類をサポート

DynamoDB%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%96%87%E6%B3%95%2028149472728249378933fb8bd5c0d7d2/3297409e957ddb00ac072123554269c0d7599e073ed2cb39eec05df510

DynamoDBへのデータインポート

■DynamoDBにテーブルを作成

以下は作成の仕方の一例。

(参考URL)

  1. DynamoDB コンソール (https://console.aws.amazon.com/dynamodb/) を開きます。
  2. [テーブルの作成] を選択します。
  3. [DynamoDB テーブルの作成] 画面で、次の操作を行います。
    1. [テーブル名] ボックスに、「Forum」と入力します
    2. [プライマリキー] の [パーティションキー] ボックスに「Name」と入力します。データ型を [文字列] に設定します。
  4. すべての設定が正しいことを確認したら、[作成] を選択します。

■アクセスキーとシークレットキーとリージョンの確認

(参考URL)https://qiita.com/kaito_program/items/7b9ba489e44d2295cf6f

aws configure listコマンドを叩いて、アクセスキーとシークレットキーとリージョンが何と設定されてるか確認。

aws configure list

必ず、データをインポート前に、最初にこちらの操作を行い、ログインしているI AMと、それに紐づくDynamoDBのリージョン、そのI AMとアクセスキー&シークレットキーを確認する。

そして、5分くらいで、アクセスキーとシークレットキーは「デフォルト」に戻ってしまうセキュリティー上の仕様のようだ)ので、以下のコマンドで変更する。

export AWS_ACCESS_KEY_ID=****hogehoge*****
export AWS_SECRET_ACCESS_KEY=****hanihani*****

その後、PCの設定ファイルを変更

~/.zshrc

再度aws configure listを叩いてキー2つを確認する。

aws configure list

この後、5分以内に、再起動しないで、すぐに作業。

■データをテーブルにロード(インポート)

(参考URL)https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/SampleData.LoadData.html

(サンプルjson

DynamoDB%E3%81%B8%E3%81%AE%E3%83%86%E3%82%99%E3%83%BC%E3%82%BF%E3%82%A4%E3%83%B3%E3%83%9B%E3%82%9A%E3%83%BC%E3%83%88%20509f9e0627f641a9bfd58f21a5a9f34c/sampledata.zip

インポートするjsonデータが入っているディレクトリに移動し、以下のコマンドを実行。

aws dynamodb batch-write-item --request-items file://ファイル名.json

成功すると

{
    "UnprocessedItems": {}
}

とターミナルに出力される。

※その他

「パイプライン」を使う手もあるようだ。こちらは未だテストしていない。

https://docs.aws.amazon.com/ja_jp/data-pipeline/index.html

Schemaを修正した場合のアップデートの仕方

何度schemaを修正してから、Amplifyのバックエンドが壊れ、その度に初期構築からやり直しをしてきただろう。。。

特にCognitoが絡んできてからは、頻繁に起こった。

ようやく、schemaを修正してから、amplifyのアップデートの仕方がわかった!!

まずは、schemaを修正。

でも、ここの作りは、AppSync & DynamoDBとモロに関連するので、できれば複数の環境でテストできた方が安全。

次に、ステータスを確認

amplify status

api の欄がupdateとなっていれば確認完了。

ここがポイント!

次に、スキーマを再実行して更新。

amplify codegen models

公式サイトより、

「これにより、変更が評価され、基になるデバイス上のストレージ構造に影響を与える変更が検出された場合は、バージョン管理されたハッシュが作成されます。たとえば、タイプが追加/削除されたり、フィールドが必須/オプションになったりします。DataStore は起動時にこのバージョンを評価し、変更がある場合はデバイスのローカル アイテムが削除され、クラウドと同期している場合はAppSync からの完全同期が行われます。」

とのこと。

更新完了後、念の為ステータスを確認。

amplify status

まだapi の欄はupdateとなっているはず。

ここでプッシュ

amplify push

を実行。するとエラーが出て、

「An error occurred when pushing the resources to the cloud

🛑 An error occurred during the push operation: /

Removing a model from the GraphQL schema will also remove the underlying DynamoDB table.

This update will remove table(s) [CheckListTable]

ALL EXISTING DATA IN THESE TABLES WILL BE LOST!

If this is intended, rerun the command with '--allow-destructive-graphql-schema-updates'.」

(翻訳)

「リソースをクラウドにプッシュするときにエラーが発生しました

🛑 プッシュ操作中にエラーが発生しました: /

GraphQL スキーマからモデルを削除すると、基礎となる DynamoDB テーブルも削除されます。

この更新によりテーブルが削除されます [CheckListTable]

これらのテーブルの既存のデータはすべて失われます。

これが意図されている場合は、'--allow-destructive-graphql-schema-updates' を指定してコマンドを再実行してください。」

と出る。

初回であれば、最後に

amplify push -allow-destructive-graphql-schema-updates

と実行。

これで、Amplifyのバックグラウンドを壊すことなく、AppSync & DynamoDB のテーブル構造の修正&更新ができる!

※これは「1度」成功すれば、2回目からはamplify push だけで行けた。 手順の順番を守ことが重要みたい。

■アプリケーションを壊すやり方

3つある。どれが先でも、どちらか一つでも、壊れた。。。(AppSyncが効かなくなった)。

2度と、繰り返すことのないようにしたい!

1 schema修正後、

amplify push --y

をいきなり実行すること。

2 これも意味わからず

amplify update api

を実行すること。

3 DynamoDBのテーブルを手動で削除すること。

■理屈的なこと

以下はAppSyncとDynamoDBの仕組みの関係である。