From 11fb2cd0e787ad00f9993d886dbc4ae964fe129a Mon Sep 17 00:00:00 2001 From: seeflood Date: Tue, 27 Sep 2022 18:00:19 +0800 Subject: [PATCH] feat(generator): generate new methods for existing APIs (#784) Co-authored-by: Xunzhuo --- .../advanced_queue/advanced_queue.proto | 30 +++++++++++ docs/_sidebar.md | 4 +- docs/en/api_reference/README.md | 2 - .../api_reference/how_to_generate_api_doc.md | 10 ++-- docs/en/start/api_plugin/generate.md | 50 +++++++++++++++++++ docs/zh/_sidebar.md | 4 +- docs/zh/api_reference/README.md | 2 - .../api_reference/how_to_generate_api_doc.md | 10 ++-- docs/zh/start/api_plugin/generate.md | 50 +++++++++++++++++++ docs/zh/start/api_plugin/helloworld.md | 4 +- etc/script/generate-code.sh | 2 +- etc/script/generate-doc.sh | 2 +- pkg/runtime/extension_api_generated.go | 30 +++++++++++ pkg/runtime/options_generated.go | 11 ---- spec/proto/extension/v1/s3/oss.proto | 4 +- spec/proto/runtime/v1/appcallback.proto | 2 +- spec/proto/runtime/v1/runtime.proto | 2 +- 17 files changed, 187 insertions(+), 32 deletions(-) create mode 100644 cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto create mode 100644 docs/en/start/api_plugin/generate.md create mode 100644 docs/zh/start/api_plugin/generate.md create mode 100644 pkg/runtime/extension_api_generated.go diff --git a/cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto b/cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto new file mode 100644 index 0000000000..00fd0cdf03 --- /dev/null +++ b/cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +option go_package = "github.com/mosn/layotto/cmd/layotto_multiple_api/advanced_queue;advanced_queue"; + +package cmd.layotto_multiple_api.advanced_queue; + +/* @exclude skip sdk_generator */ +/* @exclude extends pub_subs */ +// AdvancedQueue is advanced pubsub API +service AdvancedQueue { + + // Publish a transactional message + rpc PublishTransactionalMessage(TransactionalMessageRequest) returns (TransactionalMessageResponse); + +} + +// TransactionalMessageRequest +message TransactionalMessageRequest { + // Required + string store_name = 1; + // Required + string content = 2; +} + +// TransactionalMessageResponse +message TransactionalMessageResponse { + + // message_id is identifier of a message + string message_id = 1; +} diff --git a/docs/_sidebar.md b/docs/_sidebar.md index e4846536d9..881e6e9549 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -14,7 +14,9 @@ - [Hello World](en/start/rpc/helloworld.md) - [Dubbo JSON RPC](en/start/rpc/dubbo_json_rpc.md) - [Use OSS API](en/start/oss/start.md) - - [API plugin: register your own API](en/start/api_plugin/helloworld.md) + - API plugin + - [Register your own API](en/start/api_plugin/helloworld.md) + - [Generate API plugin automatically](en/start/api_plugin/generate.md) - [(Under construction) Use phone API](en/start/phone/start) - [(Under construction) Use email API](en/start/email/start) diff --git a/docs/en/api_reference/README.md b/docs/en/api_reference/README.md index 0731db1cef..dfc9097e5c 100644 --- a/docs/en/api_reference/README.md +++ b/docs/en/api_reference/README.md @@ -11,8 +11,6 @@ These protos define Layotto's runtime API, including: In addition to this, Layotto also provides some extension APIs, including: - - email: [spec/proto/extension/v1/email](https://mosn.io/layotto/api/v1/email.html) phone: [spec/proto/extension/v1/phone](https://mosn.io/layotto/api/v1/phone.html) diff --git a/docs/en/api_reference/how_to_generate_api_doc.md b/docs/en/api_reference/how_to_generate_api_doc.md index 5648ed3d30..86e74b3e1a 100644 --- a/docs/en/api_reference/how_to_generate_api_doc.md +++ b/docs/en/api_reference/how_to_generate_api_doc.md @@ -39,14 +39,14 @@ service EmailService2 { // different message types...... ``` -- If you don't want to generate the quickstart docs for the proto, add a comment `/* @exclude quickstart generator */` . -- If you don't want to generate the sdk & sidecar code for the proto, add a comment `/* @exclude code generator */` . +- If you don't want to generate the quickstart docs for the proto, add a comment `/* @exclude skip quickstart_generator */` . +- If you don't want to generate the sdk & sidecar code for the proto, add a comment `/* @exclude skip code_generator */` . You can take the `spec/proto/extension/v1/s3/oss.proto` as an example: ```protobuf -/* @exclude quickstart generator */ -/* @exclude code generator */ +/* @exclude skip quickstart_generator */ +/* @exclude skip code_generator */ // ObjectStorageService is an abstraction for blob storage or so called "object storage", such as alibaba cloud OSS, such as AWS S3. // You invoke ObjectStorageService API to do some CRUD operations on your binary file, e.g. query my file, delete my file, etc. service ObjectStorageService{ @@ -54,6 +54,8 @@ service ObjectStorageService{ } ``` +These special comments are called "Master's commands". There are many other commands, and you can check [the doc](https://github.com/seeflood/protoc-gen-p6#masters-commands) for more details. + ## step 2. Check the environment To run the generator, you need: - Go version >=1.16 diff --git a/docs/en/start/api_plugin/generate.md b/docs/en/start/api_plugin/generate.md new file mode 100644 index 0000000000..89f27a0b07 --- /dev/null +++ b/docs/en/start/api_plugin/generate.md @@ -0,0 +1,50 @@ +# Generate API plugin automatically + +Writing the API plugin yourself is boring. You can use code generator to generate all the code. + +Let's say you want to add a `PublishTransactionalMessage` method to existing pubsub API. You write a new proto file `cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto` : + +```protobuf +// ...... +/* @exclude extends pub_subs */ +// AdvancedQueue is advanced pubsub API +service AdvancedQueue { + + rpc PublishTransactionalMessage(TransactionalMessageRequest) returns (TransactionalMessageResponse); + +} + +message TransactionalMessageRequest { + string store_name = 1; + + string content = 2; +} + +message TransactionalMessageResponse { + string message_id = 1; +} + +``` + +and run the generator: + +```protobuf +protoc -I . \ + --go_out . --go_opt=paths=source_relative \ + --go-grpc_out=. \ + --go-grpc_opt=require_unimplemented_servers=false,paths=source_relative \ + --p6_out ./cmd/layotto_multiple_api/advanced_queue --p6_opt=paths=source_relative \ + cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto +``` + +then you get the code: + + + +Fix the path error and then you can register this API plugin in you `main`. + +## Reference + +[How to generate code and documentation from the .proto files](en/api_reference/how_to_generate_api_doc) + +[protoc-gen-p6](https://github.com/seeflood/protoc-gen-p6) \ No newline at end of file diff --git a/docs/zh/_sidebar.md b/docs/zh/_sidebar.md index dd66665be1..b882910863 100644 --- a/docs/zh/_sidebar.md +++ b/docs/zh/_sidebar.md @@ -20,7 +20,9 @@ - [(建设中)使用 phone API](zh/start/phone/start) - [(建设中)使用 email API](zh/start/email/start) - [使用 lifecycle API](zh/start/lifecycle/start) - - [API插件:注册您自己的API](zh/start/api_plugin/helloworld.md) + - API插件 + - [注册您自己的API](zh/start/api_plugin/helloworld.md) + - [自动生成 API 插件](zh/start/api_plugin/generate.md) - 作为 Istio 的数据面 - [集成 Istio 1.10.6 演示](zh/start/istio/) - [集成 Istio 1.5.x 演示](zh/start/istio/start.md) diff --git a/docs/zh/api_reference/README.md b/docs/zh/api_reference/README.md index f0c3815cf3..e0a717e23d 100644 --- a/docs/zh/api_reference/README.md +++ b/docs/zh/api_reference/README.md @@ -11,8 +11,6 @@ Layotto 有多个 gRPC proto 文件, 对应的接口文档在: 除此之外,Layotto 还提供了一些扩展 API,包括: - - email: [spec/proto/extension/v1/email](https://mosn.io/layotto/api/v1/email.html) phone: [spec/proto/extension/v1/phone](https://mosn.io/layotto/api/v1/phone.html) diff --git a/docs/zh/api_reference/how_to_generate_api_doc.md b/docs/zh/api_reference/how_to_generate_api_doc.md index df89a96dd5..5f2236ec15 100644 --- a/docs/zh/api_reference/how_to_generate_api_doc.md +++ b/docs/zh/api_reference/how_to_generate_api_doc.md @@ -39,14 +39,14 @@ service EmailService2 { // different message types...... ``` -- If you don't want to generate the quickstart docs for the proto, add a comment `/* @exclude quickstart generator */` . -- If you don't want to generate the sdk & sidecar code for the proto, add a comment `/* @exclude code generator */` . +- If you don't want to generate the quickstart docs for the proto, add a comment `/* @exclude skip quickstart_generator */` . +- If you don't want to generate the sdk & sidecar code for the proto, add a comment `/* @exclude skip code_generator */` . You can take the `spec/proto/extension/v1/s3/oss.proto` as an example: ```protobuf -/* @exclude quickstart generator */ -/* @exclude code generator */ +/* @exclude skip quickstart_generator */ +/* @exclude skip code_generator */ // ObjectStorageService is an abstraction for blob storage or so called "object storage", such as alibaba cloud OSS, such as AWS S3. // You invoke ObjectStorageService API to do some CRUD operations on your binary file, e.g. query my file, delete my file, etc. service ObjectStorageService{ @@ -54,6 +54,8 @@ service ObjectStorageService{ } ``` +These special comments are called "Master's commands". There are many other commands, and you can check [the doc](https://github.com/seeflood/protoc-gen-p6#masters-commands) for more details. + ## step 2. Check the environment To run the generator, you need: - Go version >=1.16 diff --git a/docs/zh/start/api_plugin/generate.md b/docs/zh/start/api_plugin/generate.md new file mode 100644 index 0000000000..b6c70cea86 --- /dev/null +++ b/docs/zh/start/api_plugin/generate.md @@ -0,0 +1,50 @@ +# 自动生成 API 插件 + +Writing the API plugin yourself is boring. You can use code generator to generate all the code. + +Let's say you want to add a `PublishTransactionalMessage` method to existing pubsub API. You write a new proto file `cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto` : + +```protobuf +// ...... +/* @exclude extends pub_subs */ +// AdvancedQueue is advanced pubsub API +service AdvancedQueue { + + rpc PublishTransactionalMessage(TransactionalMessageRequest) returns (TransactionalMessageResponse); + +} + +message TransactionalMessageRequest { + string store_name = 1; + + string content = 2; +} + +message TransactionalMessageResponse { + string message_id = 1; +} + +``` + +and run the generator: + +```protobuf +protoc -I . \ + --go_out . --go_opt=paths=source_relative \ + --go-grpc_out=. \ + --go-grpc_opt=require_unimplemented_servers=false,paths=source_relative \ + --p6_out ./cmd/layotto_multiple_api/advanced_queue --p6_opt=paths=source_relative \ + cmd/layotto_multiple_api/advanced_queue/advanced_queue.proto +``` + +then you get the code: + + + +Fix the path error and then you can register this API plugin in you `main`. + +## Reference + +[How to generate code and documentation from the .proto files](zh/api_reference/how_to_generate_api_doc) + +[protoc-gen-p6](https://github.com/seeflood/protoc-gen-p6) \ No newline at end of file diff --git a/docs/zh/start/api_plugin/helloworld.md b/docs/zh/start/api_plugin/helloworld.md index 2ca6eb9429..ee895044a2 100644 --- a/docs/zh/start/api_plugin/helloworld.md +++ b/docs/zh/start/api_plugin/helloworld.md @@ -59,4 +59,6 @@ Greeting: Hello world 您可以参考演示的代码来实现你自己的API。快来试试吧! -想要了解更多的详情,您可以参考[设计文档](zh/design/api_plugin/design.md) \ No newline at end of file +想要了解更多的详情,您可以参考[设计文档](zh/design/api_plugin/design.md) + +为了简化 API 插件的开发,Layotto 社区提供了一套代码生成器,可以基于 proto 文件生成 API 插件相关代码,见 [文档](zh/start/api_plugin/generate.md) \ No newline at end of file diff --git a/etc/script/generate-code.sh b/etc/script/generate-code.sh index 4fd8bd8871..ce21e4a027 100644 --- a/etc/script/generate-code.sh +++ b/etc/script/generate-code.sh @@ -20,7 +20,7 @@ needGenerate() { file=$1 # check no `@exclude` tag - if [ $(grep "@exclude code generator" $file | wc -l) -eq 0 ]; then + if [ $(grep "@exclude skip code_generator" $file | wc -l) -eq 0 ]; then # check if there's a gRPC service in it if [ $(grep "service " $file | wc -l) -gt 0 ]; then return $true diff --git a/etc/script/generate-doc.sh b/etc/script/generate-doc.sh index 2b09448c9e..eb2a1d1998 100644 --- a/etc/script/generate-doc.sh +++ b/etc/script/generate-doc.sh @@ -14,7 +14,7 @@ needGenerateQuickstart() { file=$1 # check no `@exclude` tag - if [ $(grep "@exclude quickstart generator" $file | wc -l) -eq 0 ]; then + if [ $(grep "@exclude skip quickstart_generator" $file | wc -l) -eq 0 ]; then # check if there's a gRPC service in it if [ $(grep "service " $file | wc -l) -gt 0 ]; then return $true diff --git a/pkg/runtime/extension_api_generated.go b/pkg/runtime/extension_api_generated.go new file mode 100644 index 0000000000..cdf00e278b --- /dev/null +++ b/pkg/runtime/extension_api_generated.go @@ -0,0 +1,30 @@ +// Code generated by github.com/seeflood/protoc-gen-p6 . + +// Copyright 2021 Layotto Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package runtime + +import ( + email "mosn.io/layotto/pkg/grpc/email" + s3 "mosn.io/layotto/pkg/grpc/extension/s3" + phone "mosn.io/layotto/pkg/grpc/phone" +) + +func WithExtensionGrpcAPI() Option { + return WithGrpcAPI( + s3.NewS3Server, + email.NewAPI, + phone.NewAPI, + ) +} diff --git a/pkg/runtime/options_generated.go b/pkg/runtime/options_generated.go index df973bd898..4070d4c1e1 100644 --- a/pkg/runtime/options_generated.go +++ b/pkg/runtime/options_generated.go @@ -18,9 +18,6 @@ package runtime import ( email "mosn.io/layotto/components/email" phone "mosn.io/layotto/components/phone" - email1 "mosn.io/layotto/pkg/grpc/email" - s3 "mosn.io/layotto/pkg/grpc/extension/s3" - phone1 "mosn.io/layotto/pkg/grpc/phone" ) type extensionComponentFactorys struct { @@ -44,11 +41,3 @@ func WithPhoneCallServiceFactory(phone ...*phone.Factory) Option { o.services.phone = append(o.services.phone, phone...) } } - -func WithExtensionGrpcAPI() Option { - return WithGrpcAPI( - s3.NewS3Server, - email1.NewAPI, - phone1.NewAPI, - ) -} diff --git a/spec/proto/extension/v1/s3/oss.proto b/spec/proto/extension/v1/s3/oss.proto index 0306b71df5..f2e3199f65 100644 --- a/spec/proto/extension/v1/s3/oss.proto +++ b/spec/proto/extension/v1/s3/oss.proto @@ -11,8 +11,8 @@ option go_package = "mosn.io/layotto/spec/proto/extension/v1/s3;s3"; option java_outer_classname = "ObjectStorageProto"; option java_package = "spec.proto.extension.v1.s3"; -/* @exclude quickstart generator */ -/* @exclude code generator */ +/* @exclude skip quickstart_generator */ +/* @exclude skip code_generator */ // ObjectStorageService is an abstraction for blob storage or so called "object storage", such as alibaba cloud OSS, such as AWS S3. // You invoke ObjectStorageService API to do some CRUD operations on your binary file, e.g. query my file, delete my file, etc. service ObjectStorageService{ diff --git a/spec/proto/runtime/v1/appcallback.proto b/spec/proto/runtime/v1/appcallback.proto index f190f19244..e22a5c1cbe 100644 --- a/spec/proto/runtime/v1/appcallback.proto +++ b/spec/proto/runtime/v1/appcallback.proto @@ -9,7 +9,7 @@ option go_package = "mosn.io/layotto/spec/proto/runtime/v1;runtime"; option java_outer_classname = "AppCallbackProto"; option java_package = "spec.proto.runtime.v1"; -/* @exclude quickstart generator */ +/* @exclude skip quickstart_generator */ // AppCallback V1 allows user application to interact with runtime. // User application needs to implement AppCallback service if it needs to // receive message from runtime. diff --git a/spec/proto/runtime/v1/runtime.proto b/spec/proto/runtime/v1/runtime.proto index 330afb4376..7bbbb63f2c 100644 --- a/spec/proto/runtime/v1/runtime.proto +++ b/spec/proto/runtime/v1/runtime.proto @@ -9,7 +9,7 @@ option go_package = "mosn.io/layotto/spec/proto/runtime/v1;runtime"; option java_outer_classname = "RuntimeProto"; option java_package = "spec.proto.runtime.v1"; -/* @exclude quickstart generator */ +/* @exclude skip quickstart_generator */ // Runtime encapsulates variours Runtime APIs(such as Configuration API, Pub/Sub API, etc) service Runtime { //SayHello used for test