diff --git a/README.md b/README.md index b8b8f84..62aa923 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Shared public schemas, generated Go types and validation for Weir servers and clients. Requires Go 1.27.1. ```sh -go get github.com/batchstream/weir-protocol@v0.16.0 +go get github.com/batchstream/weir-protocol@v0.17.0 ``` The dependency direction is one-way: Weir and the Go SDK depend on this module. @@ -27,13 +27,19 @@ Mutate request carries one record. Servers aggregate admitted records into database batches; clients send and consume incrementally without collecting a wire batch. The protocol imposes no item or payload-size limit on business calls or individual records; servers may bound the size of one message. Backend -protocols govern accepted documents and commands; gRPC carries one request or -event per message. Native carries a required opaque Document. NativeHead carries -optional opaque metadata and a content type for subsequent body chunks. Request -and metadata bytes are opaque to the public protocol. Their content types select -adapter-owned formats; new adapters need no protobuf fields or schema changes. -Empty request data is permitted. Unknown valid content types are left to the -selected adapter. +protocols govern accepted documents and commands. Native carries a required +opaque Document. NativeHead carries optional opaque metadata and a content type +for subsequent body chunks. Request and metadata bytes are opaque to the public +protocol. Their content types select adapter-owned formats; new adapters need no +protobuf fields or schema changes. Empty request data is permitted. Unknown +valid content types are left to the selected adapter. + +Each gRPC message, `ExecuteRequests` or `ExecuteResponses`, carries one or more +requests or responses in stream order. A peer handles each exactly as if it came +in a message of its own, so a sender packs everything it has ready into one +message instead of paying for a message per record. `ValidateExecuteRequests` +and `ValidateExecuteResponses` check a message's own envelope; its requests and +responses are validated one at a time as they are applied. Each request is validated before execution. A record the server cannot admit, such as one its adapter rejects or one sent while the Store drains, receives its diff --git a/api/protocol/protocol.go b/api/protocol/protocol.go index 2250d52..3ba3601 100644 --- a/api/protocol/protocol.go +++ b/api/protocol/protocol.go @@ -203,6 +203,27 @@ func NativeFailure(started bool, failure *pb.Failure) *pb.NativeEnd { return end } +// ValidateExecuteRequests checks one request message's own envelope: at least +// one request and no unknown fields of its own. Consumers validate and apply +// its requests in order with ValidateExecuteRequest, exactly as if each came in +// a message of its own. +func ValidateExecuteRequests(message *pb.ExecuteRequests) error { + if message == nil || len(message.Requests) == 0 || len(message.ProtoReflect().GetUnknown()) != 0 { + return fmt.Errorf("invalid Execute request message") + } + return nil +} + +// ValidateExecuteResponses checks one response message's own envelope: at +// least one response and no unknown fields of its own. Consumers validate and +// apply its responses in order with ValidateExecuteResponse. +func ValidateExecuteResponses(message *pb.ExecuteResponses) error { + if message == nil || len(message.Responses) == 0 || len(message.ProtoReflect().GetUnknown()) != 0 { + return fmt.Errorf("invalid Execute response message") + } + return nil +} + // ValidateExecuteRequest validates one record or cancel request without // retaining stream state. Callers enforce a fixed Store/kind, consecutive // indexes and cancel requests that name earlier records. diff --git a/api/protocol/protocol_test.go b/api/protocol/protocol_test.go index e175983..69aa017 100644 --- a/api/protocol/protocol_test.go +++ b/api/protocol/protocol_test.go @@ -115,6 +115,39 @@ func TestExecuteTypedEnvelopeAndUnknownFields(t *testing.T) { } } +func TestMessagesCarryAtLeastOneRequestOrResponse(t *testing.T) { + request := &pb.ExecuteRequest{StoreName: "records", CancelIndex: 1} + requests := &pb.ExecuteRequests{Requests: []*pb.ExecuteRequest{request}} + if err := ValidateExecuteRequests(requests); err != nil { + t.Fatal(err) + } + // Requests are validated one at a time as they are applied. + invalid := &pb.ExecuteRequest{} + requests.Requests = append(requests.Requests, invalid) + if err := ValidateExecuteRequests(requests); err != nil { + t.Fatal(err) + } + requests.ProtoReflect().SetUnknown([]byte{0xf8, 0x07, 1}) + empty := &pb.ExecuteRequests{} + for _, message := range []*pb.ExecuteRequests{nil, empty, requests} { + if err := ValidateExecuteRequests(message); err == nil { + t.Fatal("accepted invalid request message", message) + } + } + response := &pb.ExecuteResponse{Index: 1} + responses := &pb.ExecuteResponses{Responses: []*pb.ExecuteResponse{response}} + if err := ValidateExecuteResponses(responses); err != nil { + t.Fatal(err) + } + responses.ProtoReflect().SetUnknown([]byte{0xf8, 0x07, 1}) + emptyResponses := &pb.ExecuteResponses{} + for _, message := range []*pb.ExecuteResponses{nil, emptyResponses, responses} { + if err := ValidateExecuteResponses(message); err == nil { + t.Fatal("accepted invalid response message", message) + } + } +} + func TestCancelRequestCarriesOnlyItsStoreAndIndex(t *testing.T) { request := &pb.ExecuteRequest{StoreName: "records", CancelIndex: 3} if err := ValidateExecuteRequest(request); err != nil { diff --git a/api/weir/v1/contract_test.go b/api/weir/v1/contract_test.go index 8d5754a..aa55a3b 100644 --- a/api/weir/v1/contract_test.go +++ b/api/weir/v1/contract_test.go @@ -55,16 +55,20 @@ func TestPublicStoreContract(t *testing.T) { t.Fatal("public service must expose exactly one Execute RPC") } execute := service.Methods().ByName("Execute") - if execute == nil || execute.Input().FullName() != "weir.v1.ExecuteRequest" || execute.Output().FullName() != "weir.v1.ExecuteResponse" || !execute.IsStreamingClient() || !execute.IsStreamingServer() { + if execute == nil || execute.Input().FullName() != "weir.v1.ExecuteRequests" || execute.Output().FullName() != "weir.v1.ExecuteResponses" || !execute.IsStreamingClient() || !execute.IsStreamingServer() { t.Fatal("Execute bidirectional contract changed", execute) } if StoreService_Execute_FullMethodName != "/weir.v1.StoreService/Execute" { t.Fatal("generated public method path changed") } + requests := []fieldContract{{name: "requests", kind: protoreflect.MessageKind, message: "weir.v1.ExecuteRequest", repeated: true}} + assertFields(t, execute.Input(), requests) + responses := []fieldContract{{name: "responses", kind: protoreflect.MessageKind, message: "weir.v1.ExecuteResponse", repeated: true}} + assertFields(t, execute.Output(), responses) executeRequest := []fieldContract{{name: "store_name", kind: protoreflect.StringKind}, {name: "index", kind: protoreflect.Uint64Kind}, {name: "command", kind: protoreflect.MessageKind, message: "weir.v1.Command"}, {name: "timeout_micros", kind: protoreflect.Uint64Kind}, {name: "cancel_index", kind: protoreflect.Uint64Kind}} - assertFields(t, execute.Input(), executeRequest) + assertFields(t, execute.Input().Fields().ByName("requests").Message(), executeRequest) executeResponse := []fieldContract{{name: "index", kind: protoreflect.Uint64Kind}, {name: "event", kind: protoreflect.MessageKind, message: "weir.v1.Event"}} - assertFields(t, execute.Output(), executeResponse) + assertFields(t, execute.Output().Fields().ByName("responses").Message(), executeResponse) } func TestPublicCommandAndEventContract(t *testing.T) { @@ -143,6 +147,15 @@ func TestIndexedExecutionWireEncoding(t *testing.T) { if !bytes.Equal(encoded, wantRequest) { t.Fatal("indexed execution wire changed", encoded) } + requests := &ExecuteRequests{Requests: []*ExecuteRequest{request, request}} + encoded, err = proto.Marshal(requests) + if err != nil { + t.Fatal(err) + } + packedRequest := append([]byte{0x0a, byte(len(wantRequest))}, wantRequest...) + if !bytes.Equal(encoded, append(packedRequest, packedRequest...)) { + t.Fatal("packed execution wire changed", encoded) + } empty := &Empty{} missing := &ReadResult_Missing{Missing: empty} result := &ReadResult{Result: missing} @@ -157,4 +170,12 @@ func TestIndexedExecutionWireEncoding(t *testing.T) { if !bytes.Equal(encoded, wantResponse) { t.Fatal("indexed per-record result wire changed", encoded) } + responses := &ExecuteResponses{Responses: []*ExecuteResponse{response}} + encoded, err = proto.Marshal(responses) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(encoded, append([]byte{0x0a, byte(len(wantResponse))}, wantResponse...)) { + t.Fatal("packed per-record result wire changed", encoded) + } } diff --git a/api/weir/v1/store.pb.go b/api/weir/v1/store.pb.go index 018038f..207940c 100644 --- a/api/weir/v1/store.pb.go +++ b/api/weir/v1/store.pb.go @@ -287,6 +287,98 @@ func (NativeCompletion) EnumDescriptor() ([]byte, []int) { return file_api_weir_v1_store_proto_rawDescGZIP(), []int{3} } +// ExecuteRequests carries requests of one stream in order. +type ExecuteRequests struct { + state protoimpl.MessageState `protogen:"open.v1"` + // One or more requests, in stream order. + Requests []*ExecuteRequest `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExecuteRequests) Reset() { + *x = ExecuteRequests{} + mi := &file_api_weir_v1_store_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExecuteRequests) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteRequests) ProtoMessage() {} + +func (x *ExecuteRequests) ProtoReflect() protoreflect.Message { + mi := &file_api_weir_v1_store_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteRequests.ProtoReflect.Descriptor instead. +func (*ExecuteRequests) Descriptor() ([]byte, []int) { + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{0} +} + +func (x *ExecuteRequests) GetRequests() []*ExecuteRequest { + if x != nil { + return x.Requests + } + return nil +} + +// ExecuteResponses carries responses of one stream in order. +type ExecuteResponses struct { + state protoimpl.MessageState `protogen:"open.v1"` + // One or more responses, in stream order. + Responses []*ExecuteResponse `protobuf:"bytes,1,rep,name=responses,proto3" json:"responses,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExecuteResponses) Reset() { + *x = ExecuteResponses{} + mi := &file_api_weir_v1_store_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExecuteResponses) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteResponses) ProtoMessage() {} + +func (x *ExecuteResponses) ProtoReflect() protoreflect.Message { + mi := &file_api_weir_v1_store_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteResponses.ProtoReflect.Descriptor instead. +func (*ExecuteResponses) Descriptor() ([]byte, []int) { + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{1} +} + +func (x *ExecuteResponses) GetResponses() []*ExecuteResponse { + if x != nil { + return x.Responses + } + return nil +} + // ExecuteRequest carries one operation with its Store and index, or cancels an // earlier record of the stream. type ExecuteRequest struct { @@ -323,7 +415,7 @@ type ExecuteRequest struct { func (x *ExecuteRequest) Reset() { *x = ExecuteRequest{} - mi := &file_api_weir_v1_store_proto_msgTypes[0] + mi := &file_api_weir_v1_store_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -335,7 +427,7 @@ func (x *ExecuteRequest) String() string { func (*ExecuteRequest) ProtoMessage() {} func (x *ExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[0] + mi := &file_api_weir_v1_store_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -348,7 +440,7 @@ func (x *ExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteRequest.ProtoReflect.Descriptor instead. func (*ExecuteRequest) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{0} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{2} } func (x *ExecuteRequest) GetStoreName() string { @@ -401,7 +493,7 @@ type ExecuteResponse struct { func (x *ExecuteResponse) Reset() { *x = ExecuteResponse{} - mi := &file_api_weir_v1_store_proto_msgTypes[1] + mi := &file_api_weir_v1_store_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -413,7 +505,7 @@ func (x *ExecuteResponse) String() string { func (*ExecuteResponse) ProtoMessage() {} func (x *ExecuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[1] + mi := &file_api_weir_v1_store_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -426,7 +518,7 @@ func (x *ExecuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteResponse.ProtoReflect.Descriptor instead. func (*ExecuteResponse) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{1} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{3} } func (x *ExecuteResponse) GetIndex() uint64 { @@ -460,7 +552,7 @@ type Command struct { func (x *Command) Reset() { *x = Command{} - mi := &file_api_weir_v1_store_proto_msgTypes[2] + mi := &file_api_weir_v1_store_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -472,7 +564,7 @@ func (x *Command) String() string { func (*Command) ProtoMessage() {} func (x *Command) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[2] + mi := &file_api_weir_v1_store_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -485,7 +577,7 @@ func (x *Command) ProtoReflect() protoreflect.Message { // Deprecated: Use Command.ProtoReflect.Descriptor instead. func (*Command) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{2} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{4} } func (x *Command) GetOperation() isCommand_Operation { @@ -563,7 +655,7 @@ type NativeRequest struct { func (x *NativeRequest) Reset() { *x = NativeRequest{} - mi := &file_api_weir_v1_store_proto_msgTypes[3] + mi := &file_api_weir_v1_store_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -575,7 +667,7 @@ func (x *NativeRequest) String() string { func (*NativeRequest) ProtoMessage() {} func (x *NativeRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[3] + mi := &file_api_weir_v1_store_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -588,7 +680,7 @@ func (x *NativeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NativeRequest.ProtoReflect.Descriptor instead. func (*NativeRequest) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{3} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{5} } func (x *NativeRequest) GetResource() string { @@ -624,7 +716,7 @@ type Event struct { func (x *Event) Reset() { *x = Event{} - mi := &file_api_weir_v1_store_proto_msgTypes[4] + mi := &file_api_weir_v1_store_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -636,7 +728,7 @@ func (x *Event) String() string { func (*Event) ProtoMessage() {} func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[4] + mi := &file_api_weir_v1_store_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -649,7 +741,7 @@ func (x *Event) ProtoReflect() protoreflect.Message { // Deprecated: Use Event.ProtoReflect.Descriptor instead. func (*Event) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{4} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{6} } func (x *Event) GetValue() isEvent_Value { @@ -752,7 +844,7 @@ type Empty struct { func (x *Empty) Reset() { *x = Empty{} - mi := &file_api_weir_v1_store_proto_msgTypes[5] + mi := &file_api_weir_v1_store_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -764,7 +856,7 @@ func (x *Empty) String() string { func (*Empty) ProtoMessage() {} func (x *Empty) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[5] + mi := &file_api_weir_v1_store_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -777,7 +869,7 @@ func (x *Empty) ProtoReflect() protoreflect.Message { // Deprecated: Use Empty.ProtoReflect.Descriptor instead. func (*Empty) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{5} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{7} } // Document binds opaque bytes to an explicit content type; adapters own their format. @@ -793,7 +885,7 @@ type Document struct { func (x *Document) Reset() { *x = Document{} - mi := &file_api_weir_v1_store_proto_msgTypes[6] + mi := &file_api_weir_v1_store_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -805,7 +897,7 @@ func (x *Document) String() string { func (*Document) ProtoMessage() {} func (x *Document) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[6] + mi := &file_api_weir_v1_store_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -818,7 +910,7 @@ func (x *Document) ProtoReflect() protoreflect.Message { // Deprecated: Use Document.ProtoReflect.Descriptor instead. func (*Document) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{6} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{8} } func (x *Document) GetContentType() string { @@ -848,7 +940,7 @@ type Failure struct { func (x *Failure) Reset() { *x = Failure{} - mi := &file_api_weir_v1_store_proto_msgTypes[7] + mi := &file_api_weir_v1_store_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -860,7 +952,7 @@ func (x *Failure) String() string { func (*Failure) ProtoMessage() {} func (x *Failure) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[7] + mi := &file_api_weir_v1_store_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -873,7 +965,7 @@ func (x *Failure) ProtoReflect() protoreflect.Message { // Deprecated: Use Failure.ProtoReflect.Descriptor instead. func (*Failure) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{7} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{9} } func (x *Failure) GetCode() FailureCode { @@ -901,7 +993,7 @@ type ReadRequest struct { func (x *ReadRequest) Reset() { *x = ReadRequest{} - mi := &file_api_weir_v1_store_proto_msgTypes[8] + mi := &file_api_weir_v1_store_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -913,7 +1005,7 @@ func (x *ReadRequest) String() string { func (*ReadRequest) ProtoMessage() {} func (x *ReadRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[8] + mi := &file_api_weir_v1_store_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -926,7 +1018,7 @@ func (x *ReadRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadRequest.ProtoReflect.Descriptor instead. func (*ReadRequest) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{8} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{10} } func (x *ReadRequest) GetResource() string { @@ -953,7 +1045,7 @@ type ReadResult struct { func (x *ReadResult) Reset() { *x = ReadResult{} - mi := &file_api_weir_v1_store_proto_msgTypes[9] + mi := &file_api_weir_v1_store_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -965,7 +1057,7 @@ func (x *ReadResult) String() string { func (*ReadResult) ProtoMessage() {} func (x *ReadResult) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[9] + mi := &file_api_weir_v1_store_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -978,7 +1070,7 @@ func (x *ReadResult) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadResult.ProtoReflect.Descriptor instead. func (*ReadResult) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{9} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{11} } func (x *ReadResult) GetResult() isReadResult_Result { @@ -1055,7 +1147,7 @@ type MutationOptions struct { func (x *MutationOptions) Reset() { *x = MutationOptions{} - mi := &file_api_weir_v1_store_proto_msgTypes[10] + mi := &file_api_weir_v1_store_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1067,7 +1159,7 @@ func (x *MutationOptions) String() string { func (*MutationOptions) ProtoMessage() {} func (x *MutationOptions) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[10] + mi := &file_api_weir_v1_store_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1080,7 +1172,7 @@ func (x *MutationOptions) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationOptions.ProtoReflect.Descriptor instead. func (*MutationOptions) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{10} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{12} } func (x *MutationOptions) GetVisibility() MutationVisibility { @@ -1114,7 +1206,7 @@ type MutateRequest struct { func (x *MutateRequest) Reset() { *x = MutateRequest{} - mi := &file_api_weir_v1_store_proto_msgTypes[11] + mi := &file_api_weir_v1_store_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1126,7 +1218,7 @@ func (x *MutateRequest) String() string { func (*MutateRequest) ProtoMessage() {} func (x *MutateRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[11] + mi := &file_api_weir_v1_store_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1139,7 +1231,7 @@ func (x *MutateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutateRequest.ProtoReflect.Descriptor instead. func (*MutateRequest) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{11} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{13} } func (x *MutateRequest) GetResource() string { @@ -1260,7 +1352,7 @@ type MutationResult struct { func (x *MutationResult) Reset() { *x = MutationResult{} - mi := &file_api_weir_v1_store_proto_msgTypes[12] + mi := &file_api_weir_v1_store_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1272,7 +1364,7 @@ func (x *MutationResult) String() string { func (*MutationResult) ProtoMessage() {} func (x *MutationResult) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[12] + mi := &file_api_weir_v1_store_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1285,7 +1377,7 @@ func (x *MutationResult) ProtoReflect() protoreflect.Message { // Deprecated: Use MutationResult.ProtoReflect.Descriptor instead. func (*MutationResult) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{12} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{14} } func (x *MutationResult) GetOutcome() MutationOutcome { @@ -1318,7 +1410,7 @@ type Transform struct { func (x *Transform) Reset() { *x = Transform{} - mi := &file_api_weir_v1_store_proto_msgTypes[13] + mi := &file_api_weir_v1_store_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1330,7 +1422,7 @@ func (x *Transform) String() string { func (*Transform) ProtoMessage() {} func (x *Transform) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[13] + mi := &file_api_weir_v1_store_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1343,7 +1435,7 @@ func (x *Transform) ProtoReflect() protoreflect.Message { // Deprecated: Use Transform.ProtoReflect.Descriptor instead. func (*Transform) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{13} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{15} } func (x *Transform) GetForm() isTransform_Form { @@ -1411,7 +1503,7 @@ type LuaTransform struct { func (x *LuaTransform) Reset() { *x = LuaTransform{} - mi := &file_api_weir_v1_store_proto_msgTypes[14] + mi := &file_api_weir_v1_store_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1423,7 +1515,7 @@ func (x *LuaTransform) String() string { func (*LuaTransform) ProtoMessage() {} func (x *LuaTransform) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[14] + mi := &file_api_weir_v1_store_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1436,7 +1528,7 @@ func (x *LuaTransform) ProtoReflect() protoreflect.Message { // Deprecated: Use LuaTransform.ProtoReflect.Descriptor instead. func (*LuaTransform) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{14} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{16} } func (x *LuaTransform) GetSource() []byte { @@ -1467,7 +1559,7 @@ type NativeHead struct { func (x *NativeHead) Reset() { *x = NativeHead{} - mi := &file_api_weir_v1_store_proto_msgTypes[15] + mi := &file_api_weir_v1_store_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1479,7 +1571,7 @@ func (x *NativeHead) String() string { func (*NativeHead) ProtoMessage() {} func (x *NativeHead) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[15] + mi := &file_api_weir_v1_store_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1492,7 +1584,7 @@ func (x *NativeHead) ProtoReflect() protoreflect.Message { // Deprecated: Use NativeHead.ProtoReflect.Descriptor instead. func (*NativeHead) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{15} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{17} } func (x *NativeHead) GetMetadata() *Document { @@ -1522,7 +1614,7 @@ type NativeEnd struct { func (x *NativeEnd) Reset() { *x = NativeEnd{} - mi := &file_api_weir_v1_store_proto_msgTypes[16] + mi := &file_api_weir_v1_store_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1534,7 +1626,7 @@ func (x *NativeEnd) String() string { func (*NativeEnd) ProtoMessage() {} func (x *NativeEnd) ProtoReflect() protoreflect.Message { - mi := &file_api_weir_v1_store_proto_msgTypes[16] + mi := &file_api_weir_v1_store_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1547,7 +1639,7 @@ func (x *NativeEnd) ProtoReflect() protoreflect.Message { // Deprecated: Use NativeEnd.ProtoReflect.Descriptor instead. func (*NativeEnd) Descriptor() ([]byte, []int) { - return file_api_weir_v1_store_proto_rawDescGZIP(), []int{16} + return file_api_weir_v1_store_proto_rawDescGZIP(), []int{18} } func (x *NativeEnd) GetCompletion() NativeCompletion { @@ -1568,7 +1660,11 @@ var File_api_weir_v1_store_proto protoreflect.FileDescriptor const file_api_weir_v1_store_proto_rawDesc = "" + "\n" + - "\x17api/weir/v1/store.proto\x12\aweir.v1\"\xbb\x01\n" + + "\x17api/weir/v1/store.proto\x12\aweir.v1\"F\n" + + "\x0fExecuteRequests\x123\n" + + "\brequests\x18\x01 \x03(\v2\x17.weir.v1.ExecuteRequestR\brequests\"J\n" + + "\x10ExecuteResponses\x126\n" + + "\tresponses\x18\x01 \x03(\v2\x18.weir.v1.ExecuteResponseR\tresponses\"\xbb\x01\n" + "\x0eExecuteRequest\x12\x1d\n" + "\n" + "store_name\x18\x01 \x01(\tR\tstoreName\x12\x14\n" + @@ -1671,9 +1767,9 @@ const file_api_weir_v1_store_proto_rawDesc = "" + "\x1dNATIVE_COMPLETION_UNSPECIFIED\x10\x00\x12\x16\n" + "\x12NATIVE_NOT_STARTED\x10\x01\x12\x15\n" + "\x11RESPONSE_COMPLETE\x10\x02\x12\x17\n" + - "\x13RESPONSE_INCOMPLETE\x10\x032P\n" + - "\fStoreService\x12@\n" + - "\aExecute\x12\x17.weir.v1.ExecuteRequest\x1a\x18.weir.v1.ExecuteResponse(\x010\x01B9Z7github.com/batchstream/weir-protocol/api/weir/v1;weirv1b\x06proto3" + "\x13RESPONSE_INCOMPLETE\x10\x032R\n" + + "\fStoreService\x12B\n" + + "\aExecute\x12\x18.weir.v1.ExecuteRequests\x1a\x19.weir.v1.ExecuteResponses(\x010\x01B9Z7github.com/batchstream/weir-protocol/api/weir/v1;weirv1b\x06proto3" var ( file_api_weir_v1_store_proto_rawDescOnce sync.Once @@ -1688,67 +1784,71 @@ func file_api_weir_v1_store_proto_rawDescGZIP() []byte { } var file_api_weir_v1_store_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_api_weir_v1_store_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_api_weir_v1_store_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_api_weir_v1_store_proto_goTypes = []any{ - (FailureCode)(0), // 0: weir.v1.FailureCode - (MutationOutcome)(0), // 1: weir.v1.MutationOutcome - (MutationVisibility)(0), // 2: weir.v1.MutationVisibility - (NativeCompletion)(0), // 3: weir.v1.NativeCompletion - (*ExecuteRequest)(nil), // 4: weir.v1.ExecuteRequest - (*ExecuteResponse)(nil), // 5: weir.v1.ExecuteResponse - (*Command)(nil), // 6: weir.v1.Command - (*NativeRequest)(nil), // 7: weir.v1.NativeRequest - (*Event)(nil), // 8: weir.v1.Event - (*Empty)(nil), // 9: weir.v1.Empty - (*Document)(nil), // 10: weir.v1.Document - (*Failure)(nil), // 11: weir.v1.Failure - (*ReadRequest)(nil), // 12: weir.v1.ReadRequest - (*ReadResult)(nil), // 13: weir.v1.ReadResult - (*MutationOptions)(nil), // 14: weir.v1.MutationOptions - (*MutateRequest)(nil), // 15: weir.v1.MutateRequest - (*MutationResult)(nil), // 16: weir.v1.MutationResult - (*Transform)(nil), // 17: weir.v1.Transform - (*LuaTransform)(nil), // 18: weir.v1.LuaTransform - (*NativeHead)(nil), // 19: weir.v1.NativeHead - (*NativeEnd)(nil), // 20: weir.v1.NativeEnd + (FailureCode)(0), // 0: weir.v1.FailureCode + (MutationOutcome)(0), // 1: weir.v1.MutationOutcome + (MutationVisibility)(0), // 2: weir.v1.MutationVisibility + (NativeCompletion)(0), // 3: weir.v1.NativeCompletion + (*ExecuteRequests)(nil), // 4: weir.v1.ExecuteRequests + (*ExecuteResponses)(nil), // 5: weir.v1.ExecuteResponses + (*ExecuteRequest)(nil), // 6: weir.v1.ExecuteRequest + (*ExecuteResponse)(nil), // 7: weir.v1.ExecuteResponse + (*Command)(nil), // 8: weir.v1.Command + (*NativeRequest)(nil), // 9: weir.v1.NativeRequest + (*Event)(nil), // 10: weir.v1.Event + (*Empty)(nil), // 11: weir.v1.Empty + (*Document)(nil), // 12: weir.v1.Document + (*Failure)(nil), // 13: weir.v1.Failure + (*ReadRequest)(nil), // 14: weir.v1.ReadRequest + (*ReadResult)(nil), // 15: weir.v1.ReadResult + (*MutationOptions)(nil), // 16: weir.v1.MutationOptions + (*MutateRequest)(nil), // 17: weir.v1.MutateRequest + (*MutationResult)(nil), // 18: weir.v1.MutationResult + (*Transform)(nil), // 19: weir.v1.Transform + (*LuaTransform)(nil), // 20: weir.v1.LuaTransform + (*NativeHead)(nil), // 21: weir.v1.NativeHead + (*NativeEnd)(nil), // 22: weir.v1.NativeEnd } var file_api_weir_v1_store_proto_depIdxs = []int32{ - 6, // 0: weir.v1.ExecuteRequest.command:type_name -> weir.v1.Command - 8, // 1: weir.v1.ExecuteResponse.event:type_name -> weir.v1.Event - 12, // 2: weir.v1.Command.read:type_name -> weir.v1.ReadRequest - 15, // 3: weir.v1.Command.mutate:type_name -> weir.v1.MutateRequest - 7, // 4: weir.v1.Command.native:type_name -> weir.v1.NativeRequest - 10, // 5: weir.v1.NativeRequest.request:type_name -> weir.v1.Document - 13, // 6: weir.v1.Event.read_result:type_name -> weir.v1.ReadResult - 16, // 7: weir.v1.Event.mutation_result:type_name -> weir.v1.MutationResult - 19, // 8: weir.v1.Event.head:type_name -> weir.v1.NativeHead - 20, // 9: weir.v1.Event.native_end:type_name -> weir.v1.NativeEnd - 0, // 10: weir.v1.Failure.code:type_name -> weir.v1.FailureCode - 10, // 11: weir.v1.ReadResult.document:type_name -> weir.v1.Document - 9, // 12: weir.v1.ReadResult.missing:type_name -> weir.v1.Empty - 11, // 13: weir.v1.ReadResult.failure:type_name -> weir.v1.Failure - 2, // 14: weir.v1.MutationOptions.visibility:type_name -> weir.v1.MutationVisibility - 10, // 15: weir.v1.MutateRequest.put:type_name -> weir.v1.Document - 10, // 16: weir.v1.MutateRequest.create:type_name -> weir.v1.Document - 10, // 17: weir.v1.MutateRequest.replace:type_name -> weir.v1.Document - 9, // 18: weir.v1.MutateRequest.delete:type_name -> weir.v1.Empty - 17, // 19: weir.v1.MutateRequest.atomic_transform:type_name -> weir.v1.Transform - 14, // 20: weir.v1.MutateRequest.options:type_name -> weir.v1.MutationOptions - 1, // 21: weir.v1.MutationResult.outcome:type_name -> weir.v1.MutationOutcome - 11, // 22: weir.v1.MutationResult.failure:type_name -> weir.v1.Failure - 18, // 23: weir.v1.Transform.lua:type_name -> weir.v1.LuaTransform - 10, // 24: weir.v1.Transform.backend_expression:type_name -> weir.v1.Document - 10, // 25: weir.v1.LuaTransform.input:type_name -> weir.v1.Document - 10, // 26: weir.v1.NativeHead.metadata:type_name -> weir.v1.Document - 3, // 27: weir.v1.NativeEnd.completion:type_name -> weir.v1.NativeCompletion - 11, // 28: weir.v1.NativeEnd.failure:type_name -> weir.v1.Failure - 4, // 29: weir.v1.StoreService.Execute:input_type -> weir.v1.ExecuteRequest - 5, // 30: weir.v1.StoreService.Execute:output_type -> weir.v1.ExecuteResponse - 30, // [30:31] is the sub-list for method output_type - 29, // [29:30] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 6, // 0: weir.v1.ExecuteRequests.requests:type_name -> weir.v1.ExecuteRequest + 7, // 1: weir.v1.ExecuteResponses.responses:type_name -> weir.v1.ExecuteResponse + 8, // 2: weir.v1.ExecuteRequest.command:type_name -> weir.v1.Command + 10, // 3: weir.v1.ExecuteResponse.event:type_name -> weir.v1.Event + 14, // 4: weir.v1.Command.read:type_name -> weir.v1.ReadRequest + 17, // 5: weir.v1.Command.mutate:type_name -> weir.v1.MutateRequest + 9, // 6: weir.v1.Command.native:type_name -> weir.v1.NativeRequest + 12, // 7: weir.v1.NativeRequest.request:type_name -> weir.v1.Document + 15, // 8: weir.v1.Event.read_result:type_name -> weir.v1.ReadResult + 18, // 9: weir.v1.Event.mutation_result:type_name -> weir.v1.MutationResult + 21, // 10: weir.v1.Event.head:type_name -> weir.v1.NativeHead + 22, // 11: weir.v1.Event.native_end:type_name -> weir.v1.NativeEnd + 0, // 12: weir.v1.Failure.code:type_name -> weir.v1.FailureCode + 12, // 13: weir.v1.ReadResult.document:type_name -> weir.v1.Document + 11, // 14: weir.v1.ReadResult.missing:type_name -> weir.v1.Empty + 13, // 15: weir.v1.ReadResult.failure:type_name -> weir.v1.Failure + 2, // 16: weir.v1.MutationOptions.visibility:type_name -> weir.v1.MutationVisibility + 12, // 17: weir.v1.MutateRequest.put:type_name -> weir.v1.Document + 12, // 18: weir.v1.MutateRequest.create:type_name -> weir.v1.Document + 12, // 19: weir.v1.MutateRequest.replace:type_name -> weir.v1.Document + 11, // 20: weir.v1.MutateRequest.delete:type_name -> weir.v1.Empty + 19, // 21: weir.v1.MutateRequest.atomic_transform:type_name -> weir.v1.Transform + 16, // 22: weir.v1.MutateRequest.options:type_name -> weir.v1.MutationOptions + 1, // 23: weir.v1.MutationResult.outcome:type_name -> weir.v1.MutationOutcome + 13, // 24: weir.v1.MutationResult.failure:type_name -> weir.v1.Failure + 20, // 25: weir.v1.Transform.lua:type_name -> weir.v1.LuaTransform + 12, // 26: weir.v1.Transform.backend_expression:type_name -> weir.v1.Document + 12, // 27: weir.v1.LuaTransform.input:type_name -> weir.v1.Document + 12, // 28: weir.v1.NativeHead.metadata:type_name -> weir.v1.Document + 3, // 29: weir.v1.NativeEnd.completion:type_name -> weir.v1.NativeCompletion + 13, // 30: weir.v1.NativeEnd.failure:type_name -> weir.v1.Failure + 4, // 31: weir.v1.StoreService.Execute:input_type -> weir.v1.ExecuteRequests + 5, // 32: weir.v1.StoreService.Execute:output_type -> weir.v1.ExecuteResponses + 32, // [32:33] is the sub-list for method output_type + 31, // [31:32] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_api_weir_v1_store_proto_init() } @@ -1756,31 +1856,31 @@ func file_api_weir_v1_store_proto_init() { if File_api_weir_v1_store_proto != nil { return } - file_api_weir_v1_store_proto_msgTypes[2].OneofWrappers = []any{ + file_api_weir_v1_store_proto_msgTypes[4].OneofWrappers = []any{ (*Command_Read)(nil), (*Command_Mutate)(nil), (*Command_Native)(nil), } - file_api_weir_v1_store_proto_msgTypes[4].OneofWrappers = []any{ + file_api_weir_v1_store_proto_msgTypes[6].OneofWrappers = []any{ (*Event_ReadResult)(nil), (*Event_MutationResult)(nil), (*Event_Head)(nil), (*Event_Chunk)(nil), (*Event_NativeEnd)(nil), } - file_api_weir_v1_store_proto_msgTypes[9].OneofWrappers = []any{ + file_api_weir_v1_store_proto_msgTypes[11].OneofWrappers = []any{ (*ReadResult_Document)(nil), (*ReadResult_Missing)(nil), (*ReadResult_Failure)(nil), } - file_api_weir_v1_store_proto_msgTypes[11].OneofWrappers = []any{ + file_api_weir_v1_store_proto_msgTypes[13].OneofWrappers = []any{ (*MutateRequest_Put)(nil), (*MutateRequest_Create)(nil), (*MutateRequest_Replace)(nil), (*MutateRequest_Delete)(nil), (*MutateRequest_AtomicTransform)(nil), } - file_api_weir_v1_store_proto_msgTypes[13].OneofWrappers = []any{ + file_api_weir_v1_store_proto_msgTypes[15].OneofWrappers = []any{ (*Transform_Lua)(nil), (*Transform_BackendExpression)(nil), } @@ -1791,7 +1891,7 @@ func file_api_weir_v1_store_proto_init() { GoPackagePath: reflect.TypeOf(packageMarker).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_weir_v1_store_proto_rawDesc), len(file_api_weir_v1_store_proto_rawDesc)), NumEnums: 4, - NumMessages: 17, + NumMessages: 19, NumExtensions: 0, NumServices: 1, }, diff --git a/api/weir/v1/store.proto b/api/weir/v1/store.proto index 22ea313..202db2f 100644 --- a/api/weir/v1/store.proto +++ b/api/weir/v1/store.proto @@ -11,6 +11,9 @@ option go_package = "github.com/batchstream/weir-protocol/api/weir/v1;weirv1"; // A server that does not host the Store fails the RPC with NOT_FOUND. service StoreService { // Execute accepts requests and emits indexed results incrementally. + // Each message carries one or more requests or responses in order. A peer + // handles each exactly as if it came in a message of its own, so a sender + // can pack everything it has ready into one message. // A stream selects one Store and operation kind. Each Read or Mutate request // carries one record with a consecutive one-based index and receives at most // one result, in completion order; consumers match results by index. A @@ -31,7 +34,19 @@ service StoreService { // Never automatically replay mutations without individual application evidence. // Native accepts exactly one request with index 1 followed by half-close and // streams opaque response metadata, body chunks, and transport completion. - rpc Execute(stream ExecuteRequest) returns (stream ExecuteResponse); + rpc Execute(stream ExecuteRequests) returns (stream ExecuteResponses); +} + +// ExecuteRequests carries requests of one stream in order. +message ExecuteRequests { + // One or more requests, in stream order. + repeated ExecuteRequest requests = 1; +} + +// ExecuteResponses carries responses of one stream in order. +message ExecuteResponses { + // One or more responses, in stream order. + repeated ExecuteResponse responses = 1; } // ExecuteRequest carries one operation with its Store and index, or cancels an diff --git a/api/weir/v1/store_grpc.pb.go b/api/weir/v1/store_grpc.pb.go index 0c54a6e..58a2050 100644 --- a/api/weir/v1/store_grpc.pb.go +++ b/api/weir/v1/store_grpc.pb.go @@ -28,6 +28,9 @@ const ( // A server that does not host the Store fails the RPC with NOT_FOUND. type StoreServiceClient interface { // Execute accepts requests and emits indexed results incrementally. + // Each message carries one or more requests or responses in order. A peer + // handles each exactly as if it came in a message of its own, so a sender + // can pack everything it has ready into one message. // A stream selects one Store and operation kind. Each Read or Mutate request // carries one record with a consecutive one-based index and receives at most // one result, in completion order; consumers match results by index. A @@ -48,7 +51,7 @@ type StoreServiceClient interface { // Never automatically replay mutations without individual application evidence. // Native accepts exactly one request with index 1 followed by half-close and // streams opaque response metadata, body chunks, and transport completion. - Execute(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ExecuteRequest, ExecuteResponse], error) + Execute(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ExecuteRequests, ExecuteResponses], error) } type storeServiceClient struct { @@ -60,13 +63,13 @@ func NewStoreServiceClient(cc grpc.ClientConnInterface) StoreServiceClient { return client } -func (c *storeServiceClient) Execute(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ExecuteRequest, ExecuteResponse], error) { +func (c *storeServiceClient) Execute(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ExecuteRequests, ExecuteResponses], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &StoreService_ServiceDesc.Streams[0], StoreService_Execute_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &grpc.GenericClientStream[ExecuteRequest, ExecuteResponse]{ClientStream: stream} + x := &grpc.GenericClientStream[ExecuteRequests, ExecuteResponses]{ClientStream: stream} return x, nil } @@ -76,6 +79,9 @@ func (c *storeServiceClient) Execute(ctx context.Context, opts ...grpc.CallOptio // A server that does not host the Store fails the RPC with NOT_FOUND. type StoreServiceServer interface { // Execute accepts requests and emits indexed results incrementally. + // Each message carries one or more requests or responses in order. A peer + // handles each exactly as if it came in a message of its own, so a sender + // can pack everything it has ready into one message. // A stream selects one Store and operation kind. Each Read or Mutate request // carries one record with a consecutive one-based index and receives at most // one result, in completion order; consumers match results by index. A @@ -96,14 +102,14 @@ type StoreServiceServer interface { // Never automatically replay mutations without individual application evidence. // Native accepts exactly one request with index 1 followed by half-close and // streams opaque response metadata, body chunks, and transport completion. - Execute(grpc.BidiStreamingServer[ExecuteRequest, ExecuteResponse]) error + Execute(grpc.BidiStreamingServer[ExecuteRequests, ExecuteResponses]) error } func RegisterStoreServiceServer(s grpc.ServiceRegistrar, srv StoreServiceServer) { s.RegisterService(&StoreService_ServiceDesc, srv) } func _StoreService_Execute_Handler(srv interface{}, stream grpc.ServerStream) error { - serverStream := &grpc.GenericServerStream[ExecuteRequest, ExecuteResponse]{ServerStream: stream} + serverStream := &grpc.GenericServerStream[ExecuteRequests, ExecuteResponses]{ServerStream: stream} return srv.(StoreServiceServer).Execute(serverStream) } diff --git a/scripts/generate.sh b/scripts/generate.sh index 135e792..75ac6f3 100755 --- a/scripts/generate.sh +++ b/scripts/generate.sh @@ -39,7 +39,7 @@ awk ' print "\tclient := &storeServiceClient{cc}"; print "\treturn client"; count++; next } index($0,"\treturn srv.(StoreServiceServer).Execute(&grpc.GenericServerStream") == 1 { - print "\tserverStream := &grpc.GenericServerStream[ExecuteRequest, ExecuteResponse]{ServerStream: stream}" + print "\tserverStream := &grpc.GenericServerStream[ExecuteRequests, ExecuteResponses]{ServerStream: stream}" print "\treturn srv.(StoreServiceServer).Execute(serverStream)"; count++; next } { print }