anycable-core 1.1.0.pre1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -2
- data/README.md +2 -0
- data/lib/anycable/cli.rb +19 -1
- data/lib/anycable/grpc/config.rb +12 -2
- data/lib/anycable/grpc/handler.rb +6 -6
- data/lib/anycable/grpc.rb +0 -8
- data/lib/anycable/middleware.rb +1 -1
- data/lib/anycable/middleware_chain.rb +7 -7
- data/lib/anycable/middlewares/check_version.rb +31 -0
- data/lib/anycable/middlewares/exceptions.rb +3 -3
- data/lib/anycable/rpc/handler.rb +2 -2
- data/lib/anycable/version.rb +1 -1
- data/lib/anycable.rb +1 -0
- data/sig/anycable/cli.rbs +1 -0
- data/sig/anycable/middleware.rbs +1 -1
- data/sig/anycable/middleware_chain.rbs +3 -3
- data/sig/anycable/rpc.rbs +10 -0
- metadata +6 -5
- data/lib/anycable/grpc/check_version.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 113cfc3490f5829915e8e46026b1c7de0672bb8dc5b388a91a1d0c773688aea5
|
4
|
+
data.tar.gz: 877b8c1672dd37169787dd04bdec610810eab8b27084d8bebf16e3a1b3de98f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6f636686bba507d3b88c83541ba2189637ddb6ef2074d635715d4a533fca4480c37b1131db83a9c6e32ad5e2e166316e7c2747b4aca23a9b2620910bedc0774
|
7
|
+
data.tar.gz: 5d32ecbb7ed802e7d153f4aef170b7df5eca8bc8b4d609a725e9853dc7a4d6eb183abeb9a0ffe1615c33d5272c7cb415b86bd621aaccd5a4ea22c892df3a12c6
|
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,23 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
-
## 1.1.
|
5
|
+
## 1.1.2 (2021-09-10) 🤵👰
|
6
|
+
|
7
|
+
- Improved gRPC server args support. ([@palkan][])
|
8
|
+
|
9
|
+
Add ability to declare gRPC server args without namespacing (i.e., `"max_connection_age_ms"` instead of `"grpc.max_connection_age_ms"`). That makes it possible to use ENV vars to provide the gRPC configuration.
|
10
|
+
|
11
|
+
## 1.1.1 (2021-06-05)
|
12
|
+
|
13
|
+
- Fixed error message when RPC implementation is missing. ([@palkan][])
|
14
|
+
|
15
|
+
We haven't extracted `anycable-grpc` yet.
|
16
|
+
|
17
|
+
## 1.1.0 🚸 (2021-06-01)
|
18
|
+
|
19
|
+
- No changes since 1.1.0.rc1.
|
20
|
+
|
21
|
+
## 1.1.0.rc1 (2021-05-12)
|
6
22
|
|
7
23
|
- **BREAKING** Move middlewares from gRPC interceptors to custom implementation. ([@palkan][])
|
8
24
|
|
@@ -12,7 +28,7 @@ The API changed a bit:
|
|
12
28
|
```diff
|
13
29
|
class SomeMiddleware < AnyCable::Middleware
|
14
30
|
- def call(request, rpc_call, rpc_handler)
|
15
|
-
+ def call(rpc_method_name, request)
|
31
|
+
+ def call(rpc_method_name, request, metadata)
|
16
32
|
yield
|
17
33
|
end
|
18
34
|
end
|
data/README.md
CHANGED
@@ -12,6 +12,8 @@ AnyCable allows you to use any WebSocket server (written in any language) as a r
|
|
12
12
|
|
13
13
|
AnyCable uses the same protocol as ActionCable, so you can use its [JavaScript client](https://www.npmjs.com/package/actioncable) without any monkey-patching.
|
14
14
|
|
15
|
+
> [AnyCable Pro](https://docs.anycable.io/pro) has been launched 🚀
|
16
|
+
|
15
17
|
<a href="https://evilmartians.com/">
|
16
18
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
17
19
|
|
data/lib/anycable/cli.rb
CHANGED
@@ -19,6 +19,14 @@ module AnyCable
|
|
19
19
|
# Wait for external process termination (s)
|
20
20
|
WAIT_PROCESS = 2
|
21
21
|
|
22
|
+
# Run CLI inside the current process and shutdown at exit
|
23
|
+
def self.embed!(args = [])
|
24
|
+
new(embedded: true).tap do |cli|
|
25
|
+
cli.run(args)
|
26
|
+
at_exit { cli.shutdown }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
22
30
|
attr_reader :server, :health_server, :embedded
|
23
31
|
alias_method :embedded?, :embedded
|
24
32
|
|
@@ -55,6 +63,8 @@ module AnyCable
|
|
55
63
|
|
56
64
|
verify_server_builder!
|
57
65
|
|
66
|
+
check_version!
|
67
|
+
|
58
68
|
@server = AnyCable.server_builder.call(config)
|
59
69
|
|
60
70
|
# Make sure middlewares are not adding after server has started
|
@@ -242,11 +252,19 @@ module AnyCable
|
|
242
252
|
return if AnyCable.server_builder
|
243
253
|
|
244
254
|
logger.error "AnyCable server builder must be configured. " \
|
245
|
-
"Make sure you've required a gem (e.g. `
|
255
|
+
"Make sure you've required a gem (e.g. `grpc`) or " \
|
246
256
|
"configured `AnyCable.server_builder` yourself"
|
247
257
|
exit(1)
|
248
258
|
end
|
249
259
|
|
260
|
+
def check_version!
|
261
|
+
return unless config.version_check_enabled?
|
262
|
+
|
263
|
+
AnyCable.middleware.use(
|
264
|
+
AnyCable::Middlewares::CheckVersion.new(AnyCable::PROTO_VERSION)
|
265
|
+
)
|
266
|
+
end
|
267
|
+
|
250
268
|
def parse_gem_options!(args)
|
251
269
|
config.parse_options!(args)
|
252
270
|
rescue OptionParser::InvalidOption => e
|
data/lib/anycable/grpc/config.rb
CHANGED
@@ -8,7 +8,7 @@ AnyCable::Config.attr_config(
|
|
8
8
|
rpc_max_waiting_requests: ::GRPC::RpcServer::DEFAULT_MAX_WAITING_REQUESTS,
|
9
9
|
rpc_poll_period: ::GRPC::RpcServer::DEFAULT_POLL_PERIOD,
|
10
10
|
rpc_pool_keep_alive: ::GRPC::Pool::DEFAULT_KEEP_ALIVE,
|
11
|
-
#
|
11
|
+
# https://github.com/grpc/grpc/blob/f526602bff029b8db50a8d57134d72da33d8a752/include/grpc/impl/codegen/grpc_types.h#L141-L351
|
12
12
|
rpc_server_args: {},
|
13
13
|
log_grpc: false
|
14
14
|
)
|
@@ -33,9 +33,19 @@ module AnyCable
|
|
33
33
|
max_waiting_requests: rpc_max_waiting_requests,
|
34
34
|
poll_period: rpc_poll_period,
|
35
35
|
pool_keep_alive: rpc_pool_keep_alive,
|
36
|
-
server_args:
|
36
|
+
server_args: normalized_grpc_server_args
|
37
37
|
}
|
38
38
|
end
|
39
|
+
|
40
|
+
def normalized_grpc_server_args
|
41
|
+
val = rpc_server_args
|
42
|
+
return {} unless val.is_a?(Hash)
|
43
|
+
|
44
|
+
val.transform_keys do |key|
|
45
|
+
skey = key.to_s
|
46
|
+
skey.start_with?("grpc.") ? skey : "grpc.#{skey}"
|
47
|
+
end
|
48
|
+
end
|
39
49
|
end
|
40
50
|
end
|
41
51
|
end
|
@@ -9,16 +9,16 @@ module AnyCable
|
|
9
9
|
# RPC service handler
|
10
10
|
class Handler < AnyCable::GRPC::Service
|
11
11
|
# Handle connection request from WebSocket server
|
12
|
-
def connect(request,
|
13
|
-
AnyCable.rpc_handler.handle(:connect, request)
|
12
|
+
def connect(request, call)
|
13
|
+
AnyCable.rpc_handler.handle(:connect, request, call.metadata)
|
14
14
|
end
|
15
15
|
|
16
|
-
def disconnect(request,
|
17
|
-
AnyCable.rpc_handler.handle(:disconnect, request)
|
16
|
+
def disconnect(request, call)
|
17
|
+
AnyCable.rpc_handler.handle(:disconnect, request, call.metadata)
|
18
18
|
end
|
19
19
|
|
20
|
-
def command(request,
|
21
|
-
AnyCable.rpc_handler.handle(:command, request)
|
20
|
+
def command(request, call)
|
21
|
+
AnyCable.rpc_handler.handle(:command, request, call.metadata)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
data/lib/anycable/grpc.rb
CHANGED
@@ -9,22 +9,14 @@ end
|
|
9
9
|
|
10
10
|
require "anycable/grpc/config"
|
11
11
|
require "anycable/grpc/server"
|
12
|
-
require "anycable/grpc/check_version"
|
13
12
|
|
14
13
|
AnyCable.server_builder = ->(config) {
|
15
14
|
AnyCable.logger.info "gRPC version: #{::GRPC::VERSION}"
|
16
15
|
|
17
16
|
::GRPC.define_singleton_method(:logger) { AnyCable.logger } if config.log_grpc?
|
18
17
|
|
19
|
-
interceptors = []
|
20
|
-
|
21
|
-
if config.version_check_enabled?
|
22
|
-
interceptors << AnyCable::GRPC::CheckVersion.new(AnyCable::PROTO_VERSION)
|
23
|
-
end
|
24
|
-
|
25
18
|
params = config.to_grpc_params
|
26
19
|
params[:host] = config.rpc_host
|
27
|
-
params[:interceptors] = interceptors
|
28
20
|
|
29
21
|
AnyCable::GRPC::Server.new(**params)
|
30
22
|
}
|
data/lib/anycable/middleware.rb
CHANGED
@@ -30,19 +30,19 @@ module AnyCable
|
|
30
30
|
registry
|
31
31
|
end
|
32
32
|
|
33
|
-
def call(method_name, request, &block)
|
34
|
-
return yield(method_name, request) if registry.none?
|
33
|
+
def call(method_name, request, meta = {}, &block)
|
34
|
+
return yield(method_name, request, meta) if registry.none?
|
35
35
|
|
36
|
-
execute_next_middleware(0, method_name, request, block)
|
36
|
+
execute_next_middleware(0, method_name, request, meta, block)
|
37
37
|
end
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
-
def execute_next_middleware(ind, method_name, request, block)
|
42
|
-
return block.call(method_name, request) if ind >= registry.size
|
41
|
+
def execute_next_middleware(ind, method_name, request, meta, block)
|
42
|
+
return block.call(method_name, request, meta) if ind >= registry.size
|
43
43
|
|
44
|
-
registry[ind].call(method_name, request) do
|
45
|
-
execute_next_middleware(ind + 1, method_name, request, block)
|
44
|
+
registry[ind].call(method_name, request, meta) do
|
45
|
+
execute_next_middleware(ind + 1, method_name, request, meta, block)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCable
|
4
|
+
module Middlewares
|
5
|
+
# Checks that RPC client version is compatible with
|
6
|
+
# the current RPC proto version
|
7
|
+
class CheckVersion < AnyCable::Middleware
|
8
|
+
attr_reader :version
|
9
|
+
|
10
|
+
def initialize(version)
|
11
|
+
@version = version
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(_method, _request, meta)
|
15
|
+
check_version(meta) do
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def check_version(metadata)
|
23
|
+
supported_versions = metadata["protov"]&.split(",")
|
24
|
+
return yield if supported_versions&.include?(version)
|
25
|
+
|
26
|
+
raise "Incompatible AnyCable RPC client.\nCurrent server version: #{version}.\n" \
|
27
|
+
"Client supported versions: #{metadata["protov"] || "unknown"}."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module AnyCable
|
4
4
|
module Middlewares
|
5
5
|
class Exceptions < AnyCable::Middleware
|
6
|
-
def call(method_name, request)
|
6
|
+
def call(method_name, request, _meta)
|
7
7
|
yield
|
8
8
|
rescue => exp
|
9
9
|
notify_exception(exp, method_name, request)
|
@@ -16,8 +16,8 @@ module AnyCable
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
def notify_exception(exp, method_name,
|
20
|
-
AnyCable::ExceptionsHandling.notify(exp, method_name.to_s,
|
19
|
+
def notify_exception(exp, method_name, request)
|
20
|
+
AnyCable::ExceptionsHandling.notify(exp, method_name.to_s, request.to_h)
|
21
21
|
end
|
22
22
|
|
23
23
|
def response_class(method_name)
|
data/lib/anycable/rpc/handler.rb
CHANGED
data/lib/anycable/version.rb
CHANGED
data/lib/anycable.rb
CHANGED
data/sig/anycable/cli.rbs
CHANGED
data/sig/anycable/middleware.rbs
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
module AnyCable
|
2
2
|
class MiddlewareChain
|
3
|
-
type rpcHandlerBlock = ^(Symbol, rpcRequest) -> rpcResponse
|
3
|
+
type rpcHandlerBlock = ^(Symbol, rpcRequest, rpcMetadata) -> rpcResponse
|
4
4
|
|
5
5
|
def initialize: () -> void
|
6
6
|
def use: (singleton(Middleware) | Middleware middleware) -> void
|
7
7
|
def freeze: () -> void
|
8
8
|
def to_a: () -> Array[Middleware]
|
9
|
-
def call: (Symbol, rpcRequest) { (Symbol, rpcRequest) -> rpcResponse } -> rpcResponse
|
9
|
+
def call: (Symbol, rpcRequest, ?rpcMetadata) { (Symbol, rpcRequest, rpcMetadata) -> rpcResponse } -> rpcResponse
|
10
10
|
|
11
11
|
private
|
12
12
|
|
13
|
-
def execute_next_middleware: (Integer ind, Symbol, rpcRequest, rpcHandlerBlock block) -> rpcResponse
|
13
|
+
def execute_next_middleware: (Integer ind, Symbol, rpcRequest, rpcMetadata, rpcHandlerBlock block) -> rpcResponse
|
14
14
|
|
15
15
|
attr_reader mu: untyped
|
16
16
|
attr_reader registry: Array[Middleware]
|
data/sig/anycable/rpc.rbs
CHANGED
@@ -4,6 +4,7 @@ module AnyCable
|
|
4
4
|
|
5
5
|
type rpcStatus = 0 | 1 | 2
|
6
6
|
type protoMap = Hash[String, String]
|
7
|
+
type rpcMetadata = Hash[String, String]
|
7
8
|
|
8
9
|
interface _WithEnvState
|
9
10
|
def cstate: () -> protoMap?
|
@@ -60,6 +61,7 @@ module AnyCable
|
|
60
61
|
include _WithEnv
|
61
62
|
|
62
63
|
def initialize: (?env: Env) -> void
|
64
|
+
def to_h: () -> Hash[String, untyped]
|
63
65
|
end
|
64
66
|
|
65
67
|
class ConnectionResponse
|
@@ -78,6 +80,8 @@ module AnyCable
|
|
78
80
|
?error_msg: String,
|
79
81
|
?env: EnvResponse
|
80
82
|
) -> void
|
83
|
+
|
84
|
+
def to_h: () -> Hash[String, untyped]
|
81
85
|
end
|
82
86
|
|
83
87
|
class CommandMessage
|
@@ -94,6 +98,8 @@ module AnyCable
|
|
94
98
|
?connection_identifiers: String,
|
95
99
|
?env: Env
|
96
100
|
) -> void
|
101
|
+
|
102
|
+
def to_h: () -> Hash[String, untyped]
|
97
103
|
end
|
98
104
|
|
99
105
|
class CommandResponse
|
@@ -118,6 +124,8 @@ module AnyCable
|
|
118
124
|
?error_msg: String,
|
119
125
|
?env: EnvResponse
|
120
126
|
) -> void
|
127
|
+
|
128
|
+
def to_h: () -> Hash[String, untyped]
|
121
129
|
end
|
122
130
|
|
123
131
|
class DisconnectRequest
|
@@ -127,6 +135,7 @@ module AnyCable
|
|
127
135
|
attr_accessor subscriptions: Array[String]
|
128
136
|
|
129
137
|
def initialize: (identifiers: String, ?subscriptions: Array[String], ?env: Env) -> void
|
138
|
+
def to_h: () -> Hash[String, untyped]
|
130
139
|
end
|
131
140
|
|
132
141
|
class DisconnectResponse
|
@@ -136,6 +145,7 @@ module AnyCable
|
|
136
145
|
attr_accessor error_msg: String?
|
137
146
|
|
138
147
|
def initialize: (status: rpcStatus, ?error_msg: String) -> void
|
148
|
+
def to_h: () -> Hash[String, untyped]
|
139
149
|
end
|
140
150
|
|
141
151
|
type rpcRequest = ConnectionRequest | DisconnectRequest | CommandMessage
|
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.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: anyway_config
|
@@ -176,7 +176,6 @@ files:
|
|
176
176
|
- lib/anycable/config.rb
|
177
177
|
- lib/anycable/exceptions_handling.rb
|
178
178
|
- lib/anycable/grpc.rb
|
179
|
-
- lib/anycable/grpc/check_version.rb
|
180
179
|
- lib/anycable/grpc/config.rb
|
181
180
|
- lib/anycable/grpc/handler.rb
|
182
181
|
- lib/anycable/grpc/rpc_services_pb.rb
|
@@ -184,6 +183,7 @@ files:
|
|
184
183
|
- lib/anycable/health_server.rb
|
185
184
|
- lib/anycable/middleware.rb
|
186
185
|
- lib/anycable/middleware_chain.rb
|
186
|
+
- lib/anycable/middlewares/check_version.rb
|
187
187
|
- lib/anycable/middlewares/exceptions.rb
|
188
188
|
- lib/anycable/protos/rpc_pb.rb
|
189
189
|
- lib/anycable/rpc.rb
|
@@ -215,6 +215,7 @@ metadata:
|
|
215
215
|
documentation_uri: https://docs.anycable.io/
|
216
216
|
homepage_uri: https://anycable.io/
|
217
217
|
source_code_uri: http://github.com/anycable/anycable
|
218
|
+
funding_uri: https://github.com/sponsors/anycable
|
218
219
|
post_install_message:
|
219
220
|
rdoc_options: []
|
220
221
|
require_paths:
|
@@ -226,9 +227,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
226
227
|
version: 2.6.0
|
227
228
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
228
229
|
requirements:
|
229
|
-
- - "
|
230
|
+
- - ">="
|
230
231
|
- !ruby/object:Gem::Version
|
231
|
-
version:
|
232
|
+
version: '0'
|
232
233
|
requirements: []
|
233
234
|
rubygems_version: 3.2.15
|
234
235
|
signing_key:
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AnyCable
|
4
|
-
module GRPC
|
5
|
-
# Checks that gRPC client version is compatible with
|
6
|
-
# the current RPC proto version
|
7
|
-
class CheckVersion < ::GRPC::ServerInterceptor
|
8
|
-
attr_reader :version
|
9
|
-
|
10
|
-
def initialize(version)
|
11
|
-
@version = version
|
12
|
-
end
|
13
|
-
|
14
|
-
def request_response(request: nil, call: nil, method: nil)
|
15
|
-
# Call only for AnyCable service
|
16
|
-
return yield unless method.receiver.is_a?(AnyCable::GRPC::Handler)
|
17
|
-
|
18
|
-
check_version(call) do
|
19
|
-
yield
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def check_version(call)
|
24
|
-
supported_versions = call.metadata["protov"]&.split(",")
|
25
|
-
return yield if supported_versions&.include?(version)
|
26
|
-
|
27
|
-
raise ::GRPC::Internal,
|
28
|
-
"Incompatible AnyCable RPC client.\nCurrent server version: #{version}.\n" \
|
29
|
-
"Client supported versions: #{call.metadata["protov"] || "unknown"}."
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|