anycable 0.6.0 → 1.0.0.preview1
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 +93 -5
- data/MIT-LICENSE +1 -1
- data/README.md +13 -6
- data/bin/anycable +1 -1
- data/bin/anycabled +30 -0
- data/lib/anycable.rb +8 -13
- data/lib/anycable/broadcast_adapters.rb +3 -3
- data/lib/anycable/broadcast_adapters/redis.rb +2 -2
- data/lib/anycable/cli.rb +16 -6
- data/lib/anycable/config.rb +10 -5
- data/lib/anycable/exceptions_handling.rb +13 -9
- data/lib/anycable/health_server.rb +2 -3
- data/lib/anycable/middleware.rb +3 -0
- data/lib/anycable/middleware_chain.rb +2 -2
- data/lib/anycable/middlewares/check_version.rb +24 -0
- data/lib/anycable/rpc.rb +76 -0
- data/lib/anycable/rpc/rpc_pb.rb +54 -39
- data/lib/anycable/rpc/rpc_services_pb.rb +4 -3
- data/lib/anycable/rpc_handler.rb +77 -24
- data/lib/anycable/rspec.rb +6 -0
- data/lib/anycable/rspec/rpc_command_context.rb +20 -0
- data/lib/anycable/rspec/rpc_stub_context.rb +13 -0
- data/lib/anycable/rspec/with_grpc_server.rb +15 -0
- data/lib/anycable/server.rb +4 -48
- data/lib/anycable/socket.rb +39 -2
- data/lib/anycable/version.rb +1 -1
- metadata +34 -72
- data/.github/ISSUE_TEMPLATE.md +0 -25
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -31
- data/.gitignore +0 -40
- data/.hound.yml +0 -3
- data/.rubocop.yml +0 -71
- data/.travis.yml +0 -12
- data/Gemfile +0 -8
- data/Makefile +0 -5
- data/PITCHME.md +0 -139
- data/PITCHME.yaml +0 -1
- data/Rakefile +0 -8
- data/anycable.gemspec +0 -35
- data/assets/Memory3.png +0 -0
- data/assets/Memory5.png +0 -0
- data/assets/RTT3.png +0 -0
- data/assets/RTT5.png +0 -0
- data/assets/Scheme1.png +0 -0
- data/assets/Scheme2.png +0 -0
- data/assets/cpu_chart.gif +0 -0
- data/assets/cpu_chart2.gif +0 -0
- data/assets/evlms.png +0 -0
- data/benchmarks/.gitignore +0 -2
- data/benchmarks/2017-02-12.md +0 -308
- data/benchmarks/2018-03-04.md +0 -192
- data/benchmarks/2018-05-27-rpc-bench.md +0 -57
- data/benchmarks/2018-10-27.md +0 -181
- data/benchmarks/HowTo.md +0 -23
- data/benchmarks/ansible.cfg +0 -9
- data/benchmarks/assets/2018-10-27-action-cable-rss.png +0 -0
- data/benchmarks/assets/2018-10-27-action-cable-rtt.png +0 -0
- data/benchmarks/assets/2018-10-27-anycable-rss.png +0 -0
- data/benchmarks/assets/2018-10-27-anycable-rtt.png +0 -0
- data/benchmarks/assets/2018-10-27-async-rss.png +0 -0
- data/benchmarks/assets/2018-10-27-async-rtt.png +0 -0
- data/benchmarks/assets/2018-10-27-falcon-cable-rss.png +0 -0
- data/benchmarks/assets/2018-10-27-falcon-cable-rtt.png +0 -0
- data/benchmarks/assets/2018-10-27-iodine-cable-rss.png +0 -0
- data/benchmarks/assets/2018-10-27-iodine-cable-rtt.png +0 -0
- data/benchmarks/assets/2018-10-27-plezi-rss.png +0 -0
- data/benchmarks/assets/2018-10-27-plezi-rtt.png +0 -0
- data/benchmarks/bench.png +0 -0
- data/benchmarks/benchmark.yml +0 -69
- data/benchmarks/hosts +0 -5
- data/benchmarks/rtt_plot.py +0 -74
- data/benchmarks/rtt_plot_test.py +0 -16
- data/benchmarks/servers.yml +0 -58
- data/circle.yml +0 -8
- data/etc/bug_report_template.rb +0 -76
- data/lib/anycable/handler/capture_exceptions.rb +0 -39
- data/protos/rpc.proto +0 -55
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_context "anycable:rpc:command" do
|
4
|
+
include_context "anycable:rpc:stub"
|
5
|
+
|
6
|
+
let(:command) { "" }
|
7
|
+
let(:channel_id) { "" }
|
8
|
+
let(:identifiers) { {} }
|
9
|
+
let(:data) { {} }
|
10
|
+
|
11
|
+
let(:request) do
|
12
|
+
AnyCable::CommandMessage.new(
|
13
|
+
command: command,
|
14
|
+
identifier: channel_id,
|
15
|
+
connection_identifiers: identifiers.to_json,
|
16
|
+
data: data.to_json,
|
17
|
+
env: env
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_context "anycable:rpc:stub" do
|
4
|
+
before(:all) do
|
5
|
+
@service = AnyCable::RPC::Stub.new(AnyCable.config.rpc_host, :this_channel_is_insecure)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:service) { @service }
|
9
|
+
|
10
|
+
let(:url) { "example.com/cable" }
|
11
|
+
let(:headers) { {} }
|
12
|
+
let(:env) { AnyCable::Env.new(url: url, headers: headers) }
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_context "anycable:rpc:server" do
|
4
|
+
before(:all) do
|
5
|
+
@server = AnyCable::Server.new(
|
6
|
+
host: AnyCable.config.rpc_host,
|
7
|
+
**AnyCable.config.to_grpc_params,
|
8
|
+
interceptors: AnyCable.middleware.to_a
|
9
|
+
)
|
10
|
+
|
11
|
+
@server.start
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:all) { @server.stop }
|
15
|
+
end
|
data/lib/anycable/server.rb
CHANGED
@@ -12,8 +12,8 @@ module AnyCable
|
|
12
12
|
#
|
13
13
|
# Basic example:
|
14
14
|
#
|
15
|
-
# # create new server listening on
|
16
|
-
# server = AnyCable::Server.new(host: "
|
15
|
+
# # create new server listening on the loopback interface with 50051 port
|
16
|
+
# server = AnyCable::Server.new(host: "127.0.0.1:50051")
|
17
17
|
#
|
18
18
|
# # run gRPC server in bakground
|
19
19
|
# server.start
|
@@ -21,53 +21,9 @@ module AnyCable
|
|
21
21
|
# # stop server
|
22
22
|
# server.stop
|
23
23
|
class Server
|
24
|
-
class << self
|
25
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
26
|
-
def start(**options)
|
27
|
-
warn <<~DEPRECATION
|
28
|
-
Using AnyCable::Server.start is deprecated!
|
29
|
-
Please, use anycable CLI instead.
|
30
|
-
|
31
|
-
See https://docs.anycable.io/#upgrade_to_0_6_0
|
32
|
-
DEPRECATION
|
33
|
-
|
34
|
-
AnyCable.server_callbacks.each(&:call)
|
35
|
-
|
36
|
-
server = new(
|
37
|
-
host: AnyCable.config.rpc_host,
|
38
|
-
**AnyCable.config.to_grpc_params,
|
39
|
-
interceptors: AnyCable.middleware.to_a,
|
40
|
-
**options
|
41
|
-
)
|
42
|
-
|
43
|
-
AnyCable.middleware.freeze
|
44
|
-
|
45
|
-
if AnyCable.config.http_health_port_provided?
|
46
|
-
health_server = AnyCable::HealthServer.new(
|
47
|
-
server,
|
48
|
-
**AnyCable.config.to_http_health_params
|
49
|
-
)
|
50
|
-
health_server.start
|
51
|
-
end
|
52
|
-
|
53
|
-
at_exit do
|
54
|
-
server.stop
|
55
|
-
health_server&.stop
|
56
|
-
end
|
57
|
-
|
58
|
-
AnyCable.logger.info "Broadcasting Redis channel: #{AnyCable.config.redis_channel}"
|
59
|
-
|
60
|
-
server.start
|
61
|
-
server.wait_till_terminated
|
62
|
-
end
|
63
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
64
|
-
end
|
65
|
-
|
66
|
-
DEFAULT_HOST = "0.0.0.0:50051"
|
67
|
-
|
68
24
|
attr_reader :grpc_server, :host
|
69
25
|
|
70
|
-
def initialize(host
|
26
|
+
def initialize(host:, logger: AnyCable.logger, **options)
|
71
27
|
@logger = logger
|
72
28
|
@host = host
|
73
29
|
@grpc_server = build_server(options)
|
@@ -117,7 +73,7 @@ module AnyCable
|
|
117
73
|
attr_reader :logger, :start_thread
|
118
74
|
|
119
75
|
def build_server(options)
|
120
|
-
GRPC::RpcServer.new(options).tap do |server|
|
76
|
+
GRPC::RpcServer.new(**options).tap do |server|
|
121
77
|
server.add_http2_port(host, :this_port_is_insecure)
|
122
78
|
server.handle(AnyCable::RPCHandler)
|
123
79
|
server.handle(build_health_checker)
|
data/lib/anycable/socket.rb
CHANGED
@@ -3,11 +3,41 @@
|
|
3
3
|
module AnyCable
|
4
4
|
# Socket mock to be used with application connection
|
5
5
|
class Socket
|
6
|
-
|
6
|
+
# Represents the per-connection store
|
7
|
+
# (for example, used to keep session beetween RPC calls)
|
8
|
+
class State
|
9
|
+
attr_reader :dirty_keys, :source
|
10
|
+
|
11
|
+
def initialize(from)
|
12
|
+
@source = from
|
13
|
+
@dirty_keys = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def read(key)
|
17
|
+
source&.[](key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(key, val)
|
21
|
+
return if source&.[](key) == val
|
22
|
+
|
23
|
+
@source ||= {}
|
24
|
+
@dirty_keys ||= []
|
25
|
+
dirty_keys << key
|
26
|
+
source[key] = val
|
27
|
+
end
|
28
|
+
|
29
|
+
def changed_fields
|
30
|
+
return unless source && dirty_keys
|
31
|
+
source.slice(*dirty_keys)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :transmissions, :env, :cstate
|
7
36
|
|
8
37
|
def initialize(env: nil)
|
9
38
|
@transmissions = []
|
10
39
|
@env = env
|
40
|
+
@cstate = env["anycable.cstate"] = State.new(env["anycable.raw_cstate"])
|
11
41
|
end
|
12
42
|
|
13
43
|
def transmit(websocket_message)
|
@@ -32,7 +62,6 @@ module AnyCable
|
|
32
62
|
|
33
63
|
def close
|
34
64
|
@closed = true
|
35
|
-
@transmissions.clear
|
36
65
|
@streams&.clear
|
37
66
|
@stop_all_streams = true
|
38
67
|
end
|
@@ -44,5 +73,13 @@ module AnyCable
|
|
44
73
|
def stop_streams?
|
45
74
|
@stop_all_streams == true
|
46
75
|
end
|
76
|
+
|
77
|
+
def session
|
78
|
+
cstate.read(SESSION_KEY)
|
79
|
+
end
|
80
|
+
|
81
|
+
def session=(val)
|
82
|
+
cstate.write(SESSION_KEY, val)
|
83
|
+
end
|
47
84
|
end
|
48
85
|
end
|
data/lib/anycable/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anycable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.preview1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: anyway_config
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.4.
|
19
|
+
version: 1.4.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.4.
|
26
|
+
version: 1.4.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: grpc
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1.
|
33
|
+
version: '1.17'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1.
|
40
|
+
version: '1.17'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: redis
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,14 +56,14 @@ dependencies:
|
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
@@ -109,19 +109,19 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '3.5'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name: rubocop
|
112
|
+
name: rubocop-md
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
117
|
+
version: '0.3'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
124
|
+
version: '0.3'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: simplecov
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,102 +137,65 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 0.3.8
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: standard
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- - "
|
143
|
+
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 0.1.7
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- - "
|
150
|
+
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 0.1.7
|
153
153
|
description: AnyCable is a polyglot replacement for ActionCable-compatible servers
|
154
154
|
email:
|
155
155
|
- dementiev.vm@gmail.com
|
156
156
|
executables:
|
157
157
|
- anycable
|
158
|
+
- anycabled
|
158
159
|
extensions: []
|
159
160
|
extra_rdoc_files: []
|
160
161
|
files:
|
161
|
-
- ".github/ISSUE_TEMPLATE.md"
|
162
|
-
- ".github/PULL_REQUEST_TEMPLATE.md"
|
163
|
-
- ".gitignore"
|
164
|
-
- ".hound.yml"
|
165
|
-
- ".rubocop.yml"
|
166
|
-
- ".travis.yml"
|
167
162
|
- CHANGELOG.md
|
168
|
-
- Gemfile
|
169
163
|
- MIT-LICENSE
|
170
|
-
- Makefile
|
171
|
-
- PITCHME.md
|
172
|
-
- PITCHME.yaml
|
173
164
|
- README.md
|
174
|
-
- Rakefile
|
175
|
-
- anycable.gemspec
|
176
|
-
- assets/Memory3.png
|
177
|
-
- assets/Memory5.png
|
178
|
-
- assets/RTT3.png
|
179
|
-
- assets/RTT5.png
|
180
|
-
- assets/Scheme1.png
|
181
|
-
- assets/Scheme2.png
|
182
|
-
- assets/cpu_chart.gif
|
183
|
-
- assets/cpu_chart2.gif
|
184
|
-
- assets/evlms.png
|
185
|
-
- benchmarks/.gitignore
|
186
|
-
- benchmarks/2017-02-12.md
|
187
|
-
- benchmarks/2018-03-04.md
|
188
|
-
- benchmarks/2018-05-27-rpc-bench.md
|
189
|
-
- benchmarks/2018-10-27.md
|
190
|
-
- benchmarks/HowTo.md
|
191
|
-
- benchmarks/ansible.cfg
|
192
|
-
- benchmarks/assets/2018-10-27-action-cable-rss.png
|
193
|
-
- benchmarks/assets/2018-10-27-action-cable-rtt.png
|
194
|
-
- benchmarks/assets/2018-10-27-anycable-rss.png
|
195
|
-
- benchmarks/assets/2018-10-27-anycable-rtt.png
|
196
|
-
- benchmarks/assets/2018-10-27-async-rss.png
|
197
|
-
- benchmarks/assets/2018-10-27-async-rtt.png
|
198
|
-
- benchmarks/assets/2018-10-27-falcon-cable-rss.png
|
199
|
-
- benchmarks/assets/2018-10-27-falcon-cable-rtt.png
|
200
|
-
- benchmarks/assets/2018-10-27-iodine-cable-rss.png
|
201
|
-
- benchmarks/assets/2018-10-27-iodine-cable-rtt.png
|
202
|
-
- benchmarks/assets/2018-10-27-plezi-rss.png
|
203
|
-
- benchmarks/assets/2018-10-27-plezi-rtt.png
|
204
|
-
- benchmarks/bench.png
|
205
|
-
- benchmarks/benchmark.yml
|
206
|
-
- benchmarks/hosts
|
207
|
-
- benchmarks/rtt_plot.py
|
208
|
-
- benchmarks/rtt_plot_test.py
|
209
|
-
- benchmarks/servers.yml
|
210
165
|
- bin/anycable
|
166
|
+
- bin/anycabled
|
211
167
|
- bin/console
|
212
168
|
- bin/setup
|
213
|
-
- circle.yml
|
214
|
-
- etc/bug_report_template.rb
|
215
169
|
- lib/anycable.rb
|
216
170
|
- lib/anycable/broadcast_adapters.rb
|
217
171
|
- lib/anycable/broadcast_adapters/redis.rb
|
218
172
|
- lib/anycable/cli.rb
|
219
173
|
- lib/anycable/config.rb
|
220
174
|
- lib/anycable/exceptions_handling.rb
|
221
|
-
- lib/anycable/handler/capture_exceptions.rb
|
222
175
|
- lib/anycable/health_server.rb
|
223
176
|
- lib/anycable/middleware.rb
|
224
177
|
- lib/anycable/middleware_chain.rb
|
178
|
+
- lib/anycable/middlewares/check_version.rb
|
179
|
+
- lib/anycable/rpc.rb
|
225
180
|
- lib/anycable/rpc/rpc_pb.rb
|
226
181
|
- lib/anycable/rpc/rpc_services_pb.rb
|
227
182
|
- lib/anycable/rpc_handler.rb
|
183
|
+
- lib/anycable/rspec.rb
|
184
|
+
- lib/anycable/rspec/rpc_command_context.rb
|
185
|
+
- lib/anycable/rspec/rpc_stub_context.rb
|
186
|
+
- lib/anycable/rspec/with_grpc_server.rb
|
228
187
|
- lib/anycable/server.rb
|
229
188
|
- lib/anycable/socket.rb
|
230
189
|
- lib/anycable/version.rb
|
231
|
-
- protos/rpc.proto
|
232
190
|
homepage: http://github.com/anycable/anycable
|
233
191
|
licenses:
|
234
192
|
- MIT
|
235
|
-
metadata:
|
193
|
+
metadata:
|
194
|
+
bug_tracker_uri: http://github.com/anycable/anycable/issues
|
195
|
+
changelog_uri: https://github.com/anycable/anycable/blob/master/CHANGELOG.md
|
196
|
+
documentation_uri: https://docs.anycable.io/
|
197
|
+
homepage_uri: https://anycable.io/
|
198
|
+
source_code_uri: http://github.com/anycable/anycable
|
236
199
|
post_install_message:
|
237
200
|
rdoc_options: []
|
238
201
|
require_paths:
|
@@ -241,15 +204,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
241
204
|
requirements:
|
242
205
|
- - ">="
|
243
206
|
- !ruby/object:Gem::Version
|
244
|
-
version: 2.
|
207
|
+
version: 2.5.0
|
245
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
246
209
|
requirements:
|
247
|
-
- - "
|
210
|
+
- - ">"
|
248
211
|
- !ruby/object:Gem::Version
|
249
|
-
version:
|
212
|
+
version: 1.3.1
|
250
213
|
requirements: []
|
251
|
-
|
252
|
-
rubygems_version: 2.7.7
|
214
|
+
rubygems_version: 3.0.6
|
253
215
|
signing_key:
|
254
216
|
specification_version: 4
|
255
217
|
summary: AnyCable is a polyglot replacement for ActionCable-compatible servers
|
data/.github/ISSUE_TEMPLATE.md
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
First of all, thanks for your report/suggestion/whatever!
|
3
|
-
|
4
|
-
This template is for bug reports. If you are reporting a bug, please continue on. If you are here for another reason,
|
5
|
-
feel free to skip the rest of this template.
|
6
|
-
-->
|
7
|
-
|
8
|
-
### Tell us about your environment
|
9
|
-
|
10
|
-
**Ruby version:**
|
11
|
-
|
12
|
-
**`anycable` gem version:**
|
13
|
-
|
14
|
-
**`grpc` gem version:**
|
15
|
-
|
16
|
-
### What did you do?
|
17
|
-
|
18
|
-
### What did you expect to happen?
|
19
|
-
|
20
|
-
### What actually happened?
|
21
|
-
|
22
|
-
<!--
|
23
|
-
Please, provide reproduction script (using this template (https://github.com/anycable/anycable/blob/master/etc/bug_report_template.rb)
|
24
|
-
when submitting bugs if possible.
|
25
|
-
-->
|