emahiro/b.log

日々の勉強の記録とか育児の記録とか。

proto を syntax から edition にマイグレする

Overview

proto の edition 移行をやったのでその備忘録です。
なお、proto もバージョンを year で表記するようになっていたことは初めて知りました。ex. es2015

ちなみにこれは syntax="proto3" -> edition="2023" に上げた記録です。最新は 2024 なのでどこかで対応しようと思っています。

前提

このエントリで前提となるアプリケーションの構成は以下です。

  • アプリケーションの構成要素はシンプルな server/client 構成。
  • client-server 間の通信は REST。grpc-gateway を利用して通信する。
  • server は Go で proto から Go のコードを生成する。
  • client は proto から直接コードを生成せず、一度 OpenAPI Schema を生成してその定義ファイルから Client のコードを生成する。

移行方法

-syntax="proto";
+edition="2023"` 

これで終わりですが、これにするにあたって自分が利用していた定義がいくつか利用できなくなっていました。

optional -> features.field_presence = IMPLICIT

使えなくなっていました。この代わりに features.field_presence = EXPLICIT を使う必要があります。
nullable なフィールドの取り扱いは 2023以降ではデフォルト off で nullable なフィールドに対してはそれを明示する必要があるようです。

なので optional を使っていた箇所は以下のようになります。

+option features.field_presence = IMPLICIT; // proto3 のデフォルト動作を維持

...略

-optional string name = N
+string name = N {
+    features.field_presence = EXPLICIT,
+}

reserved

reserved は string にしなくてもよくなりました。

-reserved "name";
+reserved name;

カスタムプラグインの edition のサポート

過去に Go で protoc のカスタムプラグインを書いたことがあるのですが、カスタムプラグインを使っている場合は edition のサポートを追加する必要があります。

ema-hiro.hatenablog.com

具体的には以下

protogen.Options{}.Run(func(plugin *protogen.Plugin) error {
-  plugin.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
+   plugin.SupportedFeatures = uint64(
+       pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL |
+           pluginpb.CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS,
+   )
+   plugin.SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO3
+   plugin.SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023
    ...
}

ハマったところ

非サポート plugin があるとマイグレできない

上記のカスタムコマンドなど proto の設定側のアップデートが必要なところがありましたが、やはり一番ハマったのは edition を plugin 側がサポートしていないと protoc でコンパイルできないということでした。

具体的に非サポートだった plugin 配下

  • grpc-gateway=> github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway のバージョンを最新版( v2.27.5 ) にすることで edition のサポートがされました。
  • open-api-generator => 元々使っていた github.com/google/gnostic/cmd/protoc-gen-openapi が edition 非サポートで困りました。openAPI Generator はあまり選択肢がないので edition 対応してるものがない場合、この作業を諦めようかなと思いましたが、sansan さんの以下のブログに救われました。openapi generator を使うなら今は connect が作ってる https://github.com/sudorandom/protoc-gen-connect-openapi 一択のようですね。ちゃんと生成された OpenAPI Schema は v3.1.0 に対応してました。 gnostic の openAPI Generator は v3 系とはいえ、 v3.0.3 だったので。

buildersbox.corp-sansan.com

plugin を更新して buf でビルドし直すことで無事 edition をサポートした proto をコンパイルすることができました。

まとめ

できたのでヨシ!