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
100
カーナベルにおける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
590
カーナベル株式会社2024年2月 エンジニアイベント資料
andoshin11
0
330
Private Cloudを支える最高のユーザーガイド運用技術
andoshin11
0
290
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アプリケーションの配布とパッケージング / Distribution and packaging of Java applications
hogelog
1
250
Cursor Meetup Tokyo
iamshunta
2
700
libsyncrpcってなに?
uhyo
0
160
名刺メーカーDevグループ 紹介資料
sansan33
PRO
0
740
新卒から4年間、20年もののWebサービスと向き合って学んだソフトウェア考古学 - PHPカンファレンス新潟2025 / new graduate 4year software archeology
oguri
2
360
Bill One 開発エンジニア 紹介資料
sansan33
PRO
4
12k
Machine Intelligence for Vision, Language, and Actions
keio_smilab
PRO
0
500
いまさら聞けない Git 超入門 〜Gitって結局なに?から始める第一歩〜
devops_vtj
0
170
人とAIとの共創を夢見た2か月 #共創AIミートアップ / Co-Creation with Keito-chan
kondoyuko
1
720
Introduction to Bill One Development Engineer
sansan33
PRO
0
240
実践Kafka Streams 〜イベント駆動型アーキテクチャを添えて〜
joker1007
0
470
Introduction to Sansan, inc / Sansan Global Development Center, Inc.
sansan33
PRO
0
2.6k
Featured
See All Featured
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
45
9.6k
Optimizing for Happiness
mojombo
378
70k
Six Lessons from altMBA
skipperchong
28
3.8k
A Tale of Four Properties
chriscoyier
159
23k
Done Done
chrislema
184
16k
Rebuilding a faster, lazier Slack
samanthasiow
81
9k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
850
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
137
34k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Building a Modern Day E-commerce SEO Strategy
aleyda
40
7.3k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
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!