Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JP_Stripes: 一貫性に寄与する設計

acomagu
February 28, 2020

JP_Stripes: 一貫性に寄与する設計

200228 JP_Stripes in 会津 Vol.2
The Designium Inc. 伊藤勇希

前回: https://speakerdeck.com/acomagu/stripedehazimetefalsejue-ji

acomagu

February 28, 2020
Tweet

More Decks by acomagu

Other Decks in Programming

Transcript

  1. 自己紹介 - 伊藤勇希 @acomagu (あこまぐ) - 会津大学 学部4年 - 最近の趣味:

    音ゲー / VTuber - 最近好きな技術: Go / TypeScript / Linux / Semantic Web / Solid
  2. 前回のおさらい - バスチケットの購入/利用ができる PWA - TypeScript + AWS Lambda +

    Auth0 + Stripe - Stripe の購入履歴と自前のデータベースとの一貫性が壊れ るリスクを避けるため、データベースを用意しない設計を選 択
  3. しかし課題が浮かび上がる - Stripe からのレスポンスが想像 以上に遅い - API コール 1 回だいたい

    1 〜 3 秒くらいの幅がある - 「チケットの表示に時間がかかる と降りる直前に焦る」という意見 ↓ チケット取得 API のレイテンシ
  4. しかし課題が浮かび上がる さらに - 現状フロントとの実装の兼ね合いもあり「全ての購入履歴を取得」している - Auth0 ユーザーとの紐付けは email フィールド(Stripe Checkout

    クライアント 専用組み込みを利用しているため、metadata が利用できない) - そうすると購入履歴が膨れるに従って、線形的に API コールの時間が長くな る - 1度の API コールで 100 件までしか履歴を取得できないため
  5. 案1: 決済時にフロントからデータを送ってもらう 1. 決済が成功したときに、Stripe から決済 ID を送ってもらう 2. 決済 ID

    を Stripe に問い合わせ、独自データベースを更新する 問題点: 例えば決済は成功したが、決済 ID の送信に失敗したらどうする? → 不整合
  6. 寄り道: Stripe Webhook とは? - Stripe のアカウントに「何らかの出来事」が起こったときにそれを Webhook で知ら せてくれる仕組み

    - 設定次第で Stripe 上で履歴が残るような出来事の全てをイベントとして受け取るこ とができる - 今回の場合、支払いが成功したときにその旨を HTTP で受け取れる
  7. 案3: Stripe Webhook で受け取ったイベントを基に データベースを更新する (例えば)ユーザーが Stripe で決済を完了したとき、Stripe から決済情報を含むイベント をアプリケーションが受け取り、それに応じてユーザーが持つチケットを増やす

    レスポンス速度: 購入済みチケットの確認には Stripe を叩く必要がないので速い 反映までの早さ: ??? 破綻しにくさ: ユーザーデータ(独自データベース)の更新に失敗すると不整合が生まれ る...
  8. 案3: Stripe Webhook で受け取ったイベントを基に データベースを更新する (例えば)ユーザーが Stripe で決済を完了したとき、Stripe から決済情報を含むイベント をアプリケーションが受け取り、それに応じてユーザーが持つチケットを増やす

    レスポンス速度: 購入済みチケットの確認には Stripe を叩く必要がないので速い 反映までの早さ: ??? 破綻しにくさ: ユーザーデータ(独自データベース)の更新に失敗すると不整合が生まれ る... でもイベントから定期的に再計算することはできるのでは?
  9. Event Sourcing の重要な3特性 - Complete Rebuild: アプリケーションの状態をイベントだけで再現することができる - Temporal Query:

    アプリケーションのある時点の状態(例えば1ヶ月前など)を再現 することができる - Event Replay: もしあるイベントが間違っていた場合、イベントを修正してもう一度 計算することでアプリケーションを正しい状態に修正することができる
  10. その他の Event Sourcing の特徴 - Reversing Events: イベントを「逆適用」することで、いわゆる “Undo” が可能にな

    る - Paralell Models: ある地点でイベントを変化させた場合と変化させない場合の2パ ターンをリプレイすることで、2パターンの状態を観測できる(git のような)
  11. そもそも Stripe で Event Sourcing は可能なのか? Stripe Webhook で来るデータは Stripe

    Event と呼ばれる Stripe で取れる全てのデータは Stripe Event だけでも再現可能 間違いなくできる(とてもやりやすい)
  12. 実装上で考えなければならないこと - 「メールを送信する」などの外部に干渉するロジックがリプレイされると困るので確 認する(External Queries) - Gateway や Proxy と呼ばれるパターンで対応する

    - 「どのロジックがこのイベントをハンドルするか?」(Processing Selection Logic)をど こで考えるか。Event に持たせるのが OOP らしい - Stripe のイベントと Domain イベントの変換をどこでやるか - Stripe コンテキストと Stripe に依存しない主要ドメインを持ち、2つが通信する ようにした
  13. 「現在の状態を持つ DB」って本当に必要? 実は当初この DB は用意しない方針だった: 現在の状態をメモリ上にのみ持ち、アプリ ケーションが立ち上がるときに再計算することで実現できる →しかしアプリケーションのスケールとリクエストのロードバランシングが AWS Lambda

    依存になっている関係でそれが不可能ということがわかった(AWS だと全ての Lambda インスタンスにイベントをブロードキャストする方法がない) AWS「Lambda 関数はステートレスでなければなりません」
  14. まとめ - Event Sourcing とは「アプリケーションの状態を一連のイベントの列として表す設 計手法」 - 今回はその特性のうち Event Replay

    が必要だったので採用した - 「Stripe 上のデータと独自データベースの不整合」を防ぐのは難しいが、Event Sourcing を利用することで不整合の修正が安全に、追加のコード無しでできるよう になる - Stripe と Event Sourcing はとても相性が良い!