proto_service_mesh 0.18.0 → 0.19.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.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b3837c53424bc2b59a2808b6586c056dba67b76ff34e4871adfad3978fe9a668
|
|
4
|
+
data.tar.gz: 62dd2ab469307cf2a40e0060cdaede23c1c3e4f397e5c4d9cc4991e441a1f2d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e8552e6c52b9d1cb9f5e2e6d3b99f541659fe5f7bc29bb2e855da3e3e2c88b42c83b5147c068897a7449abee61d6a178a31be29a3e681b4b48865cfaa02a509d
|
|
7
|
+
data.tar.gz: 8982b84372dcc2e2a4ccd8b96e6f31ebcf89cde3590866088d5c4a1d403a9b7d232924d2445e0c56bf3b6b688ca540dccb25191338a95eebf31f97a3cc47b9a2
|
|
@@ -28,15 +28,19 @@ module ProtoServiceMesh
|
|
|
28
28
|
|
|
29
29
|
# Sends +request+ to a route and returns the decoded response, whose
|
|
30
30
|
# mesh_metadata is the reply's metadata without keys that start with
|
|
31
|
-
# OPTION_PREFIX. Raises MeshError for a reply carrying
|
|
32
|
-
#
|
|
33
|
-
# mesh_metadata is the same reply
|
|
31
|
+
# OPTION_PREFIX. Raises MeshError for a reply carrying Mesh-Status, or
|
|
32
|
+
# Grpc-Status when the reply has no Mesh-Status, or INTERNAL when either
|
|
33
|
+
# payload does not decode; either error's mesh_metadata is the same reply
|
|
34
|
+
# metadata. A reply that carries Grpc-Status or Content-Type without its
|
|
35
|
+
# Mesh- replacement comes from an older version, and the first such reply
|
|
36
|
+
# on the target writes a warning.
|
|
34
37
|
def self.request(rpc, request)
|
|
35
38
|
message, options = outbound(rpc, request)
|
|
36
39
|
reply = client_for(rpc.target).request(message, options)
|
|
37
40
|
reply_metadata = Wire.without_options(reply.metadata)
|
|
41
|
+
Wire.legacy_content_type?(rpc.target, reply.metadata)
|
|
38
42
|
begin
|
|
39
|
-
if reply_metadata.key?(Wire::
|
|
43
|
+
if reply_metadata.key?(Wire::MESH_STATUS_KEY) || Wire.legacy_status?(rpc.target, reply.metadata)
|
|
40
44
|
raise MeshError.from_proto(decode(Google::Rpc::Status, reply.payload))
|
|
41
45
|
end
|
|
42
46
|
|
|
@@ -6,7 +6,9 @@ module ProtoServiceMesh
|
|
|
6
6
|
# serves, taking the decoded request, whose mesh_metadata is the inbound
|
|
7
7
|
# message metadata. A route method returns the response; the response's
|
|
8
8
|
# mesh_metadata, without keys that start with OPTION_PREFIX, is the reply's
|
|
9
|
-
# metadata. The same holds for a raised MeshError.
|
|
9
|
+
# metadata. The same holds for a raised MeshError. A request that carries
|
|
10
|
+
# Content-Type without Mesh-Content-Type comes from an older version, and its
|
|
11
|
+
# reply also carries Content-Type and, for a MeshError, Grpc-Status.
|
|
10
12
|
class RPCService
|
|
11
13
|
extend RpcDSL
|
|
12
14
|
|
|
@@ -41,10 +43,11 @@ module ProtoServiceMesh
|
|
|
41
43
|
|
|
42
44
|
def endpoint_handler(rpc)
|
|
43
45
|
lambda do |message|
|
|
46
|
+
legacy = Wire.legacy_content_type?(rpc.target, message.metadata)
|
|
44
47
|
request = begin
|
|
45
48
|
decode_inbound(rpc, message)
|
|
46
49
|
rescue Google::Protobuf::ParseError => e
|
|
47
|
-
next status_reply(message, MeshError.new(:INTERNAL, e.message))
|
|
50
|
+
next status_reply(message, MeshError.new(:INTERNAL, e.message), legacy)
|
|
48
51
|
end
|
|
49
52
|
|
|
50
53
|
response = public_send(rpc.name, request)
|
|
@@ -52,17 +55,18 @@ module ProtoServiceMesh
|
|
|
52
55
|
raise TypeError, "#{rpc.name} returned #{response.class}, expected #{rpc.output}"
|
|
53
56
|
end
|
|
54
57
|
|
|
55
|
-
metadata = Wire.metadata(Wire.without_options(response.mesh_metadata)
|
|
58
|
+
metadata = Wire.metadata(Wire.without_options(response.mesh_metadata), legacy: legacy)
|
|
56
59
|
ServiceMesh::Message.new(target: message.target, metadata: metadata, payload: response.to_proto)
|
|
57
60
|
rescue MeshError => e
|
|
58
|
-
status_reply(message, e)
|
|
61
|
+
status_reply(message, e, legacy)
|
|
59
62
|
rescue => e
|
|
60
|
-
status_reply(message, MeshError.new(:UNKNOWN, e.message))
|
|
63
|
+
status_reply(message, MeshError.new(:UNKNOWN, e.message), legacy)
|
|
61
64
|
end
|
|
62
65
|
end
|
|
63
66
|
|
|
64
67
|
def subscriber_handler(rpc)
|
|
65
68
|
lambda do |message|
|
|
69
|
+
Wire.legacy_content_type?(rpc.target, message.metadata)
|
|
66
70
|
public_send(rpc.name, decode_inbound(rpc, message))
|
|
67
71
|
nil
|
|
68
72
|
end
|
|
@@ -81,8 +85,9 @@ module ProtoServiceMesh
|
|
|
81
85
|
request
|
|
82
86
|
end
|
|
83
87
|
|
|
84
|
-
def status_reply(message, error)
|
|
85
|
-
|
|
88
|
+
def status_reply(message, error, legacy)
|
|
89
|
+
metadata = Wire.status_metadata(error, Wire.without_options(error.mesh_metadata), legacy: legacy)
|
|
90
|
+
ServiceMesh::Message.new(target: message.target, metadata: metadata, payload: error.proto.to_proto)
|
|
86
91
|
end
|
|
87
92
|
end
|
|
88
93
|
end
|
|
@@ -10,14 +10,56 @@ module ProtoServiceMesh
|
|
|
10
10
|
|
|
11
11
|
# Metadata keys and values the specification fixes on every message.
|
|
12
12
|
module Wire
|
|
13
|
-
|
|
13
|
+
MESH_CONTENT_TYPE_KEY = "Mesh-Content-Type"
|
|
14
14
|
CONTENT_TYPE = "application/x-protobuf"
|
|
15
|
+
MESH_STATUS_KEY = "Mesh-Status"
|
|
16
|
+
|
|
17
|
+
# Deprecated. The key older versions send in place of
|
|
18
|
+
# MESH_CONTENT_TYPE_KEY.
|
|
19
|
+
CONTENT_TYPE_KEY = "Content-Type"
|
|
20
|
+
|
|
21
|
+
# Deprecated. The key older versions send in place of MESH_STATUS_KEY.
|
|
15
22
|
GRPC_STATUS_KEY = "Grpc-Status"
|
|
16
23
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
# The keys the library sets itself. Values for them in application
|
|
25
|
+
# metadata are dropped.
|
|
26
|
+
KEYS = [MESH_CONTENT_TYPE_KEY, MESH_STATUS_KEY, CONTENT_TYPE_KEY, GRPC_STATUS_KEY].freeze
|
|
27
|
+
|
|
28
|
+
@warned = {}
|
|
29
|
+
@warned_lock = Mutex.new
|
|
30
|
+
|
|
31
|
+
# Metadata for a message carrying a payload of the method's type: +extra+
|
|
32
|
+
# without KEYS, with MESH_CONTENT_TYPE_KEY, and with CONTENT_TYPE_KEY
|
|
33
|
+
# too when +legacy+ is true.
|
|
34
|
+
def self.metadata(extra = {}, legacy: false)
|
|
35
|
+
out = extra.to_h.except(*KEYS).merge(MESH_CONTENT_TYPE_KEY => CONTENT_TYPE)
|
|
36
|
+
out[CONTENT_TYPE_KEY] = CONTENT_TYPE if legacy
|
|
37
|
+
out
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Whether +metadata+ comes from an older version: it carries
|
|
41
|
+
# CONTENT_TYPE_KEY and no MESH_CONTENT_TYPE_KEY. The first such message on
|
|
42
|
+
# +target+ writes a warning.
|
|
43
|
+
def self.legacy_content_type?(target, metadata)
|
|
44
|
+
deprecated?(target, metadata, CONTENT_TYPE_KEY, MESH_CONTENT_TYPE_KEY)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Whether reply +metadata+ carries GRPC_STATUS_KEY and no
|
|
48
|
+
# MESH_STATUS_KEY. The first such reply on +target+ writes a warning.
|
|
49
|
+
def self.legacy_status?(target, metadata)
|
|
50
|
+
deprecated?(target, metadata, GRPC_STATUS_KEY, MESH_STATUS_KEY)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.deprecated?(target, metadata, old, replacement)
|
|
54
|
+
return false unless metadata.key?(old) && !metadata.key?(replacement)
|
|
55
|
+
|
|
56
|
+
first = @warned_lock.synchronize { @warned.key?([old, target.segments]) ? false : @warned[[old, target.segments]] = true }
|
|
57
|
+
if first
|
|
58
|
+
warn "proto_service_mesh: a message on #{target.segments.inspect} carries the deprecated metadata key #{old} in place of #{replacement}; the sender runs an older version"
|
|
59
|
+
end
|
|
60
|
+
true
|
|
20
61
|
end
|
|
62
|
+
private_class_method :deprecated?
|
|
21
63
|
|
|
22
64
|
# Splits +metadata+ into the message metadata and the transport options:
|
|
23
65
|
# the keys that start with OPTION_PREFIX become options with the prefix
|
|
@@ -40,9 +82,13 @@ module ProtoServiceMesh
|
|
|
40
82
|
split_options(metadata).first
|
|
41
83
|
end
|
|
42
84
|
|
|
43
|
-
# Metadata for a reply whose payload is an encoded google.rpc.Status
|
|
44
|
-
|
|
45
|
-
|
|
85
|
+
# Metadata for a reply whose payload is an encoded google.rpc.Status:
|
|
86
|
+
# metadata(extra, legacy:) with MESH_STATUS_KEY, and with GRPC_STATUS_KEY
|
|
87
|
+
# too when +legacy+ is true.
|
|
88
|
+
def self.status_metadata(error, extra = {}, legacy: false)
|
|
89
|
+
out = metadata(extra, legacy: legacy).merge(MESH_STATUS_KEY => error.proto.code.to_s)
|
|
90
|
+
out[GRPC_STATUS_KEY] = out[MESH_STATUS_KEY] if legacy
|
|
91
|
+
out
|
|
46
92
|
end
|
|
47
93
|
end
|
|
48
94
|
end
|