Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
カーナベルにおけるProtobuf二次利用例
Search
andoshin11
February 23, 2025
Technology
0
110
カーナベルにおけるProtobuf二次利用例
カーナベルでProtobufの運用とコード生成を使い倒しているPlatform Engineeringの事例を紹介します
andoshin11
February 23, 2025
Tweet
Share
More Decks by andoshin11
See All by andoshin11
Envoy External AuthZとgRPC Extensionを利用した「頑張らない」Microservices認証認可基盤
andoshin11
0
630
カーナベル株式会社2024年2月 エンジニアイベント資料
andoshin11
0
340
Private Cloudを支える最高のユーザーガイド運用技術
andoshin11
0
300
TS CompilerがVueを喋れても良いじゃないか
andoshin11
0
730
ain't giving up type-safe Express
andoshin11
2
440
Type Safe "Everything"
andoshin11
0
250
Hack your Nuxt router!
andoshin11
0
1.3k
GatewayパターンとSchema駆動開発
andoshin11
7
1.4k
Catch up Nuxt.js 2019.02
andoshin11
0
2.1k
Other Decks in Technology
See All in Technology
Javaで作る RAGを活用した Q&Aアプリケーション
recruitengineers
PRO
1
100
Prox Industries株式会社 会社紹介資料
proxindustries
0
270
登壇ネタの見つけ方 / How to find talk topics
pinkumohikan
3
350
Oracle Cloud Infrastructure:2025年6月度サービス・アップデート
oracle4engineer
PRO
2
230
プロダクトエンジニアリング組織への歩み、その現在地 / Our journey to becoming a product engineering organization
hiro_torii
0
130
低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 / Building a C Compiler for PHPers Who Want to Dive into Low-Level Programming - Expanded
tomzoh
4
3.1k
250627 関西Ruby会議08 前夜祭 RejectKaigi「DJ on Ruby Ver.0.1」
msykd
PRO
2
240
UIテスト自動化サポート- Testbed for XCUIAutomation practice
notoroid
0
130
「Chatwork」の認証基盤の移行とログ活用によるプロダクト改善
kubell_hr
1
140
AIのAIによるAIのための出力評価と改善
chocoyama
2
540
SalesforceArchitectGroupOsaka#20_CNX'25_Report
atomica7sei
0
140
Navigation3でViewModelにデータを渡す方法
mikanichinose
0
220
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
231
18k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Designing Experiences People Love
moore
142
24k
The Invisible Side of Design
smashingmag
299
51k
Why Our Code Smells
bkeepers
PRO
337
57k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
22k
A Modern Web Designer's Workflow
chriscoyier
694
190k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.8k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Become a Pro
speakerdeck
PRO
28
5.4k
Transcript
カーナベルにおけるProtobuf 二次利用事例 2025/02/23 カーナベル社内勉強会 @andoshin11
今日話すこと 1. スキーマ駆動開発のおさらい + Protobuf運用の現状確認 2. ProtobufからJSON Schema validatorを生成した苦労話 3.
E2E Coverage計測のためのOSSを開発した話
スキーマ駆動開発の おさらい
分散システムとスキーマ駆動開発 • カーナベルのRepositories構成 ◦ Frontend ▪ selling-web, profile-web, admin-frontend ◦
Backend ▪ Inventory Service, Authority Service, TCG Service, etc… ◦ Infrastructure ▪ ka-nabell-terraform, tcg-platform-manifests ◦ Schema ▪ tcg-platform-proto
分散システムとスキーマ駆動開発 • カーナベルのRepositories構成 ◦ Frontend ▪ selling-web, profile-web, admin-frontend ◦
Backend ▪ Inventory Service, Authority Service, TCG Service, etc… ◦ Infrastructure ▪ ka-nabell-terraform, tcg-platform-manifests ◦ Schema ▪ tcg-platform-proto API Schemaを独立したRepositoryに 切り出しているのが特徴 ↓ システム間の契約としてのスキーマの Ownershipをアプリケーションから切り離す
分散システムとスキーマ駆動開発 ◦ 古典的なAPI運用 ▪ Server > Clientという一方通行の主従関係 ▪ Backend依存の同期的な開発工程 ▪
自然言語で記述された「API定義書」の保守
分散システムとスキーマ駆動開発 ◦ モダンなスキーマ駆動開発 ▪ スキーマ = システム間の契約 ▪ スキーマさえ定義されていればBackend, Frontendともに非同期
な開発進行が可能に ▪ 標準記法によるmachine readableなスキーマ定義 • Protocol Buffer, Open API, GraphQL, etc… ▪ 各種言語向けのServer & Clientコードを自動生成可能 • → 仕様と実装が一致する ▪ テストコードやUtilityツールも自動生成可能
分散システムとスキーマ駆動開発 ◦ モダンなスキーマ駆動開発 ▪ スキーマ = システム間の契約 ▪ スキーマさえ定義されていればBackend, Frontendともに非同期
な開発進行が可能に ▪ 標準記法によるmachine readableなスキーマ定義 • Protocol Buffer, Open API, GraphQL, etc… ▪ 各種言語向けのServer & Clientコードを自動生成可能 • → 仕様と実装が一致する ▪ テストコードやUtilityツールも自動生成可能 Protocol Bufferで定義された API Schemaを使い倒す
Protocol Bufferの二次利用 ◦ API定義としてのProtobufからコード自動生成して二次利用する ◦ 現在自動生成しているもの ▪ APIドキュメント(protoc-gen-doc) ▪ TypeScript向けの型定義(ts-proto)
▪ Nest.js Server向けのMethod Handler(ts-proto) ▪ gRPC-Web向けのClientコード(protoc-gen-grpc-web) ▪ Request & Response型のJSON Schema(typescript-json-schema) ▪ ECMASCript向けのJSON Schema Validator(ajv) ◦ その他の二次利用 ▪ API認可スコープの定義(Speaker Deck) ▪ E2Eテストのカバレッジ計測(proto-coverage-reporter)
Protocol Bufferの二次利用 ◦ API定義としてのProtobufからコード自動生成して二次利用する ◦ 現在自動生成しているもの ▪ APIドキュメント(protoc-gen-doc) ▪ TypeScript向けの型定義(ts-proto)
▪ Nest.js Server向けのMethod Handler(ts-proto) ▪ gRPC-Web向けのClientコード(protoc-gen-grpc-web) ▪ Request & Response型のJSON Schema(typescript-json-schema) ▪ ECMASCript向けのJSON Schema Validator(ajv) ◦ その他の二次利用 ▪ API認可スコープの定義(Speaker Deck) ▪ E2Eテストのカバレッジ計測(proto-coverage-reporter) 今日はこの辺の話をします
JSON Schema Validatorの生成
型安全性の静的検証と動的検証 ◦ 「変数Aが〇〇型であること」をシステム横断で担保するのは難しい ▪ TSの型定義では〇〇型が入っているがDBには△△型で入ってる ▪ Client schemaとServer schemaのバージョン違いによる齟齬 ▪
ネットワーク境界やBrowser Storageを跨ぐ際のSerialize & Desirializeによる型互換性の消失 ▪ etc… ◦ TS CompilerやPrisma Schemaによる静的型チェックだけでは担保に 限界がある ◦ 特にBackend Serverに対して悪意のあるデータが混入するとシステム 障害やデータ汚染につながるリスクもある
型安全性の静的検証と動的検証 ◦ やりたきこと: ▪ ネットワーク境界を跨いでBackend Serverに到達するリクエス トをランタイムで厳密に検証したい • 型チェック •
必須プロパティのチェック • 不要プロパティの排除 • etc… ▪ Clientに返却するデータもランタイムチェックを行ってあげたい
市中のソリューション ◦ protovalidate ▪ Protoエコシステムのリーダーであるbuf社のツール ▪ Go, C++, Java, Pythonには対応しているがTS対応はなし
▪ 1ヶ月ほど前にようやくTS対応スタート(issue #67) ▪ 今年前半にアルファリリース予定 ◦ protoc-gen-jsonschema ▪ 記憶が曖昧だが、調査時点(2023年1月)で我々のプロジェクトで は利用できない問題があった ▪ メンテも止まっており現在はarchive済み
市中のソリューション ◦ protovalidate ▪ Protoエコシステムのリーダーであるbuf社のツール ▪ Go, C++, Java, Pythonには対応しているがTS対応はなし
▪ 1ヶ月ほど前にようやくTS対応スタート(issue #67) ▪ 今年前半にアルファリリース予定 ◦ protoc-gen-jsonschema ▪ 記憶が曖昧だが、調査時点(2023年1月)で我々のプロジェクトで は利用できない問題があった ▪ メンテも止まっており現在はarchive済み 自前のJSON Schema Validatorを生成しよう
JSON Schema 任意のデータ型の構造定義 + 検証に利用できる標準仕様 json-schema.org
Protobuf → JSON Schemaの生成 ◦ 直接JSON Schemaを生成できるツールはない(前述) ◦ TypeScript interfaceからJSON
Schemaを生成するツールはある (typescript-json-schema) ◦ Protobuf → TypeScript(ts-proto) → JSON Schemaという多段変換 ならいけそう!!
Protobuf → TS → JSON Schema
typescript-json-schemaの落とし穴 ◦ デフォルトのvalidation制約がイマイチ・・・ ▪ string型: 空文字も許容されてしまう ▪ array型: 空配列が許容されない ▪
etc… ◦ → そのままでは弊社のユースケースに適合しない
typescript-json-schemaの落とし穴 ◦ annotationsを付与することで制約を変更できるらしい
typescript-json-schemaの落とし穴 ◦ annotationsを付与することで制約を変更できるらしい ts-protoの生成したTSファイルを 事前加工する必要がある
TypeScript Compiler API ◦ TSファイルを型レベルで解析・加工できる公式API ◦ 内部的にはTSファイルを文字列ではなくAST(抽象構文木)として扱う のが特徴 ◦ Reference:
Using the Compiler API
TypeScript AST Viewerで遊んでみよう Link
TS interfaceにannotationを付与する ◦ typescript-json-schema向けに下記のルールでannotationを付与する ◦ string型 → reqreuid stringなら「@minLength 1」をcomment挿入
◦ array型 → required arrayなら「@minItems 0」をcomment挿入
TS interfaceにannotationを付与する ASTを再帰関数で走査(トラバース)してcommentsを付与
TS interfaceにannotationを付与する 加工したASTをファイル文字列に復元するprinterで出力
JSON Schema Validatorへの変換 ◦ typescript-json-schemaでTS → JSON Schemaに変換 ◦ ajvでJSON
SchemaからECMAScript向けのvalidatorを生成 ▪ Node.js界隈ではデファクトのツール ▪ 複数のvalidation戦略 ▪ JIT(Just in Time) Compile • validation実行時にJSON schemaを読み込みにいき validation関数を内部生成する方式 ▪ AOT(Ahead of Time) Compile • 事前に各JSON Schemaに対応したvalidation関数をビルド し、関数exportする方式 • カーナベルではこちらを利用
まとめ ◦ 安全なBackend Server実装のために値を動的検査できるランタイム validatorが欲しい ◦ エコシステムが貧弱なので自前でProto → TS →
JSON Schema → JSON Schema Validatorへ変換する仕組みが必要 ◦ ライブラリ制約でTS生成後にCompiler APIを用いたファイル加工が必 要 ◦ ajvはAOT Compileしたstandaloneなvalidation関数を生成
まとめ ◦ 安全なBackend Server実装のために値を動的検査できるランタイム validatorが欲しい ◦ エコシステムが貧弱なので自前でProto → TS →
JSON Schema → JSON Schema Validatorへ変換する仕組みが必要 ◦ ライブラリ制約でTS生成後にCompiler APIを用いたファイル加工が必 要 ◦ ajvはAOT Compileしたstandaloneなvalidation関数を生成 ◦ → めっちゃしんどいのでprotovalidateの登場を待ち侘びています
E2E Coverage計測 への取り組み
課題: • システムの肥大化によるAPIエンドポイントの増加 ◦ Customer Service → 25 APIs ◦
Inventory Service → 37 APIs ◦ Selling Service → 41 APIs ◦ TCG Service → 186 APIs(!?) ◦ And more… • デグレを避けるために自動テストの継続実行は必須 • テスト品質を定量的に観測・評価できる仕組みが欲しい
作ったもの proto-coverage-reporter
作ったもの proto-coverage-reporter どのAPIのテストが不十分なのか、 全体で何%のテスト記述が完了 したのか、が追えるのが嬉しい
内部実装の話 • 主に3つの機能で構成されている ◦ テスト結果記録機能 ◦ カバレッジ解析機能 ◦ レポーティング機能
内部実装の話: テスト結果記録機能 • 各テストシナリオにおいてどのAPIのどのStatusがテストされたのかを記録 する必要がある • 各シナリオにおけるリクエスト実行の数は不定 • gRPC Client向けのInterceptorを提供し、全てのAPI通信結果をログとし
て保存する
内部実装の話: テスト結果記録機能
内部実装の話: テスト結果記録機能 • 各テストシナリオにおいてどのAPIのどのStatusがテストされたのかを記録 する必要がある • 各シナリオにおけるリクエスト実行の数は不定 • gRPC Client向けのInterceptorを提供し、全てのAPI通信結果をログとし
て保存する • こだわりポイント: ◦ 各OS準拠のsystem temp directoryにログを格納するようにした ◦ 環境変数によるログディレクトリの指定も可能
内部実装の話: カバレッジ解析機能 • カバレッジ比率計測の母数となる各Method仕様をProtobufから解析 • Protobufには専用のextensionを用いてMethod Optionsを記述する
内部実装の話: カバレッジ解析機能
内部実装の話: カバレッジ解析機能 • こだわりポイント: ◦ extensionを定義したprotobufはPublic Repositoryにホスト ▪ → 外部からもアクセス可能
◦ 現在はstatus_codesのみ対応しているがより複雑なOptionも記述可能 ◦ ex: ignore rules, validation rules, etc…
内部実装の話: レポーティング機能 • Jestのcustom reporter APIを利用してレポーティング機能を実装 ◦ テストコンテキストの参照やLifecycle Hookを活用したテスト終了後 のログクリーンアップ等も可能
• cli-tableとchalkを利用した見やすいレポート出力 • こだわりポイント: ◦ octokitを利用してGitHub Actionsで実行された際はPull Requestに 結果をレポーティングするようにした ◦ すでにレポートコメントがある場合は都度更新を行うロジックを実装
Thank you!