starpc 0.49.18 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -3
- package/cmd/protoc-gen-es-starpc/typescript.ts +11 -6
- package/dist/cmd/protoc-gen-es-starpc/typescript.js +6 -5
- package/dist/echo/echo.pb.d.ts +1 -1
- package/dist/echo/echo.pb.js +3 -3
- package/dist/integration/cross-language/ts-client.js +84 -11
- package/dist/integration/cross-language/ts-server.js +100 -4
- package/dist/mock/index.d.ts +2 -2
- package/dist/mock/index.js +2 -2
- package/dist/mock/mock.pb.d.ts +1 -1
- package/dist/mock/mock.pb.js +3 -3
- package/dist/rpcstream/receipt.test.d.ts +1 -0
- package/dist/rpcstream/receipt.test.js +41 -0
- package/dist/rpcstream/rpcstream.pb.d.ts +1 -1
- package/dist/rpcstream/rpcstream.pb.js +14 -8
- package/dist/srpc/call-receipt.d.ts +17 -0
- package/dist/srpc/call-receipt.js +106 -0
- package/dist/srpc/call-receipt.test.d.ts +1 -0
- package/dist/srpc/call-receipt.test.js +375 -0
- package/dist/srpc/client.d.ts +3 -1
- package/dist/srpc/client.js +20 -0
- package/dist/srpc/common-rpc.d.ts +13 -3
- package/dist/srpc/common-rpc.js +87 -10
- package/dist/srpc/handler.d.ts +2 -1
- package/dist/srpc/index.d.ts +4 -0
- package/dist/srpc/index.js +3 -0
- package/dist/srpc/invoker.d.ts +2 -1
- package/dist/srpc/invoker.js +2 -2
- package/dist/srpc/rpcproto.pb.d.ts +45 -1
- package/dist/srpc/rpcproto.pb.js +60 -7
- package/dist/srpc/server-invocation.d.ts +17 -0
- package/dist/srpc/server-invocation.js +37 -0
- package/dist/srpc/server-rpc.js +3 -1
- package/echo/echo.pb.go +1 -1
- package/echo/echo.pb.ts +6 -5
- package/echo/echo_srpc.pb.cpp +1 -1
- package/echo/echo_srpc.pb.go +1 -1
- package/echo/echo_srpc.pb.hpp +1 -1
- package/echo/echo_srpc.pb.rs +1 -1
- package/go.mod +13 -12
- package/go.sum +24 -24
- package/integration/cross-language/go-client/main.go +137 -5
- package/integration/cross-language/go-server/fixture-owner_test.go +127 -0
- package/integration/cross-language/go-server/main.go +169 -4
- package/integration/cross-language/run.bash +117 -13
- package/integration/cross-language/ts-client.ts +94 -13
- package/integration/cross-language/ts-server.ts +115 -7
- package/mock/index.ts +2 -2
- package/mock/mock.pb.go +1 -1
- package/mock/mock.pb.ts +6 -5
- package/mock/mock_srpc.pb.cpp +1 -1
- package/mock/mock_srpc.pb.go +1 -1
- package/mock/mock_srpc.pb.hpp +1 -1
- package/mock/mock_srpc.pb.rs +1 -1
- package/package.json +19 -26
- package/srpc/accept.go +1 -1
- package/srpc/call-receipt-e2e_test.go +111 -0
- package/srpc/call-receipt.go +112 -0
- package/srpc/call-receipt.test.ts +441 -0
- package/srpc/call-receipt.ts +131 -0
- package/srpc/call-receipt_test.go +536 -0
- package/srpc/client-rpc.go +1 -8
- package/srpc/client.ts +29 -2
- package/srpc/common-rpc.go +114 -29
- package/srpc/common-rpc.ts +104 -13
- package/srpc/handler.ts +2 -0
- package/srpc/index.ts +4 -0
- package/srpc/invoker.ts +10 -5
- package/srpc/msg-stream.go +8 -0
- package/srpc/muxed-conn.go +9 -4
- package/srpc/muxed-conn_test.go +79 -0
- package/srpc/muxed-yamux.go +1 -1
- package/srpc/rpcproto.pb.cc +15 -4
- package/srpc/rpcproto.pb.go +97 -1
- package/srpc/rpcproto.pb.h +59 -0
- package/srpc/rpcproto.pb.rs +45 -0
- package/srpc/rpcproto.pb.ts +90 -27
- package/srpc/rpcproto.proto +16 -0
- package/srpc/schema-ownership_test.go +115 -0
- package/srpc/server-invocation.go +40 -0
- package/srpc/server-invocation.ts +76 -0
- package/srpc/server-rpc.go +1 -1
- package/srpc/server-rpc.ts +6 -2
- package/srpc/stream-yamux.go +1 -1
- package/srpc/stream.go +20 -0
- package/srpc/websocket.go +1 -1
package/srpc/rpcproto.pb.go
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Code generated by protoc-gen-go-lite. DO NOT EDIT.
|
|
2
|
-
// protoc-gen-go-lite version: v0.
|
|
2
|
+
// protoc-gen-go-lite version: v0.13.0
|
|
3
3
|
// source: github.com/aperturerobotics/starpc/srpc/rpcproto.proto
|
|
4
4
|
|
|
5
5
|
package srpc
|
|
@@ -16,6 +16,58 @@ import (
|
|
|
16
16
|
json "github.com/aperturerobotics/protobuf-go-lite/json"
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
+
// TerminalKind is the terminal state of a held unary invocation.
|
|
20
|
+
type TerminalKind int32
|
|
21
|
+
|
|
22
|
+
const (
|
|
23
|
+
// TERMINAL_KIND_UNSPECIFIED is not a valid terminal state.
|
|
24
|
+
TerminalKind_TERMINAL_KIND_UNSPECIFIED TerminalKind = 0
|
|
25
|
+
// TERMINAL_KIND_COMMITTED identifies an explicit remote CallData completion.
|
|
26
|
+
TerminalKind_TERMINAL_KIND_COMMITTED TerminalKind = 1
|
|
27
|
+
// TERMINAL_KIND_CANCELED identifies a remote CallCancel packet.
|
|
28
|
+
TerminalKind_TERMINAL_KIND_CANCELED TerminalKind = 2
|
|
29
|
+
// TERMINAL_KIND_TRANSPORT_LOST identifies a remote error or transport failure.
|
|
30
|
+
TerminalKind_TERMINAL_KIND_TRANSPORT_LOST TerminalKind = 3
|
|
31
|
+
// TERMINAL_KIND_CLOSED identifies a bare remote close without completion.
|
|
32
|
+
TerminalKind_TERMINAL_KIND_CLOSED TerminalKind = 4
|
|
33
|
+
// TERMINAL_KIND_ABANDONED identifies owner-context expiry without a remote terminal.
|
|
34
|
+
TerminalKind_TERMINAL_KIND_ABANDONED TerminalKind = 5
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
// Enum value maps for TerminalKind.
|
|
38
|
+
var (
|
|
39
|
+
TerminalKind_name = map[int32]string{
|
|
40
|
+
0: "TERMINAL_KIND_UNSPECIFIED",
|
|
41
|
+
1: "TERMINAL_KIND_COMMITTED",
|
|
42
|
+
2: "TERMINAL_KIND_CANCELED",
|
|
43
|
+
3: "TERMINAL_KIND_TRANSPORT_LOST",
|
|
44
|
+
4: "TERMINAL_KIND_CLOSED",
|
|
45
|
+
5: "TERMINAL_KIND_ABANDONED",
|
|
46
|
+
}
|
|
47
|
+
TerminalKind_value = map[string]int32{
|
|
48
|
+
"TERMINAL_KIND_UNSPECIFIED": 0,
|
|
49
|
+
"TERMINAL_KIND_COMMITTED": 1,
|
|
50
|
+
"TERMINAL_KIND_CANCELED": 2,
|
|
51
|
+
"TERMINAL_KIND_TRANSPORT_LOST": 3,
|
|
52
|
+
"TERMINAL_KIND_CLOSED": 4,
|
|
53
|
+
"TERMINAL_KIND_ABANDONED": 5,
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
func (x TerminalKind) Enum() *TerminalKind {
|
|
58
|
+
p := new(TerminalKind)
|
|
59
|
+
*p = x
|
|
60
|
+
return p
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func (x TerminalKind) String() string {
|
|
64
|
+
name, valid := TerminalKind_name[int32(x)]
|
|
65
|
+
if valid {
|
|
66
|
+
return name
|
|
67
|
+
}
|
|
68
|
+
return strconv.Itoa(int(x))
|
|
69
|
+
}
|
|
70
|
+
|
|
19
71
|
// Packet is a message sent over a srpc packet connection.
|
|
20
72
|
type Packet struct {
|
|
21
73
|
unknownFields []byte
|
|
@@ -437,6 +489,46 @@ func (this *CallData) EqualMessageVT(thatMsg any) bool {
|
|
|
437
489
|
return this.EqualVT(that)
|
|
438
490
|
}
|
|
439
491
|
|
|
492
|
+
// MarshalProtoJSON marshals the TerminalKind to JSON.
|
|
493
|
+
func (x TerminalKind) MarshalProtoJSON(s *json.MarshalState) {
|
|
494
|
+
s.WriteEnum(int32(x), TerminalKind_name)
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// MarshalText marshals the TerminalKind to text.
|
|
498
|
+
func (x TerminalKind) MarshalText() ([]byte, error) {
|
|
499
|
+
return []byte(json.GetEnumString(int32(x), TerminalKind_name)), nil
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// MarshalJSON marshals the TerminalKind to JSON.
|
|
503
|
+
func (x TerminalKind) MarshalJSON() ([]byte, error) {
|
|
504
|
+
return json.DefaultMarshalerConfig.Marshal(x)
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// UnmarshalProtoJSON unmarshals the TerminalKind from JSON.
|
|
508
|
+
func (x *TerminalKind) UnmarshalProtoJSON(s *json.UnmarshalState) {
|
|
509
|
+
v := s.ReadEnum(TerminalKind_value)
|
|
510
|
+
if err := s.Err(); err != nil {
|
|
511
|
+
s.SetErrorf("could not read TerminalKind enum: %v", err)
|
|
512
|
+
return
|
|
513
|
+
}
|
|
514
|
+
*x = TerminalKind(v)
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// UnmarshalText unmarshals the TerminalKind from text.
|
|
518
|
+
func (x *TerminalKind) UnmarshalText(b []byte) error {
|
|
519
|
+
i, err := json.ParseEnumString(string(b), TerminalKind_value)
|
|
520
|
+
if err != nil {
|
|
521
|
+
return err
|
|
522
|
+
}
|
|
523
|
+
*x = TerminalKind(i)
|
|
524
|
+
return nil
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// UnmarshalJSON unmarshals the TerminalKind from JSON.
|
|
528
|
+
func (x *TerminalKind) UnmarshalJSON(b []byte) error {
|
|
529
|
+
return json.DefaultUnmarshalerConfig.Unmarshal(b, x)
|
|
530
|
+
}
|
|
531
|
+
|
|
440
532
|
// MarshalProtoJSON marshals the Packet message to JSON.
|
|
441
533
|
func (x *Packet) MarshalProtoJSON(s *json.MarshalState) {
|
|
442
534
|
if x == nil {
|
|
@@ -983,6 +1075,10 @@ func (m *CallData) SizeVT() (n int) {
|
|
|
983
1075
|
return n
|
|
984
1076
|
}
|
|
985
1077
|
|
|
1078
|
+
func (x TerminalKind) MarshalProtoText() string {
|
|
1079
|
+
return x.String()
|
|
1080
|
+
}
|
|
1081
|
+
|
|
986
1082
|
func (x *Packet) MarshalProtoText() string {
|
|
987
1083
|
var sb strings.Builder
|
|
988
1084
|
sb.WriteString("Packet {")
|
package/srpc/rpcproto.pb.h
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
#include "google/protobuf/message_lite.h"
|
|
31
31
|
#include "google/protobuf/repeated_field.h" // IWYU pragma: export
|
|
32
32
|
#include "google/protobuf/extension_set.h" // IWYU pragma: export
|
|
33
|
+
#include "google/protobuf/generated_enum_reflection.h"
|
|
33
34
|
#include "google/protobuf/unknown_field_set.h"
|
|
34
35
|
// @@protoc_insertion_point(includes)
|
|
35
36
|
|
|
@@ -55,6 +56,8 @@ extern "C" {
|
|
|
55
56
|
extern const ::google::protobuf::internal::DescriptorTable descriptor_table_github_2ecom_2faperturerobotics_2fstarpc_2fsrpc_2frpcproto_2eproto;
|
|
56
57
|
} // extern "C"
|
|
57
58
|
namespace srpc {
|
|
59
|
+
enum TerminalKind : int;
|
|
60
|
+
extern const uint32_t TerminalKind_internal_data_[];
|
|
58
61
|
class CallData;
|
|
59
62
|
struct CallDataDefaultTypeInternal;
|
|
60
63
|
extern CallDataDefaultTypeInternal _CallData_default_instance_;
|
|
@@ -70,10 +73,53 @@ extern const ::google::protobuf::internal::ClassDataFull Packet_class_data_;
|
|
|
70
73
|
} // namespace srpc
|
|
71
74
|
namespace google {
|
|
72
75
|
namespace protobuf {
|
|
76
|
+
template <>
|
|
77
|
+
internal::EnumTraitsT<::srpc::TerminalKind_internal_data_>
|
|
78
|
+
internal::EnumTraitsImpl::value<::srpc::TerminalKind>;
|
|
73
79
|
} // namespace protobuf
|
|
74
80
|
} // namespace google
|
|
75
81
|
|
|
76
82
|
namespace srpc {
|
|
83
|
+
enum TerminalKind : int {
|
|
84
|
+
TERMINAL_KIND_UNSPECIFIED = 0,
|
|
85
|
+
TERMINAL_KIND_COMMITTED = 1,
|
|
86
|
+
TERMINAL_KIND_CANCELED = 2,
|
|
87
|
+
TERMINAL_KIND_TRANSPORT_LOST = 3,
|
|
88
|
+
TERMINAL_KIND_CLOSED = 4,
|
|
89
|
+
TERMINAL_KIND_ABANDONED = 5,
|
|
90
|
+
TerminalKind_INT_MIN_SENTINEL_DO_NOT_USE_ =
|
|
91
|
+
::std::numeric_limits<::int32_t>::min(),
|
|
92
|
+
TerminalKind_INT_MAX_SENTINEL_DO_NOT_USE_ =
|
|
93
|
+
::std::numeric_limits<::int32_t>::max(),
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
extern const uint32_t TerminalKind_internal_data_[];
|
|
97
|
+
inline constexpr TerminalKind TerminalKind_MIN =
|
|
98
|
+
static_cast<TerminalKind>(0);
|
|
99
|
+
inline constexpr TerminalKind TerminalKind_MAX =
|
|
100
|
+
static_cast<TerminalKind>(5);
|
|
101
|
+
inline bool TerminalKind_IsValid(int value) {
|
|
102
|
+
return 0 <= value && value <= 5;
|
|
103
|
+
}
|
|
104
|
+
inline constexpr int TerminalKind_ARRAYSIZE = 5 + 1;
|
|
105
|
+
const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TerminalKind_descriptor();
|
|
106
|
+
template <typename T>
|
|
107
|
+
const ::std::string& TerminalKind_Name(T value) {
|
|
108
|
+
static_assert(::std::is_same<T, TerminalKind>::value ||
|
|
109
|
+
::std::is_integral<T>::value,
|
|
110
|
+
"Incorrect type passed to TerminalKind_Name().");
|
|
111
|
+
return TerminalKind_Name(static_cast<TerminalKind>(value));
|
|
112
|
+
}
|
|
113
|
+
template <>
|
|
114
|
+
inline const ::std::string& TerminalKind_Name(TerminalKind value) {
|
|
115
|
+
return ::google::protobuf::internal::NameOfDenseEnum<TerminalKind_descriptor, 0, 5>(
|
|
116
|
+
static_cast<int>(value));
|
|
117
|
+
}
|
|
118
|
+
inline bool TerminalKind_Parse(
|
|
119
|
+
::absl::string_view name, TerminalKind* PROTOBUF_NONNULL value) {
|
|
120
|
+
return ::google::protobuf::internal::ParseNamedEnum<TerminalKind>(TerminalKind_descriptor(), name,
|
|
121
|
+
value);
|
|
122
|
+
}
|
|
77
123
|
|
|
78
124
|
// ===================================================================
|
|
79
125
|
|
|
@@ -1444,6 +1490,19 @@ inline void CallData::set_allocated_error(::std::string* PROTOBUF_NULLABLE value
|
|
|
1444
1490
|
} // namespace srpc
|
|
1445
1491
|
|
|
1446
1492
|
|
|
1493
|
+
namespace google {
|
|
1494
|
+
namespace protobuf {
|
|
1495
|
+
|
|
1496
|
+
template <>
|
|
1497
|
+
struct is_proto_enum<::srpc::TerminalKind> : std::true_type {};
|
|
1498
|
+
template <>
|
|
1499
|
+
inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::srpc::TerminalKind>() {
|
|
1500
|
+
return ::srpc::TerminalKind_descriptor();
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
} // namespace protobuf
|
|
1504
|
+
} // namespace google
|
|
1505
|
+
|
|
1447
1506
|
// @@protoc_insertion_point(global_scope)
|
|
1448
1507
|
|
|
1449
1508
|
#include "google/protobuf/port_undef.inc"
|
package/srpc/rpcproto.pb.rs
CHANGED
|
@@ -59,4 +59,49 @@ pub struct CallData {
|
|
|
59
59
|
#[prost(string, tag="4")]
|
|
60
60
|
pub error: ::prost::alloc::string::String,
|
|
61
61
|
}
|
|
62
|
+
/// TerminalKind is the terminal state of a held unary invocation.
|
|
63
|
+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
|
64
|
+
#[repr(i32)]
|
|
65
|
+
pub enum TerminalKind {
|
|
66
|
+
/// TERMINAL_KIND_UNSPECIFIED is not a valid terminal state.
|
|
67
|
+
Unspecified = 0,
|
|
68
|
+
/// TERMINAL_KIND_COMMITTED identifies an explicit remote CallData completion.
|
|
69
|
+
Committed = 1,
|
|
70
|
+
/// TERMINAL_KIND_CANCELED identifies a remote CallCancel packet.
|
|
71
|
+
Canceled = 2,
|
|
72
|
+
/// TERMINAL_KIND_TRANSPORT_LOST identifies a remote error or transport failure.
|
|
73
|
+
TransportLost = 3,
|
|
74
|
+
/// TERMINAL_KIND_CLOSED identifies a bare remote close without completion.
|
|
75
|
+
Closed = 4,
|
|
76
|
+
/// TERMINAL_KIND_ABANDONED identifies owner-context expiry without a remote terminal.
|
|
77
|
+
Abandoned = 5,
|
|
78
|
+
}
|
|
79
|
+
impl TerminalKind {
|
|
80
|
+
/// String value of the enum field names used in the ProtoBuf definition.
|
|
81
|
+
///
|
|
82
|
+
/// The values are not transformed in any way and thus are considered stable
|
|
83
|
+
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
|
84
|
+
pub fn as_str_name(&self) -> &'static str {
|
|
85
|
+
match self {
|
|
86
|
+
Self::Unspecified => "TERMINAL_KIND_UNSPECIFIED",
|
|
87
|
+
Self::Committed => "TERMINAL_KIND_COMMITTED",
|
|
88
|
+
Self::Canceled => "TERMINAL_KIND_CANCELED",
|
|
89
|
+
Self::TransportLost => "TERMINAL_KIND_TRANSPORT_LOST",
|
|
90
|
+
Self::Closed => "TERMINAL_KIND_CLOSED",
|
|
91
|
+
Self::Abandoned => "TERMINAL_KIND_ABANDONED",
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/// Creates an enum from field names used in the ProtoBuf definition.
|
|
95
|
+
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
|
96
|
+
match value {
|
|
97
|
+
"TERMINAL_KIND_UNSPECIFIED" => Some(Self::Unspecified),
|
|
98
|
+
"TERMINAL_KIND_COMMITTED" => Some(Self::Committed),
|
|
99
|
+
"TERMINAL_KIND_CANCELED" => Some(Self::Canceled),
|
|
100
|
+
"TERMINAL_KIND_TRANSPORT_LOST" => Some(Self::TransportLost),
|
|
101
|
+
"TERMINAL_KIND_CLOSED" => Some(Self::Closed),
|
|
102
|
+
"TERMINAL_KIND_ABANDONED" => Some(Self::Abandoned),
|
|
103
|
+
_ => None,
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
62
107
|
// @@protoc_insertion_point(module)
|
package/srpc/rpcproto.pb.ts
CHANGED
|
@@ -2,11 +2,75 @@
|
|
|
2
2
|
// @generated from file github.com/aperturerobotics/starpc/srpc/rpcproto.proto (package srpc, syntax proto3)
|
|
3
3
|
/* eslint-disable */
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
5
|
+
import { createEnumType } from '@aptre/protobuf-es-lite/enum'
|
|
6
|
+
import type { MessageType } from '@aptre/protobuf-es-lite/message'
|
|
7
|
+
import { createMessageType } from '@aptre/protobuf-es-lite/message'
|
|
8
|
+
import { ScalarType } from '@aptre/protobuf-es-lite/scalar'
|
|
9
|
+
import type { PartialFieldInfo } from '@aptre/protobuf-es-lite/field'
|
|
7
10
|
|
|
8
11
|
export const protobufPackage = 'srpc'
|
|
9
12
|
|
|
13
|
+
/**
|
|
14
|
+
* TerminalKind is the terminal state of a held unary invocation.
|
|
15
|
+
*
|
|
16
|
+
* @generated from enum srpc.TerminalKind
|
|
17
|
+
*/
|
|
18
|
+
export enum TerminalKind {
|
|
19
|
+
/**
|
|
20
|
+
* TERMINAL_KIND_UNSPECIFIED is not a valid terminal state.
|
|
21
|
+
*
|
|
22
|
+
* @generated from enum value: TERMINAL_KIND_UNSPECIFIED = 0;
|
|
23
|
+
*/
|
|
24
|
+
UNSPECIFIED = 0,
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* TERMINAL_KIND_COMMITTED identifies an explicit remote CallData completion.
|
|
28
|
+
*
|
|
29
|
+
* @generated from enum value: TERMINAL_KIND_COMMITTED = 1;
|
|
30
|
+
*/
|
|
31
|
+
COMMITTED = 1,
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* TERMINAL_KIND_CANCELED identifies a remote CallCancel packet.
|
|
35
|
+
*
|
|
36
|
+
* @generated from enum value: TERMINAL_KIND_CANCELED = 2;
|
|
37
|
+
*/
|
|
38
|
+
CANCELED = 2,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* TERMINAL_KIND_TRANSPORT_LOST identifies a remote error or transport failure.
|
|
42
|
+
*
|
|
43
|
+
* @generated from enum value: TERMINAL_KIND_TRANSPORT_LOST = 3;
|
|
44
|
+
*/
|
|
45
|
+
TRANSPORT_LOST = 3,
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* TERMINAL_KIND_CLOSED identifies a bare remote close without completion.
|
|
49
|
+
*
|
|
50
|
+
* @generated from enum value: TERMINAL_KIND_CLOSED = 4;
|
|
51
|
+
*/
|
|
52
|
+
CLOSED = 4,
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* TERMINAL_KIND_ABANDONED identifies owner-context expiry without a remote terminal.
|
|
56
|
+
*
|
|
57
|
+
* @generated from enum value: TERMINAL_KIND_ABANDONED = 5;
|
|
58
|
+
*/
|
|
59
|
+
ABANDONED = 5,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const TerminalKind_Enum = /* @__PURE__ */ createEnumType(
|
|
63
|
+
'srpc.TerminalKind',
|
|
64
|
+
[
|
|
65
|
+
[0, 'TERMINAL_KIND_UNSPECIFIED'],
|
|
66
|
+
[1, 'TERMINAL_KIND_COMMITTED'],
|
|
67
|
+
[2, 'TERMINAL_KIND_CANCELED'],
|
|
68
|
+
[3, 'TERMINAL_KIND_TRANSPORT_LOST'],
|
|
69
|
+
[4, 'TERMINAL_KIND_CLOSED'],
|
|
70
|
+
[5, 'TERMINAL_KIND_ABANDONED'],
|
|
71
|
+
],
|
|
72
|
+
)
|
|
73
|
+
|
|
10
74
|
/**
|
|
11
75
|
* CallStart requests starting a new RPC call.
|
|
12
76
|
*
|
|
@@ -42,17 +106,17 @@ export interface CallStart {
|
|
|
42
106
|
dataIsZero?: boolean
|
|
43
107
|
}
|
|
44
108
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
})
|
|
109
|
+
export const CallStart: MessageType<CallStart> =
|
|
110
|
+
/* @__PURE__ */ createMessageType({
|
|
111
|
+
typeName: 'srpc.CallStart',
|
|
112
|
+
fields: [
|
|
113
|
+
{ no: 1, name: 'rpc_service', kind: 'scalar', T: ScalarType.STRING },
|
|
114
|
+
{ no: 2, name: 'rpc_method', kind: 'scalar', T: ScalarType.STRING },
|
|
115
|
+
{ no: 3, name: 'data', kind: 'scalar', T: ScalarType.BYTES },
|
|
116
|
+
{ no: 4, name: 'data_is_zero', kind: 'scalar', T: ScalarType.BOOL },
|
|
117
|
+
] satisfies readonly PartialFieldInfo[],
|
|
118
|
+
packedByDefault: true,
|
|
119
|
+
})
|
|
56
120
|
|
|
57
121
|
/**
|
|
58
122
|
* CallData contains a message in a streaming RPC sequence.
|
|
@@ -87,17 +151,17 @@ export interface CallData {
|
|
|
87
151
|
error?: string
|
|
88
152
|
}
|
|
89
153
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
})
|
|
154
|
+
export const CallData: MessageType<CallData> =
|
|
155
|
+
/* @__PURE__ */ createMessageType({
|
|
156
|
+
typeName: 'srpc.CallData',
|
|
157
|
+
fields: [
|
|
158
|
+
{ no: 1, name: 'data', kind: 'scalar', T: ScalarType.BYTES },
|
|
159
|
+
{ no: 2, name: 'data_is_zero', kind: 'scalar', T: ScalarType.BOOL },
|
|
160
|
+
{ no: 3, name: 'complete', kind: 'scalar', T: ScalarType.BOOL },
|
|
161
|
+
{ no: 4, name: 'error', kind: 'scalar', T: ScalarType.STRING },
|
|
162
|
+
] satisfies readonly PartialFieldInfo[],
|
|
163
|
+
packedByDefault: true,
|
|
164
|
+
})
|
|
101
165
|
|
|
102
166
|
/**
|
|
103
167
|
* Packet is a message sent over a srpc packet connection.
|
|
@@ -144,8 +208,7 @@ export interface Packet {
|
|
|
144
208
|
}
|
|
145
209
|
}
|
|
146
210
|
|
|
147
|
-
|
|
148
|
-
export const Packet: MessageType<Packet> = createMessageType({
|
|
211
|
+
export const Packet: MessageType<Packet> = /* @__PURE__ */ createMessageType({
|
|
149
212
|
typeName: 'srpc.Packet',
|
|
150
213
|
fields: [
|
|
151
214
|
{
|
|
@@ -169,6 +232,6 @@ export const Packet: MessageType<Packet> = createMessageType({
|
|
|
169
232
|
T: ScalarType.BOOL,
|
|
170
233
|
oneof: 'body',
|
|
171
234
|
},
|
|
172
|
-
]
|
|
235
|
+
] satisfies readonly PartialFieldInfo[],
|
|
173
236
|
packedByDefault: true,
|
|
174
237
|
})
|
package/srpc/rpcproto.proto
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
syntax = "proto3";
|
|
2
2
|
package srpc;
|
|
3
3
|
|
|
4
|
+
// TerminalKind is the terminal state of a held unary invocation.
|
|
5
|
+
enum TerminalKind {
|
|
6
|
+
// TERMINAL_KIND_UNSPECIFIED is not a valid terminal state.
|
|
7
|
+
TERMINAL_KIND_UNSPECIFIED = 0;
|
|
8
|
+
// TERMINAL_KIND_COMMITTED identifies an explicit remote CallData completion.
|
|
9
|
+
TERMINAL_KIND_COMMITTED = 1;
|
|
10
|
+
// TERMINAL_KIND_CANCELED identifies a remote CallCancel packet.
|
|
11
|
+
TERMINAL_KIND_CANCELED = 2;
|
|
12
|
+
// TERMINAL_KIND_TRANSPORT_LOST identifies a remote error or transport failure.
|
|
13
|
+
TERMINAL_KIND_TRANSPORT_LOST = 3;
|
|
14
|
+
// TERMINAL_KIND_CLOSED identifies a bare remote close without completion.
|
|
15
|
+
TERMINAL_KIND_CLOSED = 4;
|
|
16
|
+
// TERMINAL_KIND_ABANDONED identifies owner-context expiry without a remote terminal.
|
|
17
|
+
TERMINAL_KIND_ABANDONED = 5;
|
|
18
|
+
}
|
|
19
|
+
|
|
4
20
|
// Packet is a message sent over a srpc packet connection.
|
|
5
21
|
message Packet {
|
|
6
22
|
// Body is the packet body.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
package srpc
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"go/ast"
|
|
5
|
+
"go/parser"
|
|
6
|
+
"go/token"
|
|
7
|
+
"os"
|
|
8
|
+
"strings"
|
|
9
|
+
"testing"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// handwrittenTerminalConst names the parallel iota constants the receipt
|
|
13
|
+
// post-mortem removed. Their reappearance signals a second handwritten owner of
|
|
14
|
+
// the cross-language terminal vocabulary.
|
|
15
|
+
var handwrittenTerminalConst = map[string]bool{
|
|
16
|
+
"TerminalCommitted": true,
|
|
17
|
+
"TerminalCanceled": true,
|
|
18
|
+
"TerminalLost": true,
|
|
19
|
+
"TerminalClosed": true,
|
|
20
|
+
"TerminalAbandoned": true,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// handwrittenTerminalKindOwners returns the source files that declare the shared
|
|
24
|
+
// TerminalKind vocabulary by hand instead of consuming the generated rpcproto
|
|
25
|
+
// owner. The cross-language terminal noun has exactly one schema owner; a
|
|
26
|
+
// handwritten type or iota constant reintroduces the parallel owner.
|
|
27
|
+
func handwrittenTerminalKindOwners(t *testing.T, files map[string]string) []string {
|
|
28
|
+
t.Helper()
|
|
29
|
+
var owners []string
|
|
30
|
+
for name, src := range files {
|
|
31
|
+
fset := token.NewFileSet()
|
|
32
|
+
file, err := parser.ParseFile(fset, name, src, 0)
|
|
33
|
+
if err != nil {
|
|
34
|
+
t.Fatalf("parse %s: %v", name, err)
|
|
35
|
+
}
|
|
36
|
+
if declaresTerminalKindByHand(file) {
|
|
37
|
+
owners = append(owners, name)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return owners
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// declaresTerminalKindByHand reports whether a file declares the TerminalKind
|
|
44
|
+
// type or one of its removed iota constants.
|
|
45
|
+
func declaresTerminalKindByHand(file *ast.File) bool {
|
|
46
|
+
for _, decl := range file.Decls {
|
|
47
|
+
gen, ok := decl.(*ast.GenDecl)
|
|
48
|
+
if !ok {
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
for _, spec := range gen.Specs {
|
|
52
|
+
switch s := spec.(type) {
|
|
53
|
+
case *ast.TypeSpec:
|
|
54
|
+
if s.Name.Name == "TerminalKind" {
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
57
|
+
case *ast.ValueSpec:
|
|
58
|
+
for _, id := range s.Names {
|
|
59
|
+
if handwrittenTerminalConst[id.Name] {
|
|
60
|
+
return true
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// packageSourceFiles reads the non-generated, non-test Go sources of the current
|
|
70
|
+
// package directory.
|
|
71
|
+
func packageSourceFiles(t *testing.T) map[string]string {
|
|
72
|
+
t.Helper()
|
|
73
|
+
entries, err := os.ReadDir(".")
|
|
74
|
+
if err != nil {
|
|
75
|
+
t.Fatalf("read package dir: %v", err)
|
|
76
|
+
}
|
|
77
|
+
files := map[string]string{}
|
|
78
|
+
for _, entry := range entries {
|
|
79
|
+
name := entry.Name()
|
|
80
|
+
if !strings.HasSuffix(name, ".go") {
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
if strings.HasSuffix(name, ".pb.go") || strings.HasSuffix(name, "_test.go") {
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
data, err := os.ReadFile(name)
|
|
87
|
+
if err != nil {
|
|
88
|
+
t.Fatalf("read %s: %v", name, err)
|
|
89
|
+
}
|
|
90
|
+
files[name] = string(data)
|
|
91
|
+
}
|
|
92
|
+
return files
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// TestTerminalKindHasSingleSchemaOwner proves no handwritten srpc source owns
|
|
96
|
+
// the cross-language TerminalKind vocabulary alongside the generated owner.
|
|
97
|
+
func TestTerminalKindHasSingleSchemaOwner(t *testing.T) {
|
|
98
|
+
owners := handwrittenTerminalKindOwners(t, packageSourceFiles(t))
|
|
99
|
+
if len(owners) != 0 {
|
|
100
|
+
t.Fatalf("TerminalKind must come from generated rpcproto; handwritten owners: %v", owners)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// TestTerminalKindGuardDetectsHandwrittenOwner proves the guard fires when a
|
|
105
|
+
// parallel handwritten TerminalKind owner regresses into the package.
|
|
106
|
+
func TestTerminalKindGuardDetectsHandwrittenOwner(t *testing.T) {
|
|
107
|
+
bad := map[string]string{
|
|
108
|
+
"server-invocation.go": "package srpc\n\n" +
|
|
109
|
+
"type TerminalKind int\n\n" +
|
|
110
|
+
"const (\n\tTerminalCommitted TerminalKind = iota\n)\n",
|
|
111
|
+
}
|
|
112
|
+
if owners := handwrittenTerminalKindOwners(t, bad); len(owners) == 0 {
|
|
113
|
+
t.Fatal("guard failed to flag a handwritten TerminalKind owner")
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
package srpc
|
|
2
|
+
|
|
3
|
+
import "context"
|
|
4
|
+
|
|
5
|
+
// ServerInvocation exposes the terminal of a held unary server invocation.
|
|
6
|
+
type ServerInvocation interface {
|
|
7
|
+
// WaitTerminal waits for a remote terminal or owner-context expiry. The
|
|
8
|
+
// owner context must outlive the invocation context.
|
|
9
|
+
WaitTerminal(ownerCtx context.Context) (TerminalKind, error)
|
|
10
|
+
// Done returns the invocation context cancellation channel for diagnostics.
|
|
11
|
+
Done() <-chan struct{}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type serverInvocationKey struct{}
|
|
15
|
+
|
|
16
|
+
func withServerInvocation(ctx context.Context, invocation ServerInvocation) context.Context {
|
|
17
|
+
return context.WithValue(ctx, serverInvocationKey{}, invocation)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// GetServerInvocation returns the held unary invocation attached to a context.
|
|
21
|
+
func GetServerInvocation(ctx context.Context) (ServerInvocation, bool) {
|
|
22
|
+
if ctx == nil {
|
|
23
|
+
return nil, false
|
|
24
|
+
}
|
|
25
|
+
invocation, ok := ctx.Value(serverInvocationKey{}).(ServerInvocation)
|
|
26
|
+
return invocation, ok
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// WaitTerminal waits for and classifies the terminal of a held unary invocation.
|
|
30
|
+
func (r *ServerRPC) WaitTerminal(ownerCtx context.Context) (TerminalKind, error) {
|
|
31
|
+
return r.commonRPC.WaitTerminal(ownerCtx)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Done returns the invocation context cancellation channel for diagnostics.
|
|
35
|
+
func (r *ServerRPC) Done() <-chan struct{} {
|
|
36
|
+
return r.ctx.Done()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// _ is a type assertion.
|
|
40
|
+
var _ ServerInvocation = (*ServerRPC)(nil)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { TerminalKind } from './rpcproto.pb.js'
|
|
2
|
+
|
|
3
|
+
// ServerInvocation exposes the invocation signal and terminal wait.
|
|
4
|
+
export class ServerInvocation implements AbortSignal {
|
|
5
|
+
public constructor(
|
|
6
|
+
public readonly signal: AbortSignal,
|
|
7
|
+
private readonly waitFn: (
|
|
8
|
+
ownerSignal: AbortSignal,
|
|
9
|
+
) => Promise<TerminalKind>,
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
public get aborted(): boolean {
|
|
13
|
+
return this.signal.aborted
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public get onabort() {
|
|
17
|
+
return this.signal.onabort
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public set onabort(value: typeof this.signal.onabort) {
|
|
21
|
+
this.signal.onabort = value
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public get reason() {
|
|
25
|
+
return this.signal.reason
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public throwIfAborted(): void {
|
|
29
|
+
this.signal.throwIfAborted()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public addEventListener<K extends keyof AbortSignalEventMap>(
|
|
33
|
+
type: K,
|
|
34
|
+
listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => unknown,
|
|
35
|
+
options?: boolean | AddEventListenerOptions,
|
|
36
|
+
): void
|
|
37
|
+
public addEventListener(
|
|
38
|
+
type: string,
|
|
39
|
+
listener: EventListenerOrEventListenerObject,
|
|
40
|
+
options?: boolean | AddEventListenerOptions,
|
|
41
|
+
): void
|
|
42
|
+
public addEventListener(
|
|
43
|
+
type: string,
|
|
44
|
+
listener: EventListenerOrEventListenerObject,
|
|
45
|
+
options?: boolean | AddEventListenerOptions,
|
|
46
|
+
): void {
|
|
47
|
+
this.signal.addEventListener(type, listener, options)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public removeEventListener<K extends keyof AbortSignalEventMap>(
|
|
51
|
+
type: K,
|
|
52
|
+
listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => unknown,
|
|
53
|
+
options?: boolean | EventListenerOptions,
|
|
54
|
+
): void
|
|
55
|
+
public removeEventListener(
|
|
56
|
+
type: string,
|
|
57
|
+
listener: EventListenerOrEventListenerObject,
|
|
58
|
+
options?: boolean | EventListenerOptions,
|
|
59
|
+
): void
|
|
60
|
+
public removeEventListener(
|
|
61
|
+
type: string,
|
|
62
|
+
listener: EventListenerOrEventListenerObject,
|
|
63
|
+
options?: boolean | EventListenerOptions,
|
|
64
|
+
): void {
|
|
65
|
+
this.signal.removeEventListener(type, listener, options)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public dispatchEvent(event: Event): boolean {
|
|
69
|
+
return this.signal.dispatchEvent(event)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// waitTerminal waits for a remote terminal or owner-signal cancellation.
|
|
73
|
+
public waitTerminal(ownerSignal: AbortSignal): Promise<TerminalKind> {
|
|
74
|
+
return this.waitFn(ownerSignal)
|
|
75
|
+
}
|
|
76
|
+
}
|
package/srpc/server-rpc.go
CHANGED
|
@@ -98,7 +98,7 @@ func (r *ServerRPC) HandleCallStart(pkt *CallStart) error {
|
|
|
98
98
|
// invokeRPC invokes the RPC after CallStart is received.
|
|
99
99
|
func (r *ServerRPC) invokeRPC(serviceID, methodID string) {
|
|
100
100
|
// on the server side, the writer is closed by invokeRPC.
|
|
101
|
-
strm := NewMsgStream(r.ctx, r, r.cancelContext)
|
|
101
|
+
strm := NewMsgStream(withServerInvocation(r.ctx, r), r, r.cancelContext)
|
|
102
102
|
ok, err := r.invoker.InvokeMethod(serviceID, methodID, strm)
|
|
103
103
|
if err == nil && !ok {
|
|
104
104
|
err = ErrUnimplemented
|