anycable-core 1.3.0 → 1.3.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: 215d37d67fe10f536e6eb2a9b8ae5e53603d4653fb2034aff9abece234da7097
4
- data.tar.gz: 50457dfd126925e875f3bb1ab323df90a0381f13de399f07e20a8cd4f2cab5d7
3
+ metadata.gz: 5eaf888f4c9312a81bbadf980e5279efa1a0403760569b0465a537e6bd2ed291
4
+ data.tar.gz: 85206aa6fb8aac5faa0641c889deb9f4c61d40a27211feffb20ab23590313469
5
5
  SHA512:
6
- metadata.gz: 43eac0f870ba33726095d8801772d3b18dd2a909a937c9c03177aab163d2ee93f92979bcfcf4cb3eb2039e80e3f28ec123d9e215ee07fe4b87fb152510f7b87d
7
- data.tar.gz: be1a5de79d480aa5d0b081354103f325cb3f997d8d134ba325b92d233408696236afedd600c7133ccb307ac7ceb9b16c60e284588942aa83886007384002a372
6
+ metadata.gz: 8eb1685bd731c6904126e0ea75a5f4489f268e97f080df60a6eec9ce3ae79cf7c3477ff5cf4add6541a7b09c21455c1d97ababcc1ad818f119e79ac6faf97e56
7
+ data.tar.gz: 9d5c9882b1eb73901e253f64915c3647c38453357560d9ec836a29163aa3b6f24a10b485b1007751e3600f81a4e4a9cb8eb0a37204af35d87cc216934b7530c2
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.3.1 (2023-05-12)
6
+
7
+ - Fix gRPC health check response for an empty service. ([@palkan][])
8
+
9
+ As per [docs](https://github.com/grpc/grpc/blob/master/doc/health-checking.md), an empty service is used as the key for server's overall health status. So, if we serve any services, we should return `SERVING` status.
10
+
11
+ - Add gRPC health check when using grpc_kit. ([@palkan][])
12
+
5
13
  ## 1.3.0 (2023-02-28)
6
14
 
7
15
  - Add configuration presets. ([@palkan][])
data/README.md CHANGED
@@ -28,6 +28,8 @@ Check out our 📑 [Documentation](https://docs.anycable.io/v1).
28
28
 
29
29
  ## Links
30
30
 
31
+ - [AnyCable off Rails: connecting Twilio streams with Hanami](https://evilmartians.com/chronicles/anycable-goes-off-rails-connecting-twilio-streams-with-hanami)
32
+
31
33
  - [AnyCable 1.0: Four years of real-time web with Ruby and Go](https://evilmartians.com/chronicles/anycable-1-0-four-years-of-real-time-web-with-ruby-and-go)
32
34
 
33
35
  - [AnyCable: Action Cable on steroids!](https://evilmartians.com/chronicles/anycable-actioncable-on-steroids)
@@ -118,7 +118,7 @@ module AnyCable
118
118
  yield http
119
119
  rescue Timeout::Error, *RECOVERABLE_EXCEPTIONS => e
120
120
  retry_count += 1
121
- if MAX_ATTEMPTS < retry_count
121
+ if retry_count > MAX_ATTEMPTS
122
122
  logger.error("Broadcast request failed: #{e.message}")
123
123
  return
124
124
  end
@@ -31,6 +31,7 @@ module AnyCable
31
31
  )
32
32
  options = AnyCable.config.to_nats_params.merge(options)
33
33
  @nats_conn = ::NATS.connect(nil, options)
34
+ setup_listeners(nats_conn)
34
35
  @channel = channel
35
36
  end
36
37
 
@@ -41,6 +42,19 @@ module AnyCable
41
42
  def announce!
42
43
  logger.info "Broadcasting NATS channel: #{channel}"
43
44
  end
45
+
46
+ private
47
+
48
+ def setup_listeners(nats_client)
49
+ nats_client.on_disconnect { logger.info "NATS client disconnected" }
50
+ nats_client.on_reconnect do
51
+ info = nats_client.server_info
52
+ logger.info "NATS client reconnected: host=#{info[:host]}:#{info[:port]} cluster=#{info[:cluster]}"
53
+ end
54
+ nats_client.on_error do |err|
55
+ logger.warn "NATS client error: #{err.message}"
56
+ end
57
+ end
44
58
  end
45
59
  end
46
60
  end
@@ -21,7 +21,7 @@ module AnyCable
21
21
  #
22
22
  # You can override these params:
23
23
  #
24
- # AnyCable.broadcast_adapter = :redis, url: "redis://my_redis", channel: "_any_cable_"
24
+ # AnyCable.broadcast_adapter = :redis, { url: "redis://my_redis", channel: "_any_cable_" }
25
25
  class Redis < Base
26
26
  attr_reader :redis_conn, :channel
27
27
 
@@ -98,7 +98,7 @@ module AnyCable
98
98
  )
99
99
  health_checker.add_status(
100
100
  "",
101
- Grpc::Health::V1::HealthCheckResponse::ServingStatus::NOT_SERVING
101
+ Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING
102
102
  )
103
103
  health_checker
104
104
  end
@@ -0,0 +1,72 @@
1
+ # Copyright 2015 gRPC authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Grpc
16
+ # Health contains classes and modules that support providing a health check
17
+ # service.
18
+ module Health
19
+ # Checker is implementation of the schema-specified health checking service.
20
+ class Checker < V1::Health::Service
21
+ StatusCodes = GRPC::Core::StatusCodes
22
+ HealthCheckResponse = V1::HealthCheckResponse
23
+
24
+ # Initializes the statuses of participating services
25
+ def initialize
26
+ @statuses = {}
27
+ @status_mutex = Mutex.new # guards access to @statuses
28
+ end
29
+
30
+ # Implements the rpc IDL API method
31
+ def check(req, _call)
32
+ status = nil
33
+ @status_mutex.synchronize do
34
+ status = @statuses["#{req.service}"]
35
+ end
36
+ if status.nil?
37
+ fail GRPC::NotFound.new("Service is not found: #{req.service}")
38
+ end
39
+ HealthCheckResponse.new(status: status)
40
+ end
41
+
42
+ # Adds the health status for a given service.
43
+ def add_status(service, status)
44
+ @status_mutex.synchronize { @statuses["#{service}"] = status }
45
+ end
46
+
47
+ # Adds given health status for all given services
48
+ def set_status_for_services(status, *services)
49
+ @status_mutex.synchronize do
50
+ services.each { |service| @statuses["#{service}"] = status }
51
+ end
52
+ end
53
+
54
+ # Adds health status for each service given within hash
55
+ def add_statuses(service_statuses = {})
56
+ @status_mutex.synchronize do
57
+ service_statuses.each_pair { |service, status| @statuses["#{service}"] = status }
58
+ end
59
+ end
60
+
61
+ # Clears the status for the given service.
62
+ def clear_status(service)
63
+ @status_mutex.synchronize { @statuses.delete("#{service}") }
64
+ end
65
+
66
+ # Clears alls the statuses.
67
+ def clear_all
68
+ @status_mutex.synchronize { @statuses = {} }
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ # source: grpc/health/v1/health.proto
5
+
6
+ require 'google/protobuf'
7
+
8
+ Google::Protobuf::DescriptorPool.generated_pool.build do
9
+ add_message "grpc.health.v1.HealthCheckRequest" do
10
+ optional :service, :string, 1
11
+ end
12
+ add_message "grpc.health.v1.HealthCheckResponse" do
13
+ optional :status, :enum, 1, "grpc.health.v1.HealthCheckResponse.ServingStatus"
14
+ end
15
+ add_enum "grpc.health.v1.HealthCheckResponse.ServingStatus" do
16
+ value :UNKNOWN, 0
17
+ value :SERVING, 1
18
+ value :NOT_SERVING, 2
19
+ end
20
+ end
21
+
22
+ module Grpc
23
+ module Health
24
+ module V1
25
+ HealthCheckRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1.HealthCheckRequest").msgclass
26
+ HealthCheckResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1.HealthCheckResponse").msgclass
27
+ HealthCheckResponse::ServingStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1.HealthCheckResponse.ServingStatus").enummodule
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: grpc/health/v1/health.proto for package 'grpc.health.v1'
3
+ # Original file comments:
4
+ # Copyright 2015 The gRPC Authors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # The canonical version of this proto can be found at
19
+ # https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
20
+ #
21
+
22
+ module Grpc
23
+ module Health
24
+ module V1
25
+ module Health
26
+ class Service
27
+
28
+ include GRPC::GenericService
29
+
30
+ self.marshal_class_method = :encode
31
+ self.unmarshal_class_method = :decode
32
+ self.service_name = 'grpc.health.v1.Health'
33
+
34
+ rpc :Check, HealthCheckRequest, HealthCheckResponse
35
+ end
36
+
37
+ Stub = Service.rpc_stub_class
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,6 +2,10 @@
2
2
 
3
3
  require "anycable/grpc/handler"
4
4
 
5
+ require_relative "./health_pb"
6
+ require_relative "./health_services_pb"
7
+ require_relative "./health_checker"
8
+
5
9
  module AnyCable
6
10
  module GRPC
7
11
  raise LoadError, "AnyCable::GRPC::Server has been already loaded!" if defined?(AnyCable::GRPC::Server)
@@ -77,8 +81,8 @@ module AnyCable
77
81
 
78
82
  loop do
79
83
  sock = TCPSocket.new(hostname, port, connect_timeout: 1)
80
- stub = AnyCable::GRPC::Stub.new(sock)
81
- stub.connect(AnyCable::ConnectionRequest.new(env: {}))
84
+ stub = ::Grpc::Health::V1::Health::Stub.new(sock)
85
+ stub.check(::Grpc::Health::V1::HealthCheckRequest.new)
82
86
  sock.close
83
87
  break
84
88
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
@@ -126,8 +130,22 @@ module AnyCable
126
130
 
127
131
  ::GrpcKit::Server.new(min_pool_size: pool_size, max_pool_size: pool_size).tap do |server|
128
132
  server.handle(AnyCable::GRPC::Handler)
133
+ server.handle(build_health_checker)
129
134
  end
130
135
  end
136
+
137
+ def build_health_checker
138
+ health_checker = ::Grpc::Health::Checker.new
139
+ health_checker.add_status(
140
+ "anycable.RPC",
141
+ ::Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING
142
+ )
143
+ health_checker.add_status(
144
+ "",
145
+ ::Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING
146
+ )
147
+ health_checker
148
+ end
131
149
  end
132
150
  end
133
151
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AnyCable
4
- VERSION = "1.3.0"
4
+ VERSION = "1.3.1"
5
5
  end
@@ -5,6 +5,10 @@ module AnyCable
5
5
  attr_reader channel: String
6
6
 
7
7
  def initialize: (?channel: String channel, **untyped options) -> void
8
+
9
+ private
10
+
11
+ def setup_listeners: (untyped nats_conn) -> void
8
12
  end
9
13
  end
10
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-01 00:00:00.000000000 Z
11
+ date: 2023-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anyway_config
@@ -210,6 +210,9 @@ files:
210
210
  - lib/anycable/grpc/rpc_services_pb.rb
211
211
  - lib/anycable/grpc/server.rb
212
212
  - lib/anycable/grpc_kit.rb
213
+ - lib/anycable/grpc_kit/health_checker.rb
214
+ - lib/anycable/grpc_kit/health_pb.rb
215
+ - lib/anycable/grpc_kit/health_services_pb.rb
213
216
  - lib/anycable/grpc_kit/server.rb
214
217
  - lib/anycable/health_server.rb
215
218
  - lib/anycable/middleware.rb
@@ -278,7 +281,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
278
281
  - !ruby/object:Gem::Version
279
282
  version: '0'
280
283
  requirements: []
281
- rubygems_version: 3.4.6
284
+ rubygems_version: 3.4.8
282
285
  signing_key:
283
286
  specification_version: 4
284
287
  summary: AnyCable core RPC implementation