AWS
AppSync

My first impression

AppSyncの感想

AppSync用語説明

AWS AppSync:
GraphQL API Managed service

Resolver:
AppSyncのデータ変換の処理を記述する箇所
defaultではVTLで記述する

AppSync採用時点

Managed Service なので便利

Subscriptionも
すぐに使える

DynamoDBとの組み合わせて簡単に始められる

serverless frameworkでも
サポートされている

実際に実装を始めたら

  • Velocityナツい、js実装があるんだ
  • テキストのテンプレートでロジックを記述する?
  • まったく構造化も再利用もできない!
  • テストどうするの?

VTLって何!

  • queryの制約キツすぎる!
  • テーブル設計が全然違う!
  • 1テーブルに全て集約するの?

DynamoDB
ムズい

serverless frameworkの offline実行が便利

VTL (Velocity Template Language)

#set($expression = "")
#set($expressionNames = {})
#set($expressionValues = {})

#foreach($key in $ctx.args.input.keySet())
    #if ($expression.length().equals(0))
    	#set($expression = "SET #$key = :$key")
    #else
    	#set($expression = "${expression}, #$key = :$key")
    #end
    $util.qr($expressionNames.put("#$key", $key))
    $util.qr($expressionValues.put(":$key", $ctx.args.input.get($key)))
#end

{
    "version" : "2018-05-29",
    "operation" : "UpdateItem",
    "key" : {
        "key": $util.dynamodb.toDynamoDBJson($ctx.args.key)
    },
    "update" : {
        "expression": "$expression",
        "expressionNames": $util.toJson($expressionNames),
        "expressionValues": $util.dynamodb.toMapValuesJson($expressionValues)
    }
}

VTL (Velocity Template Language)

## [Start] Determine request authentication mode **
#if( $util.isNullOrEmpty($authMode) && !$util.isNull($ctx.identity) && !$util.isNull($ctx.identity.sub) && !$util.isNull($ctx.identity.issuer) && !$util.isNull($ctx.identity.username) && !$util.isNull($ctx.identity.claims) && !$util.isNull($ctx.identity.sourceIp) && !$util.isNull($ctx.identity.defaultAuthStrategy) )
  #set( $authMode = "userPools" )
#end
## [End] Determine request authentication mode **
## [Start] Check authMode and execute owner/group checks **
#if( $authMode == "userPools" )
  ## [Start] Owner Authorization Checks **
  #set( $isOwnerAuthorized = false )
  ## Authorization rule: { allow: owner, ownerField: "owner", identityClaim: "cognito:username" } **
  #set( $allowedOwners0 = $util.defaultIfNull($ctx.args.input.owner, null) )
  #set( $identityValue = $util.defaultIfNull($ctx.identity.claims.get("username"), $util.defaultIfNull($ctx.identity.claims.get("cognito:username"), "___xamznone____")) )
  #if( $util.isList($allowedOwners0) )
    #foreach( $allowedOwner in $allowedOwners0 )
      #if( $allowedOwner == $identityValue )
        #set( $isOwnerAuthorized = true )
      #end
    #end
  #end
  #if( $util.isString($allowedOwners0) )
    #if( $allowedOwners0 == $identityValue )
      #set( $isOwnerAuthorized = true )
    #end
  #end
  #if( $util.isNull($allowedOwners0) && (! $ctx.args.input.containsKey("owner")) )
    $util.qr($ctx.args.input.put("owner", $identityValue))
    #set( $isOwnerAuthorized = true )
  #end
  ## [End] Owner Authorization Checks **

  ## [Start] Throw if unauthorized **
  #if( !($isStaticGroupAuthorized == true || $isDynamicGroupAuthorized == true || $isOwnerAuthorized == true) )
    $util.unauthorized()
  #end
  ## [End] Throw if unauthorized **
#end
## [End] Check authMode and execute owner/group checks **
  • DynamoDBは、いわゆるKey-Value Store
  • そのため全てのデータに一意なKeyが必要
  • Keyは以下の2種類のどちらか
    • Partition Keyのみ
    • Partition KeyとSort Keyのセット
  • Partition Key: 格納するpartitionを決める
  • Sort Key: partitionの中でのデータ順を決める

DynamoDB

  • データの取得方法は以下の3つ
    • GetItem:
      • Keyを指定してデータを1つ取得
    • Query:
      • Partition Keyを指定して複数のデータを取得、Sort Keyを使って範囲をフィルタすることも可能
    • Scan:
      • テーブルのデータを全件取得

DynamoDB

一通りの実装が終わって

それならDynamoDB を使う必要もなかったね

Lambda
Resolverで
良くない?

  • アクセス周りのテストが重要
  • 実際にアクセスする必要があるので結合テストが必要

DynamoDBは癖強すぎ

serverless frameworkは

GraphQLのschemaでtimestampは何の型で定義していますか?

標準のScalarとしては以下の5つだけ

  • Int: 32bit整数 (signed)
  • Float: 倍精度浮動小数点数 (64bit)
  • String: 任意の文字列 (UTF-8)
  • Boolean: `true` or `false`
  • ID: 一意の文字列

timestampとしてunix timeを採用する場合、

32bit signed-integerなのでミリ秒が含められない&2038年問題があります。

64bit の整数型があれば、ミリ秒もしくはマイクロ秒まで含められるのですが、AWS AppSyncではCustom Scalar typeを追加することができないため無理でした。

質問:GraphQLで
timestampの型は?

仕方ないので、今回は文字列で時刻をISO 8601フォーマットにしたものを使うことにしました。追加でサーバ側で受け取った文字列を、正規化してタイムゾーンをUTCに変換する処理を入れてます。

変換処理が必要なのはbackendがDynamoDBなので、Datetimeを保存する用の型が用意されていないため、ただの文字列として保存しないとならないのが原因ですかね?

 

他のプロジェクトではどうしているか、聞きたいです。

質問:GraphQLで
timestampの型は?

Thank You!

参考Link

AWS AppSync - My first impression

By Hiroki Horiuchi

AWS AppSync - My first impression

  • 188