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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +2 -0
- data/lib/anycable/broadcast_adapters/http.rb +1 -1
- data/lib/anycable/broadcast_adapters/nats.rb +14 -0
- data/lib/anycable/broadcast_adapters/redis.rb +1 -1
- data/lib/anycable/grpc/server.rb +1 -1
- data/lib/anycable/grpc_kit/health_checker.rb +72 -0
- data/lib/anycable/grpc_kit/health_pb.rb +30 -0
- data/lib/anycable/grpc_kit/health_services_pb.rb +41 -0
- data/lib/anycable/grpc_kit/server.rb +20 -2
- data/lib/anycable/version.rb +1 -1
- data/sig/anycable/broadcast_adapters/nats.rbs +4 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5eaf888f4c9312a81bbadf980e5279efa1a0403760569b0465a537e6bd2ed291
|
4
|
+
data.tar.gz: 85206aa6fb8aac5faa0641c889deb9f4c61d40a27211feffb20ab23590313469
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
|
data/lib/anycable/grpc/server.rb
CHANGED
@@ -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 =
|
81
|
-
stub.
|
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
|
data/lib/anycable/version.rb
CHANGED
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.
|
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-
|
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.
|
284
|
+
rubygems_version: 3.4.8
|
282
285
|
signing_key:
|
283
286
|
specification_version: 4
|
284
287
|
summary: AnyCable core RPC implementation
|