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
130
カーナベルにおける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
730
カーナベル株式会社2024年2月 エンジニアイベント資料
andoshin11
0
390
Private Cloudを支える最高のユーザーガイド運用技術
andoshin11
0
300
TS CompilerがVueを喋れても良いじゃないか
andoshin11
0
750
ain't giving up type-safe Express
andoshin11
2
450
Type Safe "Everything"
andoshin11
0
260
Hack your Nuxt router!
andoshin11
0
1.3k
GatewayパターンとSchema駆動開発
andoshin11
7
1.5k
Catch up Nuxt.js 2019.02
andoshin11
0
2.1k
Other Decks in Technology
See All in Technology
非同期処理実行基盤 Delayed脱出 → Solid Queue完全移行への旅路。
srockstyle
3
1.5k
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
9k
stupid jj tricks
indirect
0
7.6k
全てGoで作るP2P対戦ゲーム入門
ponyo877
3
1.2k
組織観点からIAM Identity CenterとIAMの設計を考える
nrinetcom
PRO
1
130
北海道の人に知ってもらいたいGISスポット / gis-spot-in-hokkaido-2025
sakaik
0
190
空間を設計する力を考える / 20251004 Naoki Takahashi
shift_evolve
PRO
3
120
Oracle Cloud Infrastructure:2025年9月度サービス・アップデート
oracle4engineer
PRO
0
320
Azure SynapseからAzure Databricksへ 移行してわかった新時代のコスト問題!?
databricksjapan
0
110
いま注目しているデータエンジニアリングの論点
ikkimiyazaki
0
550
OCI Network Firewall 概要
oracle4engineer
PRO
1
7.7k
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
3
20k
Featured
See All Featured
Optimising Largest Contentful Paint
csswizardry
37
3.4k
How GitHub (no longer) Works
holman
315
140k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.1k
Statistics for Hackers
jakevdp
799
220k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.2k
Scaling GitHub
holman
463
140k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
114
20k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Making Projects Easy
brettharned
118
6.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!