grpc_service_mesh 0.16.0 → 0.17.1

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: 241b9590dcd6bc041d6e575e74ece01d4fa165d4380c16a275b9823a05cadb94
4
- data.tar.gz: a5d716495824f89fc9f3bf9eaf6ed1b163459fee48d5f8270d4a8905538ac5c5
3
+ metadata.gz: 21c351668cf435aee69b1af4ce158f3d6ba6c82016d97a0352bf06498507f801
4
+ data.tar.gz: 97ecc19ca596654545b66a38270b39d52c79b961789b45858045d1b542eebf00
5
5
  SHA512:
6
- metadata.gz: 821daff5b253055c2baa16b9ebc41e38f624752ac0b21d4d01d510680327daaf7a040c8c740aa03211258d2d60a443464a0620411e146abb765f21cb1f7bffb1
7
- data.tar.gz: 01417c334a7980dc1da34d37266b3caeba22d01ec95d0db793abab0f025ee548c919e4754ccddfc7597a809571e144d7ca86a0d28ef13457964cabdbe4520bec
6
+ metadata.gz: f77a8d39aca21eeccfcc78132dfdfdb1b3b6a886dc83124e286153135013959317ad4e5da8261a1cec5dc953131887859384c26084b4268e2129b8a8b6249b1a
7
+ data.tar.gz: 60e395b62bb24dbc11eb59081612bc638cbbd617279e459d5804bf3402672a52e3ab48ebdf8e7335b33a562592756020557cc8078e3f3c5131e7d3a2bd4683b2
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # grpc-service-mesh-ruby
2
2
 
