diff --git a/.github/RELEASE.md b/.github/RELEASE.md
index 0e3ac1f9..8b108361 100644
--- a/.github/RELEASE.md
+++ b/.github/RELEASE.md
@@ -1,5 +1,5 @@
## Change log
-- Sponge command ui service support docker deployment.
-- Adjustment option code.
-
+- Fix bug with naocs as service discovery.
+- Add support for distributed transaction manager [DTM](https://github.com/dtm-labs/dtm).
+- Add a list api interface for GET methods.
diff --git a/Makefile b/Makefile
index 5452d610..3209a04b 100644
--- a/Makefile
+++ b/Makefile
@@ -104,7 +104,7 @@ build-sponge:
# build a sponge docker image, e.g. make image-build-sponge TAG=v1.5.8
image-build-sponge:
@echo "build a sponge docker image'"
- @cd cmd/sponge/scripts && bash image-build.sh $(TAG)
+ @cd cmd/sponge/scripts && bash build-sponge-image.sh $(TAG)
# delete the templates code end
diff --git a/README.md b/README.md
index 57ae6f3e..337216a7 100644
--- a/README.md
+++ b/README.md
@@ -18,9 +18,9 @@
-If you are developing a web or microservice with a simple CRUD API interface, you don't need to write a single line of golang code to compile and deploy to servers, dockers, k8s, and the complete service code is generated by sponge.
+If you are developing a RESTful web or microservice with a simple CRUD API interface, you don't need to write a single line of golang code to compile and deploy to servers, dockers, k8s, and the complete service code is generated by sponge.
-If you develop a generic web or microservice, you need to manually write code in addition to defining the data table, defining the api interface in the proto file, and filling in the specific business logic code in the generated template file. Other golang codes are generated by sponge.
+If you develop a generic RESTful web or microservice, you need to manually write code in addition to defining the data table, defining the api interface in the proto file, and filling in the specific business logic code in the generated template file. Other golang codes are generated by sponge.
@@ -108,6 +108,10 @@ No specific business logic code is included.
- [7_community-single](https://github.com/zhufuyi/sponge_examples/tree/main/7_community-single)
- [8_community-cluster](https://github.com/zhufuyi/sponge_examples/tree/main/8_community-cluster)
+#### Distributed transaction examples
+
+- [9_order-system](https://github.com/zhufuyi/sponge_examples/tree/main/9_order-grpc-distributed-transaction)
+
**If it's help to you, give it a star ⭐.**
diff --git a/api/serverNameExample/v1/userExample.pb.go b/api/serverNameExample/v1/userExample.pb.go
index b75ab249..6043d0b3 100644
--- a/api/serverNameExample/v1/userExample.pb.go
+++ b/api/serverNameExample/v1/userExample.pb.go
@@ -10,8 +10,11 @@
package v1
import (
+
+
+
types "github.com/zhufuyi/sponge/api/types"
-
+
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@@ -952,6 +955,116 @@ func (x *ListUserExampleByIDsReply) GetUserExamples() []*UserExample {
return nil
}
+type ListUserExampleByLastIDRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ LastID uint64 `protobuf:"varint,1,opt,name=lastID,proto3" json:"lastID" form:"lastID"`
+ Limit uint32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit" form:"limit"`
+ Sort string `protobuf:"bytes,3,opt,name=sort,proto3" json:"sort" form:"sort"`
+}
+
+func (x *ListUserExampleByLastIDRequest) Reset() {
+ *x = ListUserExampleByLastIDRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[15]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListUserExampleByLastIDRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListUserExampleByLastIDRequest) ProtoMessage() {}
+
+func (x *ListUserExampleByLastIDRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[15]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListUserExampleByLastIDRequest.ProtoReflect.Descriptor instead.
+func (*ListUserExampleByLastIDRequest) Descriptor() ([]byte, []int) {
+ return file_api_serverNameExample_v1_userExample_proto_rawDescGZIP(), []int{15}
+}
+
+func (x *ListUserExampleByLastIDRequest) GetLastID() uint64 {
+ if x != nil {
+ return x.LastID
+ }
+ return 0
+}
+
+func (x *ListUserExampleByLastIDRequest) GetLimit() uint32 {
+ if x != nil {
+ return x.Limit
+ }
+ return 0
+}
+
+func (x *ListUserExampleByLastIDRequest) GetSort() string {
+ if x != nil {
+ return x.Sort
+ }
+ return ""
+}
+
+type ListUserExampleByLastIDReply struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ UserExamples []*UserExample `protobuf:"bytes,1,rep,name=userExamples,proto3" json:"userExamples"`
+}
+
+func (x *ListUserExampleByLastIDReply) Reset() {
+ *x = ListUserExampleByLastIDReply{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[16]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListUserExampleByLastIDReply) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListUserExampleByLastIDReply) ProtoMessage() {}
+
+func (x *ListUserExampleByLastIDReply) ProtoReflect() protoreflect.Message {
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[16]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListUserExampleByLastIDReply.ProtoReflect.Descriptor instead.
+func (*ListUserExampleByLastIDReply) Descriptor() ([]byte, []int) {
+ return file_api_serverNameExample_v1_userExample_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *ListUserExampleByLastIDReply) GetUserExamples() []*UserExample {
+ if x != nil {
+ return x.UserExamples
+ }
+ return nil
+}
+
type ListUserExampleRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -963,7 +1076,7 @@ type ListUserExampleRequest struct {
func (x *ListUserExampleRequest) Reset() {
*x = ListUserExampleRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[15]
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -976,7 +1089,7 @@ func (x *ListUserExampleRequest) String() string {
func (*ListUserExampleRequest) ProtoMessage() {}
func (x *ListUserExampleRequest) ProtoReflect() protoreflect.Message {
- mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[15]
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -989,7 +1102,7 @@ func (x *ListUserExampleRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListUserExampleRequest.ProtoReflect.Descriptor instead.
func (*ListUserExampleRequest) Descriptor() ([]byte, []int) {
- return file_api_serverNameExample_v1_userExample_proto_rawDescGZIP(), []int{15}
+ return file_api_serverNameExample_v1_userExample_proto_rawDescGZIP(), []int{17}
}
func (x *ListUserExampleRequest) GetParams() *types.Params {
@@ -1011,7 +1124,7 @@ type ListUserExampleReply struct {
func (x *ListUserExampleReply) Reset() {
*x = ListUserExampleReply{}
if protoimpl.UnsafeEnabled {
- mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[16]
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1024,7 +1137,7 @@ func (x *ListUserExampleReply) String() string {
func (*ListUserExampleReply) ProtoMessage() {}
func (x *ListUserExampleReply) ProtoReflect() protoreflect.Message {
- mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[16]
+ mi := &file_api_serverNameExample_v1_userExample_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1037,7 +1150,7 @@ func (x *ListUserExampleReply) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListUserExampleReply.ProtoReflect.Descriptor instead.
func (*ListUserExampleReply) Descriptor() ([]byte, []int) {
- return file_api_serverNameExample_v1_userExample_proto_rawDescGZIP(), []int{16}
+ return file_api_serverNameExample_v1_userExample_proto_rawDescGZIP(), []int{18}
}
func (x *ListUserExampleReply) GetTotal() int64 {
@@ -1177,150 +1290,181 @@ var file_api_serverNameExample_v1_userExample_proto_rawDesc = []byte{
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x0c, 0x75,
- 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x16, 0x4c,
- 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x50, 0x61,
- 0x72, 0x61, 0x6d, 0x73, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06,
- 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x77, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73,
- 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14,
- 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x49, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69,
+ 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x1e,
+ 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42,
+ 0x79, 0x4c, 0x61, 0x73, 0x74, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a,
+ 0x0a, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x12,
+ 0x9a, 0x84, 0x9e, 0x03, 0x0d, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x22, 0x6c, 0x61, 0x73, 0x74, 0x49,
+ 0x44, 0x22, 0x52, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x44, 0x12, 0x27, 0x0a, 0x05, 0x6c, 0x69,
+ 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x11, 0x9a, 0x84, 0x9e, 0x03, 0x0c,
+ 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x22, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x52, 0x05, 0x6c, 0x69,
+ 0x6d, 0x69, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x42, 0x10, 0x9a, 0x84, 0x9e, 0x03, 0x0b, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x22, 0x73, 0x6f,
+ 0x72, 0x74, 0x22, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x22, 0x69, 0x0a, 0x1c, 0x4c, 0x69, 0x73,
+ 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x4c, 0x61,
+ 0x73, 0x74, 0x49, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x49, 0x0a, 0x0c, 0x75, 0x73, 0x65,
+ 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x25, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
+ 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x45,
+ 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72,
+ 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f,
+ 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d,
+ 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x08, 0xfa,
+ 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22,
+ 0x77, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x49, 0x0a,
+ 0x0c, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55,
+ 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72,
+ 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2a, 0x2f, 0x0a, 0x0a, 0x47, 0x65, 0x6e, 0x64,
+ 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
+ 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a,
+ 0x06, 0x46, 0x45, 0x4d, 0x41, 0x4c, 0x45, 0x10, 0x02, 0x32, 0xea, 0x0f, 0x0a, 0x0b, 0x75, 0x73,
+ 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0xcf, 0x01, 0x0a, 0x06, 0x43, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
+ 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+ 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x5f, 0x82, 0xd3, 0xe4, 0x93,
+ 0x02, 0x18, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72,
+ 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x3e, 0x12, 0x12, 0x63,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x1a, 0x28, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20,
+ 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0xcd, 0x01, 0x0a, 0x0a,
+ 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x79, 0x49, 0x44, 0x12, 0x36, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70,
- 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
- 0x65, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2a,
- 0x2f, 0x0a, 0x0a, 0x47, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a,
- 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41,
- 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x45, 0x4d, 0x41, 0x4c, 0x45, 0x10, 0x02,
- 0x32, 0x80, 0x0e, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
- 0x12, 0xcf, 0x01, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x61, 0x70,
- 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65,
- 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x30, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
- 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
- 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x70, 0x6c,
- 0x79, 0x22, 0x5f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f,
- 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x01,
- 0x2a, 0x92, 0x41, 0x3e, 0x12, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65,
- 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x1a, 0x28, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74,
- 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20,
- 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70,
- 0x6c, 0x65, 0x12, 0xcd, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x79, 0x49,
- 0x44, 0x12, 0x36, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61,
- 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c,
- 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79,
- 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x2e,
- 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
- 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45,
- 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22,
- 0x51, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
- 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x7b, 0x69, 0x64,
- 0x7d, 0x92, 0x41, 0x2e, 0x12, 0x12, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65,
- 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x1a, 0x18, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65,
- 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20,
- 0x69, 0x64, 0x12, 0xe1, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x79, 0x49,
- 0x44, 0x73, 0x12, 0x37, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e,
+ 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72,
+ 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e,
0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42,
- 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x61, 0x70,
+ 0x79, 0x49, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x51, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a,
+ 0x2a, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x2e, 0x12, 0x12, 0x64,
+ 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x1a, 0x18, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x69, 0x64, 0x12, 0xe1, 0x01, 0x0a, 0x0b,
+ 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x79, 0x49, 0x44, 0x73, 0x12, 0x37, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65,
- 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x70,
- 0x6c, 0x79, 0x22, 0x62, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x61, 0x70, 0x69,
- 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f,
- 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x2f, 0x69, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x36,
- 0x12, 0x13, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61,
- 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x1a, 0x1f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x75, 0x73,
- 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x79, 0x20, 0x62, 0x61,
- 0x74, 0x63, 0x68, 0x20, 0x69, 0x64, 0x12, 0xd0, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74,
- 0x65, 0x42, 0x79, 0x49, 0x44, 0x12, 0x36, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31,
- 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70,
- 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e,
- 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78,
- 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55,
- 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65,
- 0x70, 0x6c, 0x79, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x1a, 0x18, 0x2f, 0x61, 0x70,
- 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
- 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x2e, 0x12, 0x12, 0x75, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x1a,
- 0x18, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x69, 0x64, 0x12, 0xcc, 0x01, 0x0a, 0x07, 0x47, 0x65,
- 0x74, 0x42, 0x79, 0x49, 0x44, 0x12, 0x33, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31,
- 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42,
- 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x61, 0x70, 0x69,
- 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70,
- 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61,
- 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x59, 0x82,
- 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75,
- 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92,
- 0x41, 0x36, 0x12, 0x16, 0x67, 0x65, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x1a, 0x1c, 0x67, 0x65, 0x74, 0x20,
- 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x74, 0x61,
- 0x69, 0x6c, 0x20, 0x62, 0x79, 0x20, 0x69, 0x64, 0x12, 0xef, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74,
- 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x61, 0x70,
- 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78,
- 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
- 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
- 0x65, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c,
- 0x79, 0x22, 0x67, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x61, 0x70, 0x69, 0x2f,
- 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x63,
- 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x3c, 0x12, 0x1c,
- 0x67, 0x65, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20,
- 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1c, 0x67, 0x65,
- 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x79,
- 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xea, 0x01, 0x0a, 0x09, 0x4c,
- 0x69, 0x73, 0x74, 0x42, 0x79, 0x49, 0x44, 0x73, 0x12, 0x35, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
+ 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
+ 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x42, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x62, 0x82, 0xd3, 0xe4,
+ 0x93, 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65,
+ 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x2f,
+ 0x69, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x36, 0x12, 0x13, 0x64, 0x65, 0x6c, 0x65, 0x74,
+ 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x1a, 0x1f,
+ 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x73, 0x20, 0x62, 0x79, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x69, 0x64, 0x12,
+ 0xd0, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x79, 0x49, 0x44, 0x12, 0x36,
+ 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45,
+ 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+ 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76,
+ 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x54, 0x82, 0xd3,
+ 0xe4, 0x93, 0x02, 0x1d, 0x1a, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73,
+ 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x01,
+ 0x2a, 0x92, 0x41, 0x2e, 0x12, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x75, 0x73, 0x65,
+ 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x1a, 0x18, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
+ 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20,
+ 0x69, 0x64, 0x12, 0xcc, 0x01, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x42, 0x79, 0x49, 0x44, 0x12, 0x33,
+ 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45,
+ 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65,
+ 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47,
+ 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49,
+ 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x59, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18,
+ 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x36, 0x12, 0x16, 0x67, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x74,
+ 0x61, 0x69, 0x6c, 0x1a, 0x1c, 0x67, 0x65, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61,
+ 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x20, 0x62, 0x79, 0x20, 0x69,
+ 0x64, 0x12, 0xef, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
+ 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79,
+ 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x1a, 0x38, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d,
+ 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55,
+ 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x64,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x67, 0x82, 0xd3, 0xe4, 0x93,
+ 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72,
+ 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x3c, 0x12, 0x1c, 0x67, 0x65, 0x74, 0x20, 0x75, 0x73, 0x65,
+ 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x64,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1c, 0x67, 0x65, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45,
+ 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0xea, 0x01, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x49, 0x44,
+ 0x73, 0x12, 0x35, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61,
+ 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
+ 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44,
+ 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x33, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
- 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55,
- 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x73, 0x52,
- 0x65, 0x70, 0x6c, 0x79, 0x22, 0x71, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x22, 0x1c, 0x2f, 0x61,
- 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
- 0x65, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x69, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x47,
- 0x12, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78,
- 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x79, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20,
- 0x69, 0x64, 0x1a, 0x23, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72,
- 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x79, 0x20, 0x62, 0x79, 0x20, 0x62,
- 0x61, 0x74, 0x63, 0x68, 0x20, 0x69, 0x64, 0x12, 0xe9, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74,
- 0x12, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d,
- 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
- 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e,
- 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
- 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x70,
- 0x6c, 0x79, 0x22, 0x7f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x18, 0x2f, 0x61, 0x70, 0x69,
- 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f,
- 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x59, 0x12, 0x28, 0x6c, 0x69, 0x73, 0x74,
- 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73,
- 0x20, 0x62, 0x79, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65,
- 0x74, 0x65, 0x72, 0x73, 0x1a, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73,
- 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x79, 0x20, 0x70, 0x61,
- 0x67, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x42, 0xe5, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
- 0x6f, 0x6d, 0x2f, 0x7a, 0x68, 0x75, 0x66, 0x75, 0x79, 0x69, 0x2f, 0x73, 0x70, 0x6f, 0x6e, 0x67,
- 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
- 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x92, 0x41, 0xaa,
- 0x01, 0x12, 0x21, 0x0a, 0x1a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45,
- 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x70, 0x69, 0x20, 0x64, 0x6f, 0x63, 0x73, 0x32,
- 0x03, 0x32, 0x2e, 0x30, 0x1a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a,
- 0x38, 0x30, 0x38, 0x30, 0x2a, 0x02, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c,
- 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x5a, 0x4d, 0x0a, 0x4b,
- 0x0a, 0x0a, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x41, 0x75, 0x74, 0x68, 0x12, 0x3d, 0x08, 0x02,
- 0x12, 0x28, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x61, 0x20, 0x22, 0x42, 0x65, 0x61, 0x72, 0x65,
- 0x72, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x2d, 0x6a, 0x77, 0x74, 0x2d, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
- 0x22, 0x20, 0x74, 0x6f, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0d, 0x41, 0x75, 0x74, 0x68,
- 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x33,
+ 0x70, 0x6c, 0x65, 0x42, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x71, 0x82,
+ 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75,
+ 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2f,
+ 0x69, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x47, 0x12, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20,
+ 0x62, 0x79, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x69, 0x64, 0x1a, 0x23, 0x6c, 0x69, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+ 0x73, 0x20, 0x62, 0x79, 0x20, 0x62, 0x79, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x69, 0x64,
+ 0x12, 0xe7, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x4c, 0x61, 0x73, 0x74, 0x49,
+ 0x44, 0x12, 0x38, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61,
+ 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
+ 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x4c, 0x61,
+ 0x73, 0x74, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x61, 0x70,
+ 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45,
+ 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x79, 0x4c, 0x61, 0x73, 0x74, 0x49, 0x44, 0x52, 0x65,
+ 0x70, 0x6c, 0x79, 0x22, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x61, 0x70,
+ 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+ 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x92, 0x41, 0x42, 0x12, 0x1f, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x62,
+ 0x79, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x69, 0x64, 0x1a, 0x1f, 0x6c, 0x69, 0x73, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20,
+ 0x62, 0x79, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x69, 0x64, 0x12, 0xe9, 0x01, 0x0a, 0x04, 0x4c,
+ 0x69, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
+ 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x76, 0x31,
+ 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+ 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x7f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x18, 0x2f,
+ 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x01, 0x2a, 0x92, 0x41, 0x59, 0x12, 0x28, 0x6c,
+ 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x73, 0x20, 0x62, 0x79, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x20, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x75, 0x73, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x79,
+ 0x20, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x64,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0xe5, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x7a, 0x68, 0x75, 0x66, 0x75, 0x79, 0x69, 0x2f, 0x73, 0x70,
+ 0x6f, 0x6e, 0x67, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e,
+ 0x61, 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31,
+ 0x92, 0x41, 0xaa, 0x01, 0x12, 0x21, 0x0a, 0x1a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61,
+ 0x6d, 0x65, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x70, 0x69, 0x20, 0x64, 0x6f,
+ 0x63, 0x73, 0x32, 0x03, 0x32, 0x2e, 0x30, 0x1a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
+ 0x73, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x30, 0x2a, 0x02, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70,
+ 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61,
+ 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x5a,
+ 0x4d, 0x0a, 0x4b, 0x0a, 0x0a, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x41, 0x75, 0x74, 0x68, 0x12,
+ 0x3d, 0x08, 0x02, 0x12, 0x28, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x61, 0x20, 0x22, 0x42, 0x65,
+ 0x61, 0x72, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x2d, 0x6a, 0x77, 0x74, 0x2d, 0x74, 0x6f,
+ 0x6b, 0x65, 0x6e, 0x22, 0x20, 0x74, 0x6f, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0d, 0x41,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x02, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -1336,7 +1480,7 @@ func file_api_serverNameExample_v1_userExample_proto_rawDescGZIP() []byte {
}
var file_api_serverNameExample_v1_userExample_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_api_serverNameExample_v1_userExample_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
+var file_api_serverNameExample_v1_userExample_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_api_serverNameExample_v1_userExample_proto_goTypes = []interface{}{
(GenderType)(0), // 0: api.serverNameExample.v1.GenderType
(*CreateUserExampleRequest)(nil), // 1: api.serverNameExample.v1.CreateUserExampleRequest
@@ -1354,42 +1498,47 @@ var file_api_serverNameExample_v1_userExample_proto_goTypes = []interface{}{
(*GetUserExampleByConditionReply)(nil), // 13: api.serverNameExample.v1.GetUserExampleByConditionReply
(*ListUserExampleByIDsRequest)(nil), // 14: api.serverNameExample.v1.ListUserExampleByIDsRequest
(*ListUserExampleByIDsReply)(nil), // 15: api.serverNameExample.v1.ListUserExampleByIDsReply
- (*ListUserExampleRequest)(nil), // 16: api.serverNameExample.v1.ListUserExampleRequest
- (*ListUserExampleReply)(nil), // 17: api.serverNameExample.v1.ListUserExampleReply
- (*types.Conditions)(nil), // 18: types.Conditions
- (*types.Params)(nil), // 19: types.Params
+ (*ListUserExampleByLastIDRequest)(nil), // 16: api.serverNameExample.v1.ListUserExampleByLastIDRequest
+ (*ListUserExampleByLastIDReply)(nil), // 17: api.serverNameExample.v1.ListUserExampleByLastIDReply
+ (*ListUserExampleRequest)(nil), // 18: api.serverNameExample.v1.ListUserExampleRequest
+ (*ListUserExampleReply)(nil), // 19: api.serverNameExample.v1.ListUserExampleReply
+ (*types.Conditions)(nil), // 20: types.Conditions
+ (*types.Params)(nil), // 21: types.Params
}
var file_api_serverNameExample_v1_userExample_proto_depIdxs = []int32{
0, // 0: api.serverNameExample.v1.CreateUserExampleRequest.gender:type_name -> api.serverNameExample.v1.GenderType
0, // 1: api.serverNameExample.v1.UpdateUserExampleByIDRequest.gender:type_name -> api.serverNameExample.v1.GenderType
0, // 2: api.serverNameExample.v1.UserExample.gender:type_name -> api.serverNameExample.v1.GenderType
9, // 3: api.serverNameExample.v1.GetUserExampleByIDReply.userExample:type_name -> api.serverNameExample.v1.UserExample
- 18, // 4: api.serverNameExample.v1.GetUserExampleByConditionRequest.conditions:type_name -> types.Conditions
+ 20, // 4: api.serverNameExample.v1.GetUserExampleByConditionRequest.conditions:type_name -> types.Conditions
9, // 5: api.serverNameExample.v1.GetUserExampleByConditionReply.userExample:type_name -> api.serverNameExample.v1.UserExample
9, // 6: api.serverNameExample.v1.ListUserExampleByIDsReply.userExamples:type_name -> api.serverNameExample.v1.UserExample
- 19, // 7: api.serverNameExample.v1.ListUserExampleRequest.params:type_name -> types.Params
- 9, // 8: api.serverNameExample.v1.ListUserExampleReply.userExamples:type_name -> api.serverNameExample.v1.UserExample
- 1, // 9: api.serverNameExample.v1.userExample.Create:input_type -> api.serverNameExample.v1.CreateUserExampleRequest
- 3, // 10: api.serverNameExample.v1.userExample.DeleteByID:input_type -> api.serverNameExample.v1.DeleteUserExampleByIDRequest
- 5, // 11: api.serverNameExample.v1.userExample.DeleteByIDs:input_type -> api.serverNameExample.v1.DeleteUserExampleByIDsRequest
- 7, // 12: api.serverNameExample.v1.userExample.UpdateByID:input_type -> api.serverNameExample.v1.UpdateUserExampleByIDRequest
- 10, // 13: api.serverNameExample.v1.userExample.GetByID:input_type -> api.serverNameExample.v1.GetUserExampleByIDRequest
- 12, // 14: api.serverNameExample.v1.userExample.GetByCondition:input_type -> api.serverNameExample.v1.GetUserExampleByConditionRequest
- 14, // 15: api.serverNameExample.v1.userExample.ListByIDs:input_type -> api.serverNameExample.v1.ListUserExampleByIDsRequest
- 16, // 16: api.serverNameExample.v1.userExample.List:input_type -> api.serverNameExample.v1.ListUserExampleRequest
- 2, // 17: api.serverNameExample.v1.userExample.Create:output_type -> api.serverNameExample.v1.CreateUserExampleReply
- 4, // 18: api.serverNameExample.v1.userExample.DeleteByID:output_type -> api.serverNameExample.v1.DeleteUserExampleByIDReply
- 6, // 19: api.serverNameExample.v1.userExample.DeleteByIDs:output_type -> api.serverNameExample.v1.DeleteUserExampleByIDsReply
- 8, // 20: api.serverNameExample.v1.userExample.UpdateByID:output_type -> api.serverNameExample.v1.UpdateUserExampleByIDReply
- 11, // 21: api.serverNameExample.v1.userExample.GetByID:output_type -> api.serverNameExample.v1.GetUserExampleByIDReply
- 13, // 22: api.serverNameExample.v1.userExample.GetByCondition:output_type -> api.serverNameExample.v1.GetUserExampleByConditionReply
- 15, // 23: api.serverNameExample.v1.userExample.ListByIDs:output_type -> api.serverNameExample.v1.ListUserExampleByIDsReply
- 17, // 24: api.serverNameExample.v1.userExample.List:output_type -> api.serverNameExample.v1.ListUserExampleReply
- 17, // [17:25] is the sub-list for method output_type
- 9, // [9:17] is the sub-list for method input_type
- 9, // [9:9] is the sub-list for extension type_name
- 9, // [9:9] is the sub-list for extension extendee
- 0, // [0:9] is the sub-list for field type_name
+ 9, // 7: api.serverNameExample.v1.ListUserExampleByLastIDReply.userExamples:type_name -> api.serverNameExample.v1.UserExample
+ 21, // 8: api.serverNameExample.v1.ListUserExampleRequest.params:type_name -> types.Params
+ 9, // 9: api.serverNameExample.v1.ListUserExampleReply.userExamples:type_name -> api.serverNameExample.v1.UserExample
+ 1, // 10: api.serverNameExample.v1.userExample.Create:input_type -> api.serverNameExample.v1.CreateUserExampleRequest
+ 3, // 11: api.serverNameExample.v1.userExample.DeleteByID:input_type -> api.serverNameExample.v1.DeleteUserExampleByIDRequest
+ 5, // 12: api.serverNameExample.v1.userExample.DeleteByIDs:input_type -> api.serverNameExample.v1.DeleteUserExampleByIDsRequest
+ 7, // 13: api.serverNameExample.v1.userExample.UpdateByID:input_type -> api.serverNameExample.v1.UpdateUserExampleByIDRequest
+ 10, // 14: api.serverNameExample.v1.userExample.GetByID:input_type -> api.serverNameExample.v1.GetUserExampleByIDRequest
+ 12, // 15: api.serverNameExample.v1.userExample.GetByCondition:input_type -> api.serverNameExample.v1.GetUserExampleByConditionRequest
+ 14, // 16: api.serverNameExample.v1.userExample.ListByIDs:input_type -> api.serverNameExample.v1.ListUserExampleByIDsRequest
+ 16, // 17: api.serverNameExample.v1.userExample.ListByLastID:input_type -> api.serverNameExample.v1.ListUserExampleByLastIDRequest
+ 18, // 18: api.serverNameExample.v1.userExample.List:input_type -> api.serverNameExample.v1.ListUserExampleRequest
+ 2, // 19: api.serverNameExample.v1.userExample.Create:output_type -> api.serverNameExample.v1.CreateUserExampleReply
+ 4, // 20: api.serverNameExample.v1.userExample.DeleteByID:output_type -> api.serverNameExample.v1.DeleteUserExampleByIDReply
+ 6, // 21: api.serverNameExample.v1.userExample.DeleteByIDs:output_type -> api.serverNameExample.v1.DeleteUserExampleByIDsReply
+ 8, // 22: api.serverNameExample.v1.userExample.UpdateByID:output_type -> api.serverNameExample.v1.UpdateUserExampleByIDReply
+ 11, // 23: api.serverNameExample.v1.userExample.GetByID:output_type -> api.serverNameExample.v1.GetUserExampleByIDReply
+ 13, // 24: api.serverNameExample.v1.userExample.GetByCondition:output_type -> api.serverNameExample.v1.GetUserExampleByConditionReply
+ 15, // 25: api.serverNameExample.v1.userExample.ListByIDs:output_type -> api.serverNameExample.v1.ListUserExampleByIDsReply
+ 17, // 26: api.serverNameExample.v1.userExample.ListByLastID:output_type -> api.serverNameExample.v1.ListUserExampleByLastIDReply
+ 19, // 27: api.serverNameExample.v1.userExample.List:output_type -> api.serverNameExample.v1.ListUserExampleReply
+ 19, // [19:28] is the sub-list for method output_type
+ 10, // [10:19] is the sub-list for method input_type
+ 10, // [10:10] is the sub-list for extension type_name
+ 10, // [10:10] is the sub-list for extension extendee
+ 0, // [0:10] is the sub-list for field type_name
}
func init() { file_api_serverNameExample_v1_userExample_proto_init() }
@@ -1579,7 +1728,7 @@ func file_api_serverNameExample_v1_userExample_proto_init() {
}
}
file_api_serverNameExample_v1_userExample_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ListUserExampleRequest); i {
+ switch v := v.(*ListUserExampleByLastIDRequest); i {
case 0:
return &v.state
case 1:
@@ -1591,6 +1740,30 @@ func file_api_serverNameExample_v1_userExample_proto_init() {
}
}
file_api_serverNameExample_v1_userExample_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListUserExampleByLastIDReply); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_api_serverNameExample_v1_userExample_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListUserExampleRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_api_serverNameExample_v1_userExample_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListUserExampleReply); i {
case 0:
return &v.state
@@ -1609,7 +1782,7 @@ func file_api_serverNameExample_v1_userExample_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_api_serverNameExample_v1_userExample_proto_rawDesc,
NumEnums: 1,
- NumMessages: 17,
+ NumMessages: 19,
NumExtensions: 0,
NumServices: 1,
},
diff --git a/api/serverNameExample/v1/userExample.pb.validate.go b/api/serverNameExample/v1/userExample.pb.validate.go
index 341721c1..f828255b 100644
--- a/api/serverNameExample/v1/userExample.pb.validate.go
+++ b/api/serverNameExample/v1/userExample.pb.validate.go
@@ -1918,6 +1918,252 @@ var _ interface {
ErrorName() string
} = ListUserExampleByIDsReplyValidationError{}
+// Validate checks the field values on ListUserExampleByLastIDRequest with the
+// rules defined in the proto definition for this message. If any rules are
+// violated, the first error encountered is returned, or nil if there are no violations.
+func (m *ListUserExampleByLastIDRequest) Validate() error {
+ return m.validate(false)
+}
+
+// ValidateAll checks the field values on ListUserExampleByLastIDRequest with
+// the rules defined in the proto definition for this message. If any rules
+// are violated, the result is a list of violation errors wrapped in
+// ListUserExampleByLastIDRequestMultiError, or nil if none found.
+func (m *ListUserExampleByLastIDRequest) ValidateAll() error {
+ return m.validate(true)
+}
+
+func (m *ListUserExampleByLastIDRequest) validate(all bool) error {
+ if m == nil {
+ return nil
+ }
+
+ var errors []error
+
+ // no validation rules for LastID
+
+ // no validation rules for Limit
+
+ // no validation rules for Sort
+
+ if len(errors) > 0 {
+ return ListUserExampleByLastIDRequestMultiError(errors)
+ }
+
+ return nil
+}
+
+// ListUserExampleByLastIDRequestMultiError is an error wrapping multiple
+// validation errors returned by ListUserExampleByLastIDRequest.ValidateAll()
+// if the designated constraints aren't met.
+type ListUserExampleByLastIDRequestMultiError []error
+
+// Error returns a concatenation of all the error messages it wraps.
+func (m ListUserExampleByLastIDRequestMultiError) Error() string {
+ var msgs []string
+ for _, err := range m {
+ msgs = append(msgs, err.Error())
+ }
+ return strings.Join(msgs, "; ")
+}
+
+// AllErrors returns a list of validation violation errors.
+func (m ListUserExampleByLastIDRequestMultiError) AllErrors() []error { return m }
+
+// ListUserExampleByLastIDRequestValidationError is the validation error
+// returned by ListUserExampleByLastIDRequest.Validate if the designated
+// constraints aren't met.
+type ListUserExampleByLastIDRequestValidationError struct {
+ field string
+ reason string
+ cause error
+ key bool
+}
+
+// Field function returns field value.
+func (e ListUserExampleByLastIDRequestValidationError) Field() string { return e.field }
+
+// Reason function returns reason value.
+func (e ListUserExampleByLastIDRequestValidationError) Reason() string { return e.reason }
+
+// Cause function returns cause value.
+func (e ListUserExampleByLastIDRequestValidationError) Cause() error { return e.cause }
+
+// Key function returns key value.
+func (e ListUserExampleByLastIDRequestValidationError) Key() bool { return e.key }
+
+// ErrorName returns error name.
+func (e ListUserExampleByLastIDRequestValidationError) ErrorName() string {
+ return "ListUserExampleByLastIDRequestValidationError"
+}
+
+// Error satisfies the builtin error interface
+func (e ListUserExampleByLastIDRequestValidationError) Error() string {
+ cause := ""
+ if e.cause != nil {
+ cause = fmt.Sprintf(" | caused by: %v", e.cause)
+ }
+
+ key := ""
+ if e.key {
+ key = "key for "
+ }
+
+ return fmt.Sprintf(
+ "invalid %sListUserExampleByLastIDRequest.%s: %s%s",
+ key,
+ e.field,
+ e.reason,
+ cause)
+}
+
+var _ error = ListUserExampleByLastIDRequestValidationError{}
+
+var _ interface {
+ Field() string
+ Reason() string
+ Key() bool
+ Cause() error
+ ErrorName() string
+} = ListUserExampleByLastIDRequestValidationError{}
+
+// Validate checks the field values on ListUserExampleByLastIDReply with the
+// rules defined in the proto definition for this message. If any rules are
+// violated, the first error encountered is returned, or nil if there are no violations.
+func (m *ListUserExampleByLastIDReply) Validate() error {
+ return m.validate(false)
+}
+
+// ValidateAll checks the field values on ListUserExampleByLastIDReply with the
+// rules defined in the proto definition for this message. If any rules are
+// violated, the result is a list of violation errors wrapped in
+// ListUserExampleByLastIDReplyMultiError, or nil if none found.
+func (m *ListUserExampleByLastIDReply) ValidateAll() error {
+ return m.validate(true)
+}
+
+func (m *ListUserExampleByLastIDReply) validate(all bool) error {
+ if m == nil {
+ return nil
+ }
+
+ var errors []error
+
+ for idx, item := range m.GetUserExamples() {
+ _, _ = idx, item
+
+ if all {
+ switch v := interface{}(item).(type) {
+ case interface{ ValidateAll() error }:
+ if err := v.ValidateAll(); err != nil {
+ errors = append(errors, ListUserExampleByLastIDReplyValidationError{
+ field: fmt.Sprintf("UserExamples[%v]", idx),
+ reason: "embedded message failed validation",
+ cause: err,
+ })
+ }
+ case interface{ Validate() error }:
+ if err := v.Validate(); err != nil {
+ errors = append(errors, ListUserExampleByLastIDReplyValidationError{
+ field: fmt.Sprintf("UserExamples[%v]", idx),
+ reason: "embedded message failed validation",
+ cause: err,
+ })
+ }
+ }
+ } else if v, ok := interface{}(item).(interface{ Validate() error }); ok {
+ if err := v.Validate(); err != nil {
+ return ListUserExampleByLastIDReplyValidationError{
+ field: fmt.Sprintf("UserExamples[%v]", idx),
+ reason: "embedded message failed validation",
+ cause: err,
+ }
+ }
+ }
+
+ }
+
+ if len(errors) > 0 {
+ return ListUserExampleByLastIDReplyMultiError(errors)
+ }
+
+ return nil
+}
+
+// ListUserExampleByLastIDReplyMultiError is an error wrapping multiple
+// validation errors returned by ListUserExampleByLastIDReply.ValidateAll() if
+// the designated constraints aren't met.
+type ListUserExampleByLastIDReplyMultiError []error
+
+// Error returns a concatenation of all the error messages it wraps.
+func (m ListUserExampleByLastIDReplyMultiError) Error() string {
+ var msgs []string
+ for _, err := range m {
+ msgs = append(msgs, err.Error())
+ }
+ return strings.Join(msgs, "; ")
+}
+
+// AllErrors returns a list of validation violation errors.
+func (m ListUserExampleByLastIDReplyMultiError) AllErrors() []error { return m }
+
+// ListUserExampleByLastIDReplyValidationError is the validation error returned
+// by ListUserExampleByLastIDReply.Validate if the designated constraints
+// aren't met.
+type ListUserExampleByLastIDReplyValidationError struct {
+ field string
+ reason string
+ cause error
+ key bool
+}
+
+// Field function returns field value.
+func (e ListUserExampleByLastIDReplyValidationError) Field() string { return e.field }
+
+// Reason function returns reason value.
+func (e ListUserExampleByLastIDReplyValidationError) Reason() string { return e.reason }
+
+// Cause function returns cause value.
+func (e ListUserExampleByLastIDReplyValidationError) Cause() error { return e.cause }
+
+// Key function returns key value.
+func (e ListUserExampleByLastIDReplyValidationError) Key() bool { return e.key }
+
+// ErrorName returns error name.
+func (e ListUserExampleByLastIDReplyValidationError) ErrorName() string {
+ return "ListUserExampleByLastIDReplyValidationError"
+}
+
+// Error satisfies the builtin error interface
+func (e ListUserExampleByLastIDReplyValidationError) Error() string {
+ cause := ""
+ if e.cause != nil {
+ cause = fmt.Sprintf(" | caused by: %v", e.cause)
+ }
+
+ key := ""
+ if e.key {
+ key = "key for "
+ }
+
+ return fmt.Sprintf(
+ "invalid %sListUserExampleByLastIDReply.%s: %s%s",
+ key,
+ e.field,
+ e.reason,
+ cause)
+}
+
+var _ error = ListUserExampleByLastIDReplyValidationError{}
+
+var _ interface {
+ Field() string
+ Reason() string
+ Key() bool
+ Cause() error
+ ErrorName() string
+} = ListUserExampleByLastIDReplyValidationError{}
+
// Validate checks the field values on ListUserExampleRequest with the rules
// defined in the proto definition for this message. If any rules are
// violated, the first error encountered is returned, or nil if there are no violations.
diff --git a/api/serverNameExample/v1/userExample.proto b/api/serverNameExample/v1/userExample.proto
index b733a303..a0be5a3e 100644
--- a/api/serverNameExample/v1/userExample.proto
+++ b/api/serverNameExample/v1/userExample.proto
@@ -159,6 +159,23 @@ service userExample {
};
}
+ // list userExample by last id
+ rpc ListByLastID(ListUserExampleByLastIDRequest) returns (ListUserExampleByLastIDReply) {
+ option (google.api.http) = {
+ get: "/api/v1/userExample/list"
+ };
+ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
+ summary: "list of userExamples by last id",
+ description: "list of userExamples by last id",
+ //security: {
+ // security_requirement: {
+ // key: "BearerAuth";
+ // value: {}
+ // }
+ //}
+ };
+ }
+
// list of userExample by query parameters
rpc List(ListUserExampleRequest) returns (ListUserExampleReply) {
option (google.api.http) = {
@@ -282,6 +299,16 @@ message ListUserExampleByIDsReply {
repeated UserExample userExamples = 1;
}
+message ListUserExampleByLastIDRequest {
+ uint64 lastID = 1 [(tagger.tags) = "form:\"lastID\""]; // last id
+ uint32 limit = 2 [(tagger.tags) = "form:\"limit\""]; // page size
+ string sort = 3 [(tagger.tags) = "form:\"sort\""]; // sort by column name of table, default is -id, the - sign indicates descending order.
+}
+
+message ListUserExampleByLastIDReply {
+ repeated UserExample userExamples = 1;
+}
+
message ListUserExampleRequest {
types.Params params = 1 [(validate.rules).message.required = true];
}
diff --git a/api/serverNameExample/v1/userExample_grpc.pb.go b/api/serverNameExample/v1/userExample_grpc.pb.go
index 56b4ed09..6768510f 100644
--- a/api/serverNameExample/v1/userExample_grpc.pb.go
+++ b/api/serverNameExample/v1/userExample_grpc.pb.go
@@ -36,6 +36,8 @@ type UserExampleClient interface {
GetByCondition(ctx context.Context, in *GetUserExampleByConditionRequest, opts ...grpc.CallOption) (*GetUserExampleByConditionReply, error)
// list of userExample by batch id
ListByIDs(ctx context.Context, in *ListUserExampleByIDsRequest, opts ...grpc.CallOption) (*ListUserExampleByIDsReply, error)
+ // list userExample by last id
+ ListByLastID(ctx context.Context, in *ListUserExampleByLastIDRequest, opts ...grpc.CallOption) (*ListUserExampleByLastIDReply, error)
// list of userExample by query parameters
List(ctx context.Context, in *ListUserExampleRequest, opts ...grpc.CallOption) (*ListUserExampleReply, error)
}
@@ -111,6 +113,15 @@ func (c *userExampleClient) ListByIDs(ctx context.Context, in *ListUserExampleBy
return out, nil
}
+func (c *userExampleClient) ListByLastID(ctx context.Context, in *ListUserExampleByLastIDRequest, opts ...grpc.CallOption) (*ListUserExampleByLastIDReply, error) {
+ out := new(ListUserExampleByLastIDReply)
+ err := c.cc.Invoke(ctx, "/api.serverNameExample.v1.userExample/ListByLastID", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func (c *userExampleClient) List(ctx context.Context, in *ListUserExampleRequest, opts ...grpc.CallOption) (*ListUserExampleReply, error) {
out := new(ListUserExampleReply)
err := c.cc.Invoke(ctx, "/api.serverNameExample.v1.userExample/List", in, out, opts...)
@@ -138,6 +149,8 @@ type UserExampleServer interface {
GetByCondition(context.Context, *GetUserExampleByConditionRequest) (*GetUserExampleByConditionReply, error)
// list of userExample by batch id
ListByIDs(context.Context, *ListUserExampleByIDsRequest) (*ListUserExampleByIDsReply, error)
+ // list userExample by last id
+ ListByLastID(context.Context, *ListUserExampleByLastIDRequest) (*ListUserExampleByLastIDReply, error)
// list of userExample by query parameters
List(context.Context, *ListUserExampleRequest) (*ListUserExampleReply, error)
mustEmbedUnimplementedUserExampleServer()
@@ -168,6 +181,9 @@ func (UnimplementedUserExampleServer) GetByCondition(context.Context, *GetUserEx
func (UnimplementedUserExampleServer) ListByIDs(context.Context, *ListUserExampleByIDsRequest) (*ListUserExampleByIDsReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListByIDs not implemented")
}
+func (UnimplementedUserExampleServer) ListByLastID(context.Context, *ListUserExampleByLastIDRequest) (*ListUserExampleByLastIDReply, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListByLastID not implemented")
+}
func (UnimplementedUserExampleServer) List(context.Context, *ListUserExampleRequest) (*ListUserExampleReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
}
@@ -310,6 +326,24 @@ func _UserExample_ListByIDs_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
+func _UserExample_ListByLastID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListUserExampleByLastIDRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(UserExampleServer).ListByLastID(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/api.serverNameExample.v1.userExample/ListByLastID",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(UserExampleServer).ListByLastID(ctx, req.(*ListUserExampleByLastIDRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
func _UserExample_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUserExampleRequest)
if err := dec(in); err != nil {
@@ -363,6 +397,10 @@ var UserExample_ServiceDesc = grpc.ServiceDesc{
MethodName: "ListByIDs",
Handler: _UserExample_ListByIDs_Handler,
},
+ {
+ MethodName: "ListByLastID",
+ Handler: _UserExample_ListByLastID_Handler,
+ },
{
MethodName: "List",
Handler: _UserExample_List_Handler,
diff --git a/api/serverNameExample/v1/userExample_router.pb.go b/api/serverNameExample/v1/userExample_router.pb.go
index 42229e65..b7e21204 100644
--- a/api/serverNameExample/v1/userExample_router.pb.go
+++ b/api/serverNameExample/v1/userExample_router.pb.go
@@ -21,6 +21,7 @@ type UserExampleLogicer interface {
GetByID(ctx context.Context, req *GetUserExampleByIDRequest) (*GetUserExampleByIDReply, error)
List(ctx context.Context, req *ListUserExampleRequest) (*ListUserExampleReply, error)
ListByIDs(ctx context.Context, req *ListUserExampleByIDsRequest) (*ListUserExampleByIDsReply, error)
+ ListByLastID(ctx context.Context, req *ListUserExampleByLastIDRequest) (*ListUserExampleByLastIDReply, error)
UpdateByID(ctx context.Context, req *UpdateUserExampleByIDRequest) (*UpdateUserExampleByIDReply, error)
}
@@ -130,6 +131,7 @@ func (r *userExampleRouter) register() {
r.iRouter.Handle("GET", "/api/v1/userExample/:id", r.withMiddleware("GET", "/api/v1/userExample/:id", r.GetByID_0)...)
r.iRouter.Handle("POST", "/api/v1/userExample/condition", r.withMiddleware("POST", "/api/v1/userExample/condition", r.GetByCondition_0)...)
r.iRouter.Handle("POST", "/api/v1/userExample/list/ids", r.withMiddleware("POST", "/api/v1/userExample/list/ids", r.ListByIDs_0)...)
+ r.iRouter.Handle("GET", "/api/v1/userExample/list", r.withMiddleware("GET", "/api/v1/userExample/list", r.ListByLastID_0)...)
r.iRouter.Handle("POST", "/api/v1/userExample/list", r.withMiddleware("POST", "/api/v1/userExample/list", r.List_0)...)
}
@@ -175,7 +177,7 @@ func (r *userExampleRouter) Create_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.Create(ctx, req)
@@ -207,7 +209,7 @@ func (r *userExampleRouter) DeleteByID_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.DeleteByID(ctx, req)
@@ -233,7 +235,7 @@ func (r *userExampleRouter) DeleteByIDs_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.DeleteByIDs(ctx, req)
@@ -265,7 +267,7 @@ func (r *userExampleRouter) UpdateByID_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.UpdateByID(ctx, req)
@@ -297,7 +299,7 @@ func (r *userExampleRouter) GetByID_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.GetByID(ctx, req)
@@ -323,7 +325,7 @@ func (r *userExampleRouter) GetByCondition_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.GetByCondition(ctx, req)
@@ -349,7 +351,7 @@ func (r *userExampleRouter) ListByIDs_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.ListByIDs(ctx, req)
@@ -361,6 +363,32 @@ func (r *userExampleRouter) ListByIDs_0(c *gin.Context) {
r.iResponse.Success(c, out)
}
+func (r *userExampleRouter) ListByLastID_0(c *gin.Context) {
+ req := &ListUserExampleByLastIDRequest{}
+ var err error
+
+ if err = c.ShouldBindQuery(req); err != nil {
+ r.zapLog.Warn("ShouldBindQuery error", zap.Error(err), middleware.GCtxRequestIDField(c))
+ r.iResponse.ParamError(c, err)
+ return
+ }
+
+ var ctx context.Context
+ if r.wrapCtxFn != nil {
+ ctx = r.wrapCtxFn(c)
+ } else {
+ ctx = middleware.WrapCtx(c)
+ }
+
+ out, err := r.iLogic.ListByLastID(ctx, req)
+ if err != nil {
+ r.iResponse.Error(c, err)
+ return
+ }
+
+ r.iResponse.Success(c, out)
+}
+
func (r *userExampleRouter) List_0(c *gin.Context) {
req := &ListUserExampleRequest{}
var err error
@@ -375,7 +403,7 @@ func (r *userExampleRouter) List_0(c *gin.Context) {
if r.wrapCtxFn != nil {
ctx = r.wrapCtxFn(c)
} else {
- ctx = c
+ ctx = middleware.WrapCtx(c)
}
out, err := r.iLogic.List(ctx, req)
diff --git a/api/types/types.pb.go b/api/types/types.pb.go
index 4b995379..c49e5ca6 100644
--- a/api/types/types.pb.go
+++ b/api/types/types.pb.go
@@ -97,7 +97,7 @@ type Column struct {
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name"` // column name
- Exp string `protobuf:"bytes,2,opt,name=exp,proto3" json:"exp"` // expressions, which default to = when the value is null, have =, !=, >, >=, <, <=, like
+ Exp string `protobuf:"bytes,2,opt,name=exp,proto3" json:"exp"` // expressions, which default to = when the value is null, have =, !=, >, >=, <, <=, like, in
Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value"` // column value
Logic string `protobuf:"bytes,4,opt,name=logic,proto3" json:"logic"` // logical type, defaults to and when value is null, only &(and), ||(or)
}
diff --git a/assets/install-cn.md b/assets/install-cn.md
index c61089b0..e6b8b0a6 100644
--- a/assets/install-cn.md
+++ b/assets/install-cn.md
@@ -76,8 +76,8 @@ sponge -v
对cmder进行简单的配置:
-- **配置右键启动cmder**,按下组合键`win+x`,再按字母`a`进入有管理权限的终端,执行命令`Cmder.exe /REGISTER ALL`。 随便在一个文件夹里按下鼠标右键,选择`Cmder Here`即可打开cmder界面。
- **解决输入命令时的空格问题**,打开cmder界面,按下组合键win+alt+p进入设置界面,在左上角搜索`Monospace`,取消勾选,保存退出。
+- **配置右键启动cmder**,按下组合键`win+x`,再按字母`a`进入有管理权限的终端,执行命令`Cmder.exe /REGISTER ALL`。 随便在一个文件夹里按下鼠标右键,选择`Cmder Here`即可打开cmder界面。
> ⚠ 在windows环境使用sponge开发项目,为了避免找不到linux命令错误,请使用cmder,不要用系统自带的cmd终端、Goland和VS Code下的终端。
@@ -89,6 +89,7 @@ make --version
cp --version
chmod --version
rm --version
+sed --version
```
diff --git a/assets/install-en.md b/assets/install-en.md
index 7b166274..95326ff4 100644
--- a/assets/install-en.md
+++ b/assets/install-en.md
@@ -74,8 +74,8 @@ After downloading, extract it to the directory `D:\Program Files\cmder`, and add
Perform basic configuration for cmder:
-- **Configure Right-Click Launch for cmder**: Press the `win+x` key combination, then press the letter `a` to enter the administrative terminal. Execute the command `Cmder.exe /REGISTER ALL`. Right-click in any folder and choose `Cmder Here` to open the cmder interface.
- **Resolve Space Issue While Typing Commands**: Open the cmder interface, press `win+alt+p` to access the settings, search for `Monospace` in the upper left corner, uncheck it, and save and exit.
+- **Configure Right-Click Launch for cmder**: Press the `win+x` key combination, then press the letter `a` to enter the administrative terminal. Execute the command `Cmder.exe /REGISTER ALL`. Right-click in any folder and choose `Cmder Here` to open the cmder interface.
> ⚠ When developing projects with Sponge in a Windows environment, to avoid issues with missing Linux commands, please use cmder instead of the built-in cmd terminal, the terminal in Goland, or the terminal in VS Code.
@@ -87,6 +87,7 @@ make --version
cp --version
chmod --version
rm --version
+sed --version
```
diff --git a/assets/readme-cn.md b/assets/readme-cn.md
index 117c51e5..38347575 100644
--- a/assets/readme-cn.md
+++ b/assets/readme-cn.md
@@ -67,6 +67,7 @@ sponge包含丰富的组件(按需使用):
- 鉴权 [jwt](https://github.com/golang-jwt/jwt)
- 校验 [validator](https://github.com/go-playground/validator)
- 消息组件 [rabbitmq](github.com/rabbitmq/amqp091-go)
+- 分布式事务管理器 [dtm](https://github.com/dtm-labs/dtm)
- 自适应限流 [ratelimit](https://github.com/zhufuyi/sponge/tree/main/pkg/shield/ratelimit)
- 自适应熔断 [circuitbreaker](https://github.com/zhufuyi/sponge/tree/main/pkg/shield/circuitbreaker)
- 链路跟踪 [opentelemetry](https://github.com/open-telemetry/opentelemetry-go)
@@ -153,6 +154,10 @@ sponge run
- [7_community-single](https://github.com/zhufuyi/sponge_examples/tree/main/7_community-single)
- [8_community-cluster](https://github.com/zhufuyi/sponge_examples/tree/main/8_community-cluster)
+#### 分布式事务示例
+
+- [9_order-system](https://github.com/zhufuyi/sponge_examples/tree/main/9_order-grpc-distributed-transaction)
+
### 视频介绍
diff --git a/cmd/serverNameExample_mixExample/initial/registerServer.go b/cmd/serverNameExample_mixExample/initial/registerServer.go
index 87a337f5..0fd6981a 100644
--- a/cmd/serverNameExample_mixExample/initial/registerServer.go
+++ b/cmd/serverNameExample_mixExample/initial/registerServer.go
@@ -54,7 +54,7 @@ func registryService(scheme string, host string, port int) (registry.Registry, *
instance *registry.ServiceInstance
err error
- id = cfg.App.Name + "_" + scheme + "_" + host
+ id = cfg.App.Name + "_" + scheme + "_" + host + "_" + strconv.Itoa(port)
logField logger.Field
)
@@ -103,7 +103,7 @@ func registryService(scheme string, host string, port int) (registry.Registry, *
if instance != nil {
msg := fmt.Sprintf("register service address to %s", cfg.App.RegistryDiscoveryType)
- logger.Info(msg, logField, logger.String("id", id), logger.String("name", cfg.App.Name), logger.String("endpoint", instanceEndpoint))
+ logger.Info(msg, logger.String("name", cfg.App.Name), logger.String("endpoint", instanceEndpoint), logger.String("id", id), logField)
return iRegistry, instance
}
diff --git a/cmd/sponge/commands/generate/common.go b/cmd/sponge/commands/generate/common.go
index b6521231..c99b79c2 100644
--- a/cmd/sponge/commands/generate/common.go
+++ b/cmd/sponge/commands/generate/common.go
@@ -139,7 +139,7 @@ func deleteFieldsMark(r replacer.Replacer, filename string, startMark []byte, en
data, err := r.ReadFile(filename)
if err != nil {
- fmt.Printf("readFile error: %v, please execute the \"sponge update\" command to resolve\n ", err)
+ fmt.Printf("readFile error: %v, please execute the \"sponge upgrade\" command to resolve\n ", err)
return fields
}
if subBytes := gofile.FindSubBytes(data, startMark, endMark); len(subBytes) > 0 {
@@ -159,7 +159,7 @@ func deleteAllFieldsMark(r replacer.Replacer, filename string, startMark []byte,
data, err := r.ReadFile(filename)
if err != nil {
- fmt.Printf("readFile error: %v, please execute the \"sponge update\" command to resolve\n ", err)
+ fmt.Printf("readFile error: %v, please execute the \"sponge upgrade\" command to resolve\n ", err)
return fields
}
allSubBytes := gofile.FindAllSubBytes(data, startMark, endMark)
diff --git a/cmd/sponge/commands/generate/http-pb.go b/cmd/sponge/commands/generate/http-pb.go
index 744444b3..886f60b9 100644
--- a/cmd/sponge/commands/generate/http-pb.go
+++ b/cmd/sponge/commands/generate/http-pb.go
@@ -81,8 +81,8 @@ func runGenHTTPPbCommand(moduleName string, serverName string, projectName strin
"sponge/.gitignore", "sponge/.golangci.yml", "sponge/go.mod", "sponge/go.sum",
"sponge/Jenkinsfile", "sponge/Makefile", "sponge/README.md",
}
- ignoreDirs := []string{} // specify the directory in the subdirectory where processing is ignored
- ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
+ ignoreDirs := []string{"cmd/sponge"} // specify the directory in the subdirectory where processing is ignored
+ ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
"types.pb.validate.go", "types.pb.go", // api/types
"swagger.json", "swagger.yaml", "apis.swagger.json", "apis.html", "docs.go", // sponge/docs
"userExample_rpc.go", "systemCode_rpc.go", "userExample_http.go", // internal/ecode
diff --git a/cmd/sponge/commands/generate/http.go b/cmd/sponge/commands/generate/http.go
index e2335b97..71aff36d 100644
--- a/cmd/sponge/commands/generate/http.go
+++ b/cmd/sponge/commands/generate/http.go
@@ -142,7 +142,7 @@ func runGenHTTPCommand(moduleName string, serverName string, projectName string,
"sponge/Jenkinsfile", "sponge/Makefile", "sponge/README.md",
}
ignoreDirs := []string{ // specify the directory in the subdirectory where processing is ignored
- "internal/service", "internal/rpcclient",
+ "internal/service", "internal/rpcclient", "cmd/sponge",
}
ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
"swagger.json", "swagger.yaml", "apis.swagger.json", "apis.html", "apis.go", // sponge/docs
diff --git a/cmd/sponge/commands/generate/rpc-gw-pb.go b/cmd/sponge/commands/generate/rpc-gw-pb.go
index 0e8c26b4..6db93d83 100644
--- a/cmd/sponge/commands/generate/rpc-gw-pb.go
+++ b/cmd/sponge/commands/generate/rpc-gw-pb.go
@@ -81,8 +81,8 @@ func runGenRPCGwCommand(moduleName string, serverName string, projectName string
"sponge/.gitignore", "sponge/.golangci.yml", "sponge/go.mod", "sponge/go.sum",
"sponge/Jenkinsfile", "sponge/Makefile", "sponge/README.md",
}
- ignoreDirs := []string{} // specify the directory in the subdirectory where processing is ignored
- ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
+ ignoreDirs := []string{"cmd/sponge"} // specify the directory in the subdirectory where processing is ignored
+ ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
"types.pb.validate.go", "types.pb.go", // api/types
"swagger.json", "swagger.yaml", "apis.swagger.json", "apis.html", "docs.go", // sponge/docs
"userExample_rpc.go", "systemCode_http.go", "userExample_http.go", // internal/ecode
diff --git a/cmd/sponge/commands/generate/rpc-pb.go b/cmd/sponge/commands/generate/rpc-pb.go
index 022c4f31..3dcdb7d2 100644
--- a/cmd/sponge/commands/generate/rpc-pb.go
+++ b/cmd/sponge/commands/generate/rpc-pb.go
@@ -80,8 +80,8 @@ func runGenRPCPbCommand(moduleName string, serverName string, projectName string
"sponge/.gitignore", "sponge/.golangci.yml", "sponge/go.mod", "sponge/go.sum",
"sponge/Jenkinsfile", "sponge/Makefile", "sponge/README.md",
}
- ignoreDirs := []string{} // specify the directory in the subdirectory where processing is ignored
- ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
+ ignoreDirs := []string{"cmd/sponge"} // specify the directory in the subdirectory where processing is ignored
+ ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
"types.pb.validate.go", "types.pb.go", // api/types
"userExample_rpc.go", "systemCode_http.go", "userExample_http.go", // internal/ecode
"http.go", "http_option.go", "http_test.go", // internal/server
diff --git a/cmd/sponge/commands/generate/rpc.go b/cmd/sponge/commands/generate/rpc.go
index aa667e6b..21c04334 100644
--- a/cmd/sponge/commands/generate/rpc.go
+++ b/cmd/sponge/commands/generate/rpc.go
@@ -143,7 +143,7 @@ func runGenRPCCommand(moduleName string, serverName string, projectName string,
"sponge/Jenkinsfile", "sponge/Makefile", "sponge/README.md",
}
ignoreDirs := []string{ // specify the directory in the subdirectory where processing is ignored
- "internal/handler", "internal/rpcclient", "internal/routers", "internal/types",
+ "internal/handler", "internal/rpcclient", "internal/routers", "internal/types", "cmd/sponge",
}
ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
"types.pb.validate.go", "types.pb.go", // api/types
diff --git a/cmd/sponge/commands/run.go b/cmd/sponge/commands/run.go
index ced5a7e4..f121bdd1 100644
--- a/cmd/sponge/commands/run.go
+++ b/cmd/sponge/commands/run.go
@@ -54,7 +54,7 @@ visit %s in your browser.
},
}
cmd.Flags().IntVarP(&port, "port", "p", 24631, "port on which the sponge service listens")
- cmd.Flags().StringVarP(&spongeAddr, "addr", "a", "", "address of the front-end page requesting the sponge service, e.g. http://192.168.1.10:24631 or https://go-sponge.com/ui")
+ cmd.Flags().StringVarP(&spongeAddr, "addr", "a", "", "address of the front-end page requesting the sponge service, e.g. http://192.168.1.10:24631 or https://your-domain.com")
cmd.Flags().BoolVarP(&isLog, "log", "l", false, "enable service logging")
return cmd
}
diff --git a/cmd/sponge/scripts/image-build.sh b/cmd/sponge/scripts/build-sponge-image.sh
similarity index 93%
rename from cmd/sponge/scripts/image-build.sh
rename to cmd/sponge/scripts/build-sponge-image.sh
index efe0fce6..4db11b4e 100644
--- a/cmd/sponge/scripts/image-build.sh
+++ b/cmd/sponge/scripts/build-sponge-image.sh
@@ -2,16 +2,15 @@
TAG=$1
if [ "X${TAG}" = "X" ];then
- echo "image tag cannot be empty, example: ./image-build.sh v1.0.0"
+ echo "image tag cannot be empty, example: ./image-build.sh v1.5.8"
exit 1
fi
function rmFile() {
sFile=$1
- if [ "X${sFile}" = "X" ];then
- return 0
+ if [ -e "${sFile}" ]; then
+ rm -rf ${sFile}
fi
- rm -f ${sFile}
}
function checkResult() {
@@ -48,7 +47,7 @@ docker build -t zhufuyi/sponge:${TAG} .
checkResult $?
rmFile sponge
-rmFile .sponge
+rm -rf .sponge
# delete none image
noneImages=$(docker images | grep "" | awk '{print $3}')
diff --git a/configs/serverNameExample_cc.yml b/configs/serverNameExample_cc.yml
index 40ef3025..d908e502 100644
--- a/configs/serverNameExample_cc.yml
+++ b/configs/serverNameExample_cc.yml
@@ -4,7 +4,7 @@
nacos:
ipAddr: "192.168.3.37" # server address
port: 8848 # listening port
- scheme: "http" # http or https
+ scheme: "http" # http or grpc
contextPath: "/nacos" # path
namespaceID: "3454d2b5-2455-4d0e-bf6d-e033b086bb4c" # namespace id
group: "dev" # group name: dev, prod, test
diff --git a/docs/apis.swagger.json b/docs/apis.swagger.json
index cf720b0f..2ce12a63 100644
--- a/docs/apis.swagger.json
+++ b/docs/apis.swagger.json
@@ -124,6 +124,50 @@
}
},
"/api/v1/userExample/list": {
+ "get": {
+ "summary": "list of userExamples by last id",
+ "description": "list of userExamples by last id",
+ "operationId": "userExample_ListByLastID",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/v1ListUserExampleByLastIDReply"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response.",
+ "schema": {
+ "$ref": "#/definitions/rpcStatus"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "lastID",
+ "in": "query",
+ "required": false,
+ "type": "integer",
+ "format": "uint64"
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "required": false,
+ "type": "integer",
+ "format": "int64"
+ },
+ {
+ "name": "sort",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "tags": [
+ "userExample"
+ ]
+ },
"post": {
"summary": "list of userExamples by query parameters",
"description": "list of userExamples by paging and conditions",
@@ -515,6 +559,17 @@
}
}
},
+ "v1ListUserExampleByLastIDReply": {
+ "type": "object",
+ "properties": {
+ "userExamples": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/v1UserExample"
+ }
+ }
+ }
+ },
"v1ListUserExampleReply": {
"type": "object",
"properties": {
diff --git a/docs/docs.go b/docs/docs.go
index 0afc2984..e79bc1ae 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -70,7 +70,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
- "$ref": "#/definitions/types.Conditions"
+ "$ref": "#/definitions/github_com_zhufuyi_sponge_internal_types.Conditions"
}
}
],
@@ -119,6 +119,50 @@ const docTemplate = `{
}
},
"/api/v1/userExample/list": {
+ "get": {
+ "description": "list of userExamples by last id and limit",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "userExample"
+ ],
+ "summary": "list of userExamples by last id and limit",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "last id, default is MaxInt64",
+ "name": "lastID",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "default": 10,
+ "description": "size in each page",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "default": "-id",
+ "description": "sort by column name of table, and the ",
+ "name": "sort",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/types.ListUserExamplesRespond"
+ }
+ }
+ }
+ },
"post": {
"description": "list of userExamples by paging and conditions",
"consumes": [
@@ -380,6 +424,18 @@ const docTemplate = `{
}
}
},
+ "github_com_zhufuyi_sponge_internal_types.Conditions": {
+ "type": "object",
+ "properties": {
+ "columns": {
+ "description": "columns info",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/github_com_zhufuyi_sponge_internal_types.Column"
+ }
+ }
+ }
+ },
"github_com_zhufuyi_sponge_internal_types.Params": {
"type": "object",
"properties": {
@@ -415,18 +471,6 @@ const docTemplate = `{
}
}
},
- "types.Conditions": {
- "type": "object",
- "properties": {
- "columns": {
- "description": "columns info",
- "type": "array",
- "items": {
- "$ref": "#/definitions/github_com_zhufuyi_sponge_internal_types.Column"
- }
- }
- }
- },
"types.CreateUserExampleRequest": {
"type": "object",
"properties": {
diff --git a/docs/swagger.json b/docs/swagger.json
index 9460b87f..da51ea5d 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -66,7 +66,7 @@
"in": "body",
"required": true,
"schema": {
- "$ref": "#/definitions/types.Conditions"
+ "$ref": "#/definitions/github_com_zhufuyi_sponge_internal_types.Conditions"
}
}
],
@@ -115,6 +115,50 @@
}
},
"/api/v1/userExample/list": {
+ "get": {
+ "description": "list of userExamples by last id and limit",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "userExample"
+ ],
+ "summary": "list of userExamples by last id and limit",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "last id, default is MaxInt64",
+ "name": "lastID",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "default": 10,
+ "description": "size in each page",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "default": "-id",
+ "description": "sort by column name of table, and the ",
+ "name": "sort",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/types.ListUserExamplesRespond"
+ }
+ }
+ }
+ },
"post": {
"description": "list of userExamples by paging and conditions",
"consumes": [
@@ -376,6 +420,18 @@
}
}
},
+ "github_com_zhufuyi_sponge_internal_types.Conditions": {
+ "type": "object",
+ "properties": {
+ "columns": {
+ "description": "columns info",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/github_com_zhufuyi_sponge_internal_types.Column"
+ }
+ }
+ }
+ },
"github_com_zhufuyi_sponge_internal_types.Params": {
"type": "object",
"properties": {
@@ -411,18 +467,6 @@
}
}
},
- "types.Conditions": {
- "type": "object",
- "properties": {
- "columns": {
- "description": "columns info",
- "type": "array",
- "items": {
- "$ref": "#/definitions/github_com_zhufuyi_sponge_internal_types.Column"
- }
- }
- }
- },
"types.CreateUserExampleRequest": {
"type": "object",
"properties": {
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index f16673d0..b047e28a 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -15,6 +15,14 @@ definitions:
value:
description: column value
type: object
+ github_com_zhufuyi_sponge_internal_types.Conditions:
+ properties:
+ columns:
+ description: columns info
+ items:
+ $ref: '#/definitions/github_com_zhufuyi_sponge_internal_types.Column'
+ type: array
+ type: object
github_com_zhufuyi_sponge_internal_types.Params:
properties:
columns:
@@ -39,14 +47,6 @@ definitions:
status:
type: string
type: object
- types.Conditions:
- properties:
- columns:
- description: columns info
- items:
- $ref: '#/definitions/github_com_zhufuyi_sponge_internal_types.Column'
- type: array
- type: object
types.CreateUserExampleRequest:
properties:
age:
@@ -376,7 +376,7 @@ paths:
name: data
required: true
schema:
- $ref: '#/definitions/types.Conditions'
+ $ref: '#/definitions/github_com_zhufuyi_sponge_internal_types.Conditions'
produces:
- application/json
responses:
@@ -410,6 +410,36 @@ paths:
tags:
- userExample
/api/v1/userExample/list:
+ get:
+ consumes:
+ - application/json
+ description: list of userExamples by last id and limit
+ parameters:
+ - description: last id, default is MaxInt64
+ in: query
+ name: lastID
+ required: true
+ type: integer
+ - default: 10
+ description: size in each page
+ in: query
+ name: limit
+ type: integer
+ - default: -id
+ description: 'sort by column name of table, and the '
+ in: query
+ name: sort
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/types.ListUserExamplesRespond'
+ summary: list of userExamples by last id and limit
+ tags:
+ - userExample
post:
consumes:
- application/json
diff --git a/examples/README.md b/examples/README.md
index f1ac24ee..87da9edd 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -8,3 +8,4 @@
- [6_micro-cluster](https://github.com/zhufuyi/sponge_examples/tree/main/6_micro-cluster)
- [7_community-single](https://github.com/zhufuyi/sponge_examples/tree/main/7_community-single)
- [8_community-cluster](https://github.com/zhufuyi/sponge_examples/tree/main/8_community-cluster)
+- [9_order-grpc-distributed-transaction](https://github.com/zhufuyi/sponge_examples/tree/main/9_order-grpc-distributed-transaction)
diff --git a/internal/dao/userExample.go b/internal/dao/userExample.go
index faf6ec50..d90b1bcd 100644
--- a/internal/dao/userExample.go
+++ b/internal/dao/userExample.go
@@ -28,6 +28,7 @@ type UserExampleDao interface {
GetByID(ctx context.Context, id uint64) (*model.UserExample, error)
GetByCondition(ctx context.Context, condition *query.Conditions) (*model.UserExample, error)
GetByIDs(ctx context.Context, ids []uint64) (map[uint64]*model.UserExample, error)
+ GetByLastID(ctx context.Context, lastID uint64, limit int, sort string) ([]*model.UserExample, error)
GetByColumns(ctx context.Context, params *query.Params) ([]*model.UserExample, int64, error)
CreateByTx(ctx context.Context, tx *gorm.DB, table *model.UserExample) (uint64, error)
@@ -214,7 +215,7 @@ func (d *userExampleDao) GetByCondition(ctx context.Context, c *query.Conditions
return table, nil
}
-// GetByIDs list of records by batch id
+// GetByIDs get records by batch id
func (d *userExampleDao) GetByIDs(ctx context.Context, ids []uint64) (map[uint64]*model.UserExample, error) {
itemMap, err := d.cache.MultiGet(ctx, ids)
if err != nil {
@@ -268,7 +269,19 @@ func (d *userExampleDao) GetByIDs(ctx context.Context, ids []uint64) (map[uint64
return itemMap, nil
}
-// GetByColumns get records by paging and column information,
+// GetByLastID get paging records by last id and limit
+func (d *userExampleDao) GetByLastID(ctx context.Context, lastID uint64, limit int, sort string) ([]*model.UserExample, error) {
+ page := query.NewPage(0, limit, sort)
+
+ records := []*model.UserExample{}
+ err := d.db.WithContext(ctx).Order(page.Sort()).Limit(page.Size()).Where("id < ?", lastID).Find(&records).Error
+ if err != nil {
+ return nil, err
+ }
+ return records, nil
+}
+
+// GetByColumns get paging records by column information,
// Note: query performance degrades when table rows are very large because of the use of offset.
//
// params includes paging parameters and query parameters
diff --git a/internal/dao/userExample_test.go b/internal/dao/userExample_test.go
index 505a2446..5b7b5841 100644
--- a/internal/dao/userExample_test.go
+++ b/internal/dao/userExample_test.go
@@ -251,6 +251,31 @@ func Test_userExampleDao_GetByIDs(t *testing.T) {
}
}
+func Test_userExampleDao_GetByLastID(t *testing.T) {
+ d := newUserExampleDao()
+ defer d.Close()
+ testData := d.TestData.(*model.UserExample)
+
+ rows := sqlmock.NewRows([]string{"id", "created_at", "updated_at"}).
+ AddRow(testData.ID, testData.CreatedAt, testData.UpdatedAt)
+
+ d.SQLMock.ExpectQuery("SELECT .*").WillReturnRows(rows)
+
+ _, err := d.IDao.(UserExampleDao).GetByLastID(d.Ctx, 0, 10, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = d.SQLMock.ExpectationsWereMet()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // err test
+ _, err = d.IDao.(UserExampleDao).GetByLastID(d.Ctx, 0, 10, "unknown-column")
+ assert.Error(t, err)
+}
+
func Test_userExampleDao_GetByColumns(t *testing.T) {
d := newUserExampleDao()
defer d.Close()
diff --git a/internal/ecode/userExample_http.go b/internal/ecode/userExample_http.go
index 15ee95c0..c6fdf6a2 100644
--- a/internal/ecode/userExample_http.go
+++ b/internal/ecode/userExample_http.go
@@ -18,6 +18,7 @@ var (
ErrGetByIDUserExample = errcode.NewError(userExampleBaseCode+5, "failed to get "+userExampleName+" details")
ErrGetByConditionUserExample = errcode.NewError(userExampleBaseCode+6, "failed to get "+userExampleName+" details by conditions")
ErrListByIDsUserExample = errcode.NewError(userExampleBaseCode+7, "failed to list by batch ids "+userExampleName)
- ErrListUserExample = errcode.NewError(userExampleBaseCode+8, "failed to list of "+userExampleName)
+ ErrListByLastIDUserExample = errcode.NewError(userExampleBaseCode+8, "failed to list by last id "+userExampleName)
+ ErrListUserExample = errcode.NewError(userExampleBaseCode+9, "failed to list of "+userExampleName)
// error codes are globally unique, adding 1 to the previous error code
)
diff --git a/internal/ecode/userExample_rpc.go b/internal/ecode/userExample_rpc.go
index 8b7e59cf..0565702a 100644
--- a/internal/ecode/userExample_rpc.go
+++ b/internal/ecode/userExample_rpc.go
@@ -18,6 +18,7 @@ var (
StatusGetByIDUserExample = errcode.NewRPCStatus(_userExampleBaseCode+5, "failed to get "+_userExampleName+" details")
StatusGetByConditionUserExample = errcode.NewRPCStatus(_userExampleBaseCode+6, "failed to get "+_userExampleName+" by conditions")
StatusListByIDsUserExample = errcode.NewRPCStatus(_userExampleBaseCode+7, "failed to list by batch ids "+_userExampleName)
- StatusListUserExample = errcode.NewRPCStatus(_userExampleBaseCode+8, "failed to list of "+_userExampleName)
+ StatusListByLastIDUserExample = errcode.NewRPCStatus(_userExampleBaseCode+8, "failed to list by last id "+_userExampleName)
+ StatusListUserExample = errcode.NewRPCStatus(_userExampleBaseCode+9, "failed to list of "+_userExampleName)
// error codes are globally unique, adding 1 to the previous error code
)
diff --git a/internal/handler/userExample.go b/internal/handler/userExample.go
index 7da26bcf..7eb72dda 100644
--- a/internal/handler/userExample.go
+++ b/internal/handler/userExample.go
@@ -2,6 +2,7 @@ package handler
import (
"errors"
+ "math"
"github.com/zhufuyi/sponge/internal/cache"
"github.com/zhufuyi/sponge/internal/dao"
@@ -30,6 +31,7 @@ type UserExampleHandler interface {
GetByID(c *gin.Context)
GetByCondition(c *gin.Context)
ListByIDs(c *gin.Context)
+ ListByLastID(c *gin.Context)
List(c *gin.Context)
}
@@ -315,6 +317,47 @@ func (h *userExampleHandler) ListByIDs(c *gin.Context) {
})
}
+// ListByLastID get records by last id and limit
+// @Summary list of userExamples by last id and limit
+// @Description list of userExamples by last id and limit
+// @Tags userExample
+// @accept json
+// @Produce json
+// @Param lastID query int true "last id, default is MaxInt64"
+// @Param limit query int false "size in each page" default(10)
+// @Param sort query string false "sort by column name of table, and the "-" sign before column name indicates reverse order" default(-id)
+// @Success 200 {object} types.ListUserExamplesRespond{}
+// @Router /api/v1/userExample/list [get]
+func (h *userExampleHandler) ListByLastID(c *gin.Context) {
+ lastID := utils.StrToUint64(c.Query("lastID"))
+ if lastID == 0 {
+ lastID = math.MaxInt64
+ }
+ limit := utils.StrToInt(c.Query("limit"))
+ if limit == 0 {
+ limit = 10
+ }
+ sort := c.Query("sort")
+
+ ctx := middleware.WrapCtx(c)
+ userExamples, err := h.iDao.GetByLastID(ctx, lastID, limit, sort)
+ if err != nil {
+ logger.Error("GetByLastID error", logger.Err(err), logger.Uint64("latsID", lastID), logger.Int("limit", limit), middleware.GCtxRequestIDField(c))
+ response.Output(c, ecode.InternalServerError.ToHTTPCode())
+ return
+ }
+
+ data, err := convertUserExamples(userExamples)
+ if err != nil {
+ response.Error(c, ecode.ErrListByLastIDUserExample)
+ return
+ }
+
+ response.Success(c, gin.H{
+ "userExamples": data,
+ })
+}
+
// List of records by query parameters
// @Summary list of userExamples by query parameters
// @Description list of userExamples by paging and conditions
diff --git a/internal/handler/userExample_logic.go b/internal/handler/userExample_logic.go
index e754225c..c0698b8e 100644
--- a/internal/handler/userExample_logic.go
+++ b/internal/handler/userExample_logic.go
@@ -216,6 +216,35 @@ func (h *userExamplePbHandler) ListByIDs(ctx context.Context, req *serverNameExa
}, nil
}
+// ListByLastID get records by last id
+func (h *userExamplePbHandler) ListByLastID(ctx context.Context, req *serverNameExampleV1.ListUserExampleByLastIDRequest) (*serverNameExampleV1.ListUserExampleByLastIDReply, error) {
+ err := req.Validate()
+ if err != nil {
+ logger.Warn("req.Validate error", logger.Err(err), logger.Any("req", req), middleware.CtxRequestIDField(ctx))
+ return nil, ecode.InvalidParams.Err()
+ }
+
+ records, err := h.userExampleDao.GetByLastID(ctx, req.LastID, int(req.Limit), req.Sort)
+ if err != nil {
+ logger.Error("GetByColumns error", logger.Err(err), logger.Any("req", req), middleware.CtxRequestIDField(ctx))
+ return nil, ecode.InternalServerError.Err()
+ }
+
+ userExamples := []*serverNameExampleV1.UserExample{}
+ for _, record := range records {
+ data, err := convertUserExamplePb(record)
+ if err != nil {
+ logger.Warn("convertUserExample error", logger.Err(err), logger.Any("id", record.ID), middleware.CtxRequestIDField(ctx))
+ continue
+ }
+ userExamples = append(userExamples, data)
+ }
+
+ return &serverNameExampleV1.ListUserExampleByLastIDReply{
+ UserExamples: userExamples,
+ }, nil
+}
+
// List of records by query parameters
func (h *userExamplePbHandler) List(ctx context.Context, req *serverNameExampleV1.ListUserExampleRequest) (*serverNameExampleV1.ListUserExampleReply, error) {
err := req.Validate()
diff --git a/internal/handler/userExample_logic_test.go b/internal/handler/userExample_logic_test.go
index 594ea8cb..c7b7ca55 100644
--- a/internal/handler/userExample_logic_test.go
+++ b/internal/handler/userExample_logic_test.go
@@ -155,6 +155,21 @@ func newUserExamplePbHandler() *gotest.Handler {
response.Success(c)
},
},
+ {
+ FuncName: "ListByLastID",
+ Method: http.MethodGet,
+ Path: "/userExample/list",
+ HandlerFunc: func(c *gin.Context) {
+ req := &serverNameExampleV1.ListUserExampleByLastIDRequest{}
+ _ = c.ShouldBindJSON(req)
+ _, err := iHandler.ListByLastID(c, req)
+ if err != nil {
+ response.Error(c, ecode.ErrListByLastIDUserExample)
+ return
+ }
+ response.Success(c)
+ },
+ },
{
FuncName: "List",
Method: http.MethodPost,
@@ -430,6 +445,30 @@ func Test_userExamplePbHandler_ListByIDs(t *testing.T) {
assert.NoError(t, err)
}
+func Test_userExamplePbHandler_ListByLastID(t *testing.T) {
+ h := newUserExamplePbHandler()
+ defer h.Close()
+ testData := h.TestData.(*model.UserExample)
+
+ rows := sqlmock.NewRows([]string{"id", "created_at", "updated_at"}).
+ AddRow(testData.ID, testData.CreatedAt, testData.UpdatedAt)
+
+ h.MockDao.SQLMock.ExpectQuery("SELECT .*").WillReturnRows(rows)
+
+ result := &gohttp.StdResult{}
+ err := gohttp.Get(result, h.GetRequestURL("ListByLastID"), gohttp.KV{"lastID": 0, "size": 10})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if result.Code != 0 {
+ t.Fatalf("%+v", result)
+ }
+
+ // get error test
+ err = gohttp.Get(result, h.GetRequestURL("ListByLastID"), gohttp.KV{"lastID": 0, "size": 10, "sort": "unknown-column"})
+ assert.NoError(t, err)
+}
+
func Test_userExamplePbHandler_List(t *testing.T) {
h := newUserExamplePbHandler()
defer h.Close()
diff --git a/internal/handler/userExample_test.go b/internal/handler/userExample_test.go
index 459ee073..f3754007 100644
--- a/internal/handler/userExample_test.go
+++ b/internal/handler/userExample_test.go
@@ -86,6 +86,12 @@ func newUserExampleHandler() *gotest.Handler {
Path: "/userExample/list/ids",
HandlerFunc: iHandler.ListByIDs,
},
+ {
+ FuncName: "ListByLastID",
+ Method: http.MethodGet,
+ Path: "/userExample/list",
+ HandlerFunc: iHandler.ListByLastID,
+ },
{
FuncName: "List",
Method: http.MethodPost,
@@ -337,6 +343,30 @@ func Test_userExampleHandler_ListByIDs(t *testing.T) {
assert.Error(t, err)
}
+func Test_userExampleHandler_ListByLastID(t *testing.T) {
+ h := newUserExampleHandler()
+ defer h.Close()
+ testData := h.TestData.(*model.UserExample)
+
+ rows := sqlmock.NewRows([]string{"id", "created_at", "updated_at"}).
+ AddRow(testData.ID, testData.CreatedAt, testData.UpdatedAt)
+
+ h.MockDao.SQLMock.ExpectQuery("SELECT .*").WillReturnRows(rows)
+
+ result := &gohttp.StdResult{}
+ err := gohttp.Get(result, h.GetRequestURL("ListByLastID"), gohttp.KV{"lastID": 0, "size": 10})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if result.Code != 0 {
+ t.Fatalf("%+v", result)
+ }
+
+ // error test
+ err = gohttp.Get(result, h.GetRequestURL("ListByLastID"), gohttp.KV{"lastID": 0, "size": 10, "sort": "unknown-column"})
+ assert.Error(t, err)
+}
+
func Test_userExampleHandler_List(t *testing.T) {
h := newUserExampleHandler()
defer h.Close()
@@ -362,12 +392,15 @@ func Test_userExampleHandler_List(t *testing.T) {
// nil params error test
err = gohttp.Post(result, h.GetRequestURL("List"), nil)
+ assert.NoError(t, err)
// get error test
err = gohttp.Post(result, h.GetRequestURL("List"), &types.ListUserExamplesRequest{query.Params{
Page: 0,
Size: 10,
+ Sort: "unknown-column",
}})
+ assert.Error(t, err)
}
func TestNewUserExampleHandler(t *testing.T) {
diff --git a/internal/routers/routers_pbExample_test.go b/internal/routers/routers_pbExample_test.go
index b6e2cf7a..1db57189 100644
--- a/internal/routers/routers_pbExample_test.go
+++ b/internal/routers/routers_pbExample_test.go
@@ -71,6 +71,10 @@ func (m mockGw) DeleteByIDs(ctx context.Context, req *serverNameExampleV1.Delete
return nil, nil
}
+func (m mockGw) UpdateByID(ctx context.Context, req *serverNameExampleV1.UpdateUserExampleByIDRequest) (*serverNameExampleV1.UpdateUserExampleByIDReply, error) {
+ return nil, nil
+}
+
func (m mockGw) GetByID(ctx context.Context, req *serverNameExampleV1.GetUserExampleByIDRequest) (*serverNameExampleV1.GetUserExampleByIDReply, error) {
return nil, nil
}
@@ -79,14 +83,14 @@ func (m mockGw) GetByCondition(ctx context.Context, req *serverNameExampleV1.Get
return nil, nil
}
-func (m mockGw) List(ctx context.Context, req *serverNameExampleV1.ListUserExampleRequest) (*serverNameExampleV1.ListUserExampleReply, error) {
+func (m mockGw) ListByIDs(ctx context.Context, req *serverNameExampleV1.ListUserExampleByIDsRequest) (*serverNameExampleV1.ListUserExampleByIDsReply, error) {
return nil, nil
}
-func (m mockGw) ListByIDs(ctx context.Context, req *serverNameExampleV1.ListUserExampleByIDsRequest) (*serverNameExampleV1.ListUserExampleByIDsReply, error) {
+func (m mockGw) ListByLastID(ctx context.Context, req *serverNameExampleV1.ListUserExampleByLastIDRequest) (*serverNameExampleV1.ListUserExampleByLastIDReply, error) {
return nil, nil
}
-func (m mockGw) UpdateByID(ctx context.Context, req *serverNameExampleV1.UpdateUserExampleByIDRequest) (*serverNameExampleV1.UpdateUserExampleByIDReply, error) {
+func (m mockGw) List(ctx context.Context, req *serverNameExampleV1.ListUserExampleRequest) (*serverNameExampleV1.ListUserExampleReply, error) {
return nil, nil
}
diff --git a/internal/routers/routers_test.go b/internal/routers/routers_test.go
index 647f7c76..4db7f083 100644
--- a/internal/routers/routers_test.go
+++ b/internal/routers/routers_test.go
@@ -59,6 +59,7 @@ func (u mock) UpdateByID(c *gin.Context) { return }
func (u mock) GetByID(c *gin.Context) { return }
func (u mock) GetByCondition(c *gin.Context) { return }
func (u mock) ListByIDs(c *gin.Context) { return }
+func (u mock) ListByLastID(c *gin.Context) { return }
func (u mock) List(c *gin.Context) { return }
func Test_userExampleRouter(t *testing.T) {
diff --git a/internal/routers/userExample.go b/internal/routers/userExample.go
index d1bd4c18..38203825 100644
--- a/internal/routers/userExample.go
+++ b/internal/routers/userExample.go
@@ -23,5 +23,6 @@ func userExampleRouter(group *gin.RouterGroup, h handler.UserExampleHandler) {
group.GET("/userExample/:id", h.GetByID)
group.POST("/userExample/condition", h.GetByCondition)
group.POST("/userExample/list/ids", h.ListByIDs)
+ group.GET("/userExample/list", h.ListByLastID)
group.POST("/userExample/list", h.List)
}
diff --git a/internal/routers/userExample_router.go b/internal/routers/userExample_router.go
index bb67bff0..8c6989e1 100644
--- a/internal/routers/userExample_router.go
+++ b/internal/routers/userExample_router.go
@@ -66,13 +66,13 @@ func userExampleMiddlewares(c *middlewareConfig) {
// c.setGroupPath("/api/v1/userExample", middleware.Auth())
// set up single route middleware, just uncomment the code and fill in the middlewares, nothing else needs to be changed
- //c.setSinglePath("POST", "/api/v1/userExample")
+ //c.setSinglePath("POST", "/api/v1/userExample", middleware.Auth())
//c.setSinglePath("DELETE", "/api/v1/userExample/:id", middleware.Auth())
//c.setSinglePath("POST", "/api/v1/userExample/delete/ids", middleware.Auth())
//c.setSinglePath("PUT", "/api/v1/userExample/:id", middleware.Auth())
//c.setSinglePath("GET", "/api/v1/userExample/:id", middleware.Auth())
+ //c.setSinglePath("POST", "/api/v1/userExample/condition", middleware.Auth())
//c.setSinglePath("POST", "/api/v1/userExample/list/ids", middleware.Auth())
+ //c.setSinglePath("GET", "/api/v1/userExample/list", middleware.Auth())
//c.setSinglePath("POST", "/api/v1/userExample/list", middleware.Auth())
- //c.setSinglePath("POST", "/api/v1/userExample", middleware.Auth())
- //c.setSinglePath("POST", "/api/v1/userExample/condition", middleware.Auth())
}
diff --git a/internal/service/userExample.go b/internal/service/userExample.go
index 1ac16c46..5586c7f7 100644
--- a/internal/service/userExample.go
+++ b/internal/service/userExample.go
@@ -3,6 +3,7 @@ package service
import (
"context"
"errors"
+ "math"
"strings"
serverNameExampleV1 "github.com/zhufuyi/sponge/api/serverNameExample/v1"
@@ -228,6 +229,41 @@ func (s *userExample) ListByIDs(ctx context.Context, req *serverNameExampleV1.Li
return &serverNameExampleV1.ListUserExampleByIDsReply{UserExamples: userExamples}, nil
}
+// ListByLastID list userExample by last id
+func (s *userExample) ListByLastID(ctx context.Context, req *serverNameExampleV1.ListUserExampleByLastIDRequest) (*serverNameExampleV1.ListUserExampleByLastIDReply, error) {
+ err := req.Validate()
+ if err != nil {
+ logger.Warn("req.Validate error", logger.Err(err), logger.Any("req", req), interceptor.CtxRequestIDField(ctx))
+ return nil, ecode.StatusInvalidParams.Err()
+ }
+ if req.LastID == 0 {
+ req.LastID = math.MaxInt64
+ }
+ if req.Limit == 0 {
+ req.Limit = 10
+ }
+
+ records, err := s.iDao.GetByLastID(ctx, req.LastID, int(req.Limit), req.Sort)
+ if err != nil {
+ logger.Error("ListByLastID error", logger.Err(err), interceptor.CtxRequestIDField(ctx))
+ return nil, ecode.StatusInternalServerError.ToRPCErr()
+ }
+
+ userExamples := []*serverNameExampleV1.UserExample{}
+ for _, record := range records {
+ data, err := convertUserExample(record)
+ if err != nil {
+ logger.Warn("convertUserExample error", logger.Err(err), logger.Any("id", record.ID), interceptor.ServerCtxRequestIDField(ctx))
+ continue
+ }
+ userExamples = append(userExamples, data)
+ }
+
+ return &serverNameExampleV1.ListUserExampleByLastIDReply{
+ UserExamples: userExamples,
+ }, nil
+}
+
// List of records by query parameters
func (s *userExample) List(ctx context.Context, req *serverNameExampleV1.ListUserExampleRequest) (*serverNameExampleV1.ListUserExampleReply, error) {
err := req.Validate()
diff --git a/internal/service/userExample_client_test.go b/internal/service/userExample_client_test.go
index 287347f9..c305911f 100644
--- a/internal/service/userExample_client_test.go
+++ b/internal/service/userExample_client_test.go
@@ -128,6 +128,20 @@ func Test_service_userExample_methods(t *testing.T) {
wantErr: false,
},
+ {
+ name: "ListByLastID",
+ fn: func() (interface{}, error) {
+ // todo type in the parameters to test
+ req := &serverNameExampleV1.ListUserExampleByLastIDRequest{
+ LastID: 0,
+ Limit: 5,
+ Sort: "-age",
+ }
+ return cli.ListByLastID(ctx, req)
+ },
+ wantErr: false,
+ },
+
{
name: "List",
fn: func() (interface{}, error) {
@@ -221,6 +235,25 @@ func Test_service_userExample_benchmark(t *testing.T) {
wantErr: false,
},
+ {
+ name: "ListByLastID",
+ fn: func() error {
+ // todo type in the parameters to test
+ message := &serverNameExampleV1.ListUserExampleByLastIDRequest{
+ LastID: 0,
+ Limit: 5,
+ Sort: "-id",
+ }
+ var total uint = 100 // total number of requests
+ b, err := benchmark.New(host, protoFile, "ListByLastID", message, total, importPaths...)
+ if err != nil {
+ return err
+ }
+ return b.Run()
+ },
+ wantErr: false,
+ },
+
{
name: "List",
fn: func() error {
diff --git a/internal/service/userExample_logic.go b/internal/service/userExample_logic.go
index a0e9f8b3..4702745c 100644
--- a/internal/service/userExample_logic.go
+++ b/internal/service/userExample_logic.go
@@ -64,6 +64,12 @@ func (c *userExampleClient) ListByIDs(ctx context.Context, req *serverNameExampl
return c.userExampleCli.ListByIDs(ctx, req)
}
+func (c *userExampleClient) ListByLastID(ctx context.Context, req *serverNameExampleV1.ListUserExampleByLastIDRequest) (*serverNameExampleV1.ListUserExampleByLastIDReply, error) {
+ // implement me
+ // If required, fill in the code to fetch data from other rpc servers here.
+ return c.userExampleCli.ListByLastID(ctx, req)
+}
+
func (c *userExampleClient) List(ctx context.Context, req *serverNameExampleV1.ListUserExampleRequest) (*serverNameExampleV1.ListUserExampleReply, error) {
// implement me
// If required, fill in the code to fetch data from other rpc servers here.
diff --git a/internal/service/userExample_logic_test.go b/internal/service/userExample_logic_test.go
index 40db65af..0e2616cc 100644
--- a/internal/service/userExample_logic_test.go
+++ b/internal/service/userExample_logic_test.go
@@ -62,6 +62,11 @@ func TestNewUserExampleServiceClient(t *testing.T) {
t.Log(reply, err)
cancel()
})
+ utils.SafeRunWithTimeout(time.Second, func(cancel context.CancelFunc) {
+ reply, err := cli.ListByLastID(ctx, nil)
+ t.Log(reply, err)
+ cancel()
+ })
utils.SafeRunWithTimeout(time.Second, func(cancel context.CancelFunc) {
reply, err := cli.List(ctx, nil)
t.Log(reply, err)
diff --git a/internal/service/userExample_test.go b/internal/service/userExample_test.go
index 09626bd4..a42000dd 100644
--- a/internal/service/userExample_test.go
+++ b/internal/service/userExample_test.go
@@ -288,6 +288,33 @@ func Test_userExampleService_List(t *testing.T) {
assert.Error(t, err)
}
+func Test_userExampleService_ListByLastID(t *testing.T) {
+ s := newUserExampleService()
+ defer s.Close()
+ testData := s.TestData.(*model.UserExample)
+
+ rows := sqlmock.NewRows([]string{"id", "created_at", "updated_at"}).
+ AddRow(testData.ID, testData.CreatedAt, testData.UpdatedAt)
+
+ s.MockDao.SQLMock.ExpectQuery("SELECT .*").WillReturnRows(rows)
+
+ reply, err := s.IServiceClient.(serverNameExampleV1.UserExampleClient).ListByLastID(s.Ctx, &serverNameExampleV1.ListUserExampleByLastIDRequest{
+ LastID: 0,
+ Limit: 0,
+ Sort: "",
+ })
+ assert.NoError(t, err)
+ t.Log(reply.String())
+
+ // get error test
+ reply, err = s.IServiceClient.(serverNameExampleV1.UserExampleClient).ListByLastID(s.Ctx, &serverNameExampleV1.ListUserExampleByLastIDRequest{
+ LastID: 0,
+ Limit: 0,
+ Sort: "unknown-column",
+ })
+ assert.Error(t, err)
+}
+
func Test_convertUserExample(t *testing.T) {
testData := &model.UserExample{}
testData.ID = 1
diff --git a/pkg/nacoscli/nacos.go b/pkg/nacoscli/nacos.go
index c47b95c8..0520cf59 100644
--- a/pkg/nacoscli/nacos.go
+++ b/pkg/nacoscli/nacos.go
@@ -88,7 +88,7 @@ func setParams(params *Params, opts ...Option) {
}
}
-// Init get configuration from nacos and parse to struct, use for configuration centre
+// Init get configuration from nacos and parse to struct, use for configuration center
func Init(obj interface{}, params *Params, opts ...Option) error {
err := params.valid()
if err != nil {
diff --git a/pkg/sql2code/parser/template.go b/pkg/sql2code/parser/template.go
index ac62be5a..dc7a6130 100644
--- a/pkg/sql2code/parser/template.go
+++ b/pkg/sql2code/parser/template.go
@@ -116,6 +116,9 @@ service {{.TName}} {
// list of {{.TName}} by batch id
rpc ListByIDs(List{{.TableName}}ByIDsRequest) returns (List{{.TableName}}ByIDsReply) {}
+ // list {{.TName}} by last id
+ rpc ListByLastID(List{{.TableName}}ByLastIDRequest) returns (List{{.TableName}}ByLastIDReply) {}
+
// list of {{.TName}} by query parameters
rpc List(List{{.TableName}}Request) returns (List{{.TableName}}Reply) {}
}
@@ -177,6 +180,16 @@ message List{{.TableName}}ByIDsReply {
repeated {{.TableName}} {{.TName}}s = 1;
}
+message List{{.TableName}}ByLastIDRequest {
+ uint64 lastID = 1; // last id
+ uint32 limit = 2; // page size
+ string sort = 3; // sort by column name of table, default is -id, the - sign indicates descending order.
+}
+
+message List{{.TableName}}ByLastIDReply {
+ repeated {{.TableName}} {{.TName}}s = 1;
+}
+
message List{{.TableName}}Request {
types.Params params = 1;
}
@@ -346,6 +359,23 @@ service {{.TName}} {
};
}
+ // list {{.TName}} by last id
+ rpc ListByLastID(List{{.TableName}}ByLastIDRequest) returns (List{{.TableName}}ByLastIDReply) {
+ option (google.api.http) = {
+ get: "/api/v1/{{.TName}}/list"
+ };
+ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
+ summary: "list of {{.TName}} by last id",
+ description: "list of {{.TName}} by last id",
+ //security: {
+ // security_requirement: {
+ // key: "BearerAuth";
+ // value: {}
+ // }
+ //}
+ };
+ }
+
// list of {{.TName}} by query parameters
rpc List(List{{.TableName}}Request) returns (List{{.TableName}}Reply) {
option (google.api.http) = {
@@ -432,6 +462,16 @@ message List{{.TableName}}ByIDsReply {
repeated {{.TableName}} {{.TName}}s = 1;
}
+message List{{.TableName}}ByLastIDRequest {
+ uint64 lastID = 1 [(tagger.tags) = "form:\"lastID\""]; // last id
+ uint32 limit = 2 [(tagger.tags) = "form:\"limit\""]; // page size
+ string sort = 3 [(tagger.tags) = "form:\"sort\""]; // sort by column name of table, default is -id, the - sign indicates descending order.
+}
+
+message List{{.TableName}}ByLastIDReply {
+ repeated {{.TableName}} {{.TName}}s = 1;
+}
+
message List{{.TableName}}Request {
types.Params params = 1;
}