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
160
カーナベルにおけるProtobuf二次利用例
カーナベルでProtobufの運用とコード生成を使い倒しているPlatform Engineeringの事例を紹介します
andoshin11
February 23, 2025
Tweet
Share
More Decks by andoshin11
See All by andoshin11
Introduction to gRPC Interceptors
andoshin11
0
82
Envoy External AuthZとgRPC Extensionを利用した「頑張らない」Microservices認証認可基盤
andoshin11
0
890
カーナベル株式会社2024年2月 エンジニアイベント資料
andoshin11
0
490
Private Cloudを支える最高のユーザーガイド運用技術
andoshin11
0
310
TS CompilerがVueを喋れても良いじゃないか
andoshin11
0
780
ain't giving up type-safe Express
andoshin11
2
480
Type Safe "Everything"
andoshin11
0
280
Hack your Nuxt router!
andoshin11
0
1.4k
GatewayパターンとSchema駆動開発
andoshin11
7
1.5k
Other Decks in Technology
See All in Technology
「データとの対話」の現在地と未来
kobakou
0
970
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.4k
NW構成図の自動描画は何が難しいのか?/netdevnight3
corestate55
2
490
LINEヤフーにおけるAI駆動開発組織のプロデュース施策
lycorptech_jp
PRO
0
190
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
4
22k
AIで 浮いた時間で 何をする? 2026春 #devsumi
konifar
16
3.5k
Eight Engineering Unit 紹介資料
sansan33
PRO
1
6.8k
LINEアプリ開発のための Claude Code活用基盤の構築
lycorptech_jp
PRO
1
1.1k
バニラVisaギフトカードを棄てるのは結構大変
meow_noisy
0
160
LINE Messengerの次世代ストレージ選定
lycorptech_jp
PRO
3
1.6k
失敗できる意思決定とソフトウェアとの正しい歩き方_-_変化と向き合う選択肢/ Designing for Reversible Decisions
soudai
PRO
8
1.4k
AIに視覚を与えモバイルアプリケーション開発をより円滑に行う
lycorptech_jp
PRO
1
570
Featured
See All Featured
Navigating Team Friction
lara
192
16k
Color Theory Basics | Prateek | Gurzu
gurzu
0
220
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
63
The Language of Interfaces
destraynor
162
26k
How Software Deployment tools have changed in the past 20 years
geshan
0
32k
Utilizing Notion as your number one productivity tool
mfonobong
3
240
Measuring & Analyzing Core Web Vitals
bluesmoon
9
760
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Code Reviewing Like a Champion
maltzj
527
40k
Mobile First: as difficult as doing things right
swwweet
225
10k
The Cult of Friendly URLs
andyhume
79
6.8k
A designer walks into a library…
pauljervisheath
210
24k
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!