3
- `grpc_service_mesh` is the Ruby implementation of the
3
+ grpc-service-mesh-ruby is the Ruby implementation of the
4
4
  [gRPC Service Mesh API](https://github.com/Paymentbox-com/grpc-service-mesh-api).
5
5
  It carries protobuf messages over any transport that implements the
6
6
  [Service Mesh API Specification](https://github.com/Paymentbox-com/service-mesh-api)
@@ -22,13 +22,9 @@ repository and lives in a definitions project.
22
22
 
23
23
  ## Install
24
24
 
25
- The gem and its `service_mesh` dependency are installed from their
26
- repositories at a tag, so the Gemfile names both git sources.
27
-
28
25
  ```ruby
29
26
  # Gemfile
30
- gem "grpc_service_mesh", git: "https://github.com/Paymentbox-com/grpc-service-mesh-ruby", tag: "v0.15.0"
31
- gem "service_mesh", git: "https://github.com/Paymentbox-com/service-mesh-ruby", tag: "v0.4.2"
27
+ gem "grpc_service_mesh"
32
28
  ```
33
29
 
34
30
  Requires Ruby 3.3 or newer. The gem depends on `service_mesh`,
@@ -9,29 +9,46 @@ module GrpcServiceMesh
9
9
  @subscribers = []
10
10
  end
11
11
 
12
- # Adds the bindings of +service+, an RPCService instance. Every binding
13
- # is kept, so two registrations of one Target hand the transport two
14
- # bindings for it.
15
- def register(service)
16
- @endpoints.concat(service.endpoints)
17
- @subscribers.concat(service.subscribers)
12
+ # Adds the endpoints and subscribers of +service+, an RPCService
13
+ # instance. +consumer_groups+ maps a target of the service to the
14
+ # consumer group of its endpoint or subscriber, replacing the one the
15
+ # generated code carries. "" removes it, so the runtime's deployment group
16
+ # applies, and ServiceMesh::CONSUMER_GROUP_NONE means no group. Raises
17
+ # ArgumentError, and registers nothing, when a target is not one of the
18
+ # service's. Every endpoint and subscriber is kept, so two registrations of
19
+ # one target hand the transport two of them.
20
+ def register(service, consumer_groups: {})
21
+ endpoints = service.endpoints
22
+ subscribers = service.subscribers
23
+ consumer_groups.each do |target, group|
24
+ found = false
25
+ apply = lambda do |served|
26
+ next served unless served.target.same_channel?(target)
27
+
28
+ found = true
29
+ with_group(served, group)
30
+ end
31
+ endpoints = endpoints.map(&apply)
32
+ subscribers = subscribers.map(&apply)
33
+ raise ArgumentError, "consumer_groups names target #{target.segments.inspect}, which is not an rpc method of #{service.class}" unless found
34
+ end
35
+ @endpoints.concat(endpoints)
36
+ @subscribers.concat(subscribers)
18
37
  nil
19
38
  end
20
39
 
21
- # Endpoints whose Target carries +deployment_group+.
22
- def endpoints(deployment_group)
23
- @endpoints.select { |e| in_group?(e, deployment_group) }
24
- end
40
+ # Every registered Endpoint.
41
+ attr_reader :endpoints
25
42
 
26
- # Subscribers whose Target carries +deployment_group+.
27
- def subscribers(deployment_group)
28
- @subscribers.select { |s| in_group?(s, deployment_group) }
29
- end
43
+ # Every registered Subscriber.
44
+ attr_reader :subscribers
30
45
 
31
46
  private
32
47
 
33
- def in_group?(binding, deployment_group)
34
- binding.target.metadata[ServiceMesh::DEPLOYMENT_GROUP_KEY] == deployment_group
48
+ def with_group(served, group)
49
+ metadata = served.metadata.to_h.except(ServiceMesh::CONSUMER_GROUP_KEY)
50
+ metadata[ServiceMesh::CONSUMER_GROUP_KEY] = group unless group.to_s.empty?
51
+ served.with(metadata: metadata)
35
52
  end
36
53
  end
37
54
  end
@@ -2,12 +2,13 @@
2
2
 
3
3
  module GrpcServiceMesh
4
4
  # One rpc method as the generated code declares it. +owner+ is the class
5
- # the declaration appeared in.
6
- Rpc = Data.define(:name, :target, :input, :output, :kind, :owner) do
7
- def initialize(name:, target:, input:, kind:, owner:, output: nil)
5
+ # the declaration appeared in. +consumer_group+ is the method's
6
+ # consumer_group option, or nil when it has none.
7
+ Rpc = Data.define(:name, :target, :input, :output, :kind, :owner, :consumer_group) do
8
+ def initialize(name:, target:, input:, kind:, owner:, output: nil, consumer_group: nil)
8
9
  raise ServiceMesh::KindMismatch, "rpc #{name}: declared #{kind}, target is #{target.kind}" unless kind == target.kind
9
10
 
10
- super(name: name, target: target, input: input, output: output, kind: kind, owner: owner)
11
+ super(name: name, target: target, input: input, output: output, kind: kind, owner: owner, consumer_group: consumer_group)
11
12
  end
12
13
 
13
14
  def route? = kind == :route
@@ -17,9 +18,10 @@ module GrpcServiceMesh
17
18
  module RpcDSL
18
19
  # Declares one rpc. +name+ is the Ruby method name, +target+ the
19
20
  # ServiceMesh::Target, +input+ and +output+ the message classes, +kind+
20
- # :route or :topic. +output+ is not used for a topic.
21
- def rpc(name, target:, input:, kind:, output: nil)
22
- rpc = Rpc.new(name: name, target: target, input: input, output: output, kind: kind, owner: self)
21
+ # :route or :topic, and +consumer_group+ the method's consumer_group
22
+ # option. +output+ is not used for a topic.
23
+ def rpc(name, target:, input:, kind:, output: nil, consumer_group: nil)
24
+ rpc = Rpc.new(name: name, target: target, input: input, output: output, kind: kind, owner: self, consumer_group: consumer_group)
23
25
  own_rpcs[rpc.name] = rpc
24
26
  define_rpc(rpc)
25
27
  rpc
@@ -2,32 +2,31 @@
2
2
 
3
3
  module GrpcServiceMesh
4
4
  # The service process for one transport and one deployment group. new
5
- # takes the transport's client from the process router and the matching
6
- # bindings from the process registry, and builds the transport's Runtime
7
- # from them with the +runtime+ constructor.
5
+ # takes the transport's client from the process router and every endpoint
6
+ # and subscriber in the process registry whose target is on that transport,
7
+ # and builds the transport's Runtime from them with the +runtime+
8
+ # constructor.
8
9
  class RPCRuntime
9
10
  attr_reader :transport, :deployment_group, :t_runtime
10
11
 
11
12
  # +runtime+ is ->(client, config, endpoints:, subscribers:) returning the
12
13
  # transport's Runtime. It receives +config+ with deployment_group set.
13
- # +endpoints+ and +subscribers+, when given, replace the registry's list
14
- # of that kind, and [] serves none. Raises ArgumentError for a given
15
- # binding whose Target's deployment_group or transport is not this
16
- # runtime's, UnknownTransport, and whatever +runtime+ raises.
17
- def initialize(transport:, deployment_group:, runtime:, config: {}, endpoints: nil, subscribers: nil)
14
+ # Endpoints and subscribers of other transports are left for those
15
+ # transports' runtimes. Raises ArgumentError when +runtime+ is not
16
+ # callable, UnknownTransport, and whatever +runtime+ raises.
17
+ def initialize(transport:, deployment_group:, runtime:, config: {})
18
18
  raise ArgumentError, "runtime: must be a callable that builds the transport's Runtime, got #{runtime.inspect}" unless runtime.respond_to?(:call)
19
19
 
20
20
  registry = GrpcServiceMesh.registry
21
21
  client = GrpcServiceMesh.transport_router.client(transport)
22
22
  @transport = transport
23
23
  @deployment_group = deployment_group
24
- endpoints&.each { |binding| check_target("endpoint", binding.target) }
25
- subscribers&.each { |binding| check_target("subscriber", binding.target) }
24
+ on_transport = ->(served) { served.target.metadata["transport"] == transport }
26
25
  @t_runtime = runtime.call(
27
26
  client,
28
27
  config.to_h.merge(ServiceMesh::DEPLOYMENT_GROUP_KEY => deployment_group),
29
- endpoints: endpoints || registry.endpoints(deployment_group),
30
- subscribers: subscribers || registry.subscribers(deployment_group)
28
+ endpoints: registry.endpoints.select(&on_transport),
29
+ subscribers: registry.subscribers.select(&on_transport)
31
30
  )
32
31
  end
33
32
 
@@ -38,16 +37,5 @@ module GrpcServiceMesh
38
37
  def running? = @t_runtime.running?
39
38
 
40
39
  def client = @t_runtime.client
41
-
42
- private
43
-
44
- def check_target(kind, target)
45
- {ServiceMesh::DEPLOYMENT_GROUP_KEY => @deployment_group, "transport" => @transport}.each do |key, want|
46
- got = target.metadata[key]
47
- next if got == want
48
-
49
- raise ArgumentError, "#{kind} #{target.segments.inspect} has #{key} #{got.inspect}, want #{want.inspect}"
50
- end
51
- end
52
40
  end
53
41
  end
@@ -10,18 +10,28 @@ module GrpcServiceMesh
10
10
  class RPCService
11
11
  extend RpcDSL
12
12
 
13
- # A ServiceMesh::Endpoint for each route rpc this instance implements.
13
+ # A ServiceMesh::Endpoint for each route rpc this instance implements,
14
+ # with the rpc's consumer_group in its metadata when it has one.
14
15
  def endpoints
15
- implemented.select(&:route?).map { |rpc| ServiceMesh::Endpoint.new(target: rpc.target, handler: endpoint_handler(rpc)) }
16
+ implemented.select(&:route?).map do |rpc|
17
+ ServiceMesh::Endpoint.new(target: rpc.target, handler: endpoint_handler(rpc), metadata: consumer_group_metadata(rpc))
18
+ end
16
19
  end
17
20
 
18
- # A ServiceMesh::Subscriber for each topic rpc this instance implements.
21
+ # A ServiceMesh::Subscriber for each topic rpc this instance implements,
22
+ # with the rpc's consumer_group in its metadata when it has one.
19
23
  def subscribers
20
- implemented.reject(&:route?).map { |rpc| ServiceMesh::Subscriber.new(target: rpc.target, handler: subscriber_handler(rpc)) }
24
+ implemented.reject(&:route?).map do |rpc|
25
+ ServiceMesh::Subscriber.new(target: rpc.target, handler: subscriber_handler(rpc), metadata: consumer_group_metadata(rpc))
26
+ end
21
27
  end
22
28
 
23
29
  private
24
30
 
31
+ def consumer_group_metadata(rpc)
32
+ rpc.consumer_group.nil? ? {} : {ServiceMesh::CONSUMER_GROUP_KEY => rpc.consumer_group}
33
+ end
34
+
25
35
  # Rpcs whose method is defined in the declaring class or below it.
26
36
  def implemented
27
37
  self.class.rpcs.values.select do |rpc|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrpcServiceMesh
4
- VERSION = "0.16.0"
4
+ VERSION = "0.17.1"
5
5
  end
@@ -35,8 +35,8 @@ module GrpcServiceMesh
35
35
  end
36
36
 
37
37
  # Shortcut for registry.register.
38
- def register(service)
39
- registry.register(service)
38
+ def register(service, consumer_groups: {})
39
+ registry.register(service, consumer_groups: consumer_groups)
40
40
  end
41
41
  end
42
42
  end
@@ -7,7 +7,7 @@ require 'google/protobuf'
7
7
  require 'google/protobuf/descriptor_pb'
8
8
 
9
9
 
10
- descriptor_data = "\n\x12mesh/options.proto\x12\x04mesh\x1a google/protobuf/descriptor.proto*\x1c\n\x04Kind\x12\t\n\x05ROUTE\x10\x00\x12\t\n\x05TOPIC\x10\x01::\n\x04kind\x12\x1e.google.protobuf.MethodOptions\x18\xd1\x86\x03 \x01(\x0e\x32\n.mesh.Kind:8\n\x0e\x63onsumer_group\x12\x1e.google.protobuf.MethodOptions\x18\xd2\x86\x03 \x01(\t:8\n\x10\x64\x65ployment_group\x12\x1c.google.protobuf.FileOptions\x18\xd3\x86\x03 \x01(\t:1\n\ttransport\x12\x1c.google.protobuf.FileOptions\x18\xd4\x86\x03 \x01(\t:3\n\x0broot_prefix\x12\x1c.google.protobuf.FileOptions\x18\xd5\x86\x03 \x01(\tB<Z:github.com/Paymentbox-com/grpc-service-mesh-go/meshoptionsb\x06proto3"
10
+ descriptor_data = "\n\x12mesh/options.proto\x12\x04mesh\x1a google/protobuf/descriptor.proto*\x1c\n\x04Kind\x12\t\n\x05ROUTE\x10\x00\x12\t\n\x05TOPIC\x10\x01::\n\x04kind\x12\x1e.google.protobuf.MethodOptions\x18\xd1\x86\x03 \x01(\x0e\x32\n.mesh.Kind:8\n\x0e\x63onsumer_group\x12\x1e.google.protobuf.MethodOptions\x18\xd2\x86\x03 \x01(\t:1\n\ttransport\x12\x1c.google.protobuf.FileOptions\x18\xd4\x86\x03 \x01(\t:3\n\x0broot_prefix\x12\x1c.google.protobuf.FileOptions\x18\xd5\x86\x03 \x01(\tB<Z:github.com/Paymentbox-com/grpc-service-mesh-go/meshoptionsb\x06proto3"
11
11
 
12
12
  pool = ::Google::Protobuf::DescriptorPool.generated_pool
13
13
  pool.add_serialized_file(descriptor_data)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grpc_service_mesh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.17.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryant Morrill
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-09-29 00:00:00.000000000 Z
12
+ date: 2026-09-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-protobuf