anycable 0.6.0.rc1 → 1.0.0.preview1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -5
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +13 -6
  5. data/bin/anycable +1 -1
  6. data/bin/anycabled +30 -0
  7. data/lib/anycable.rb +16 -11
  8. data/lib/anycable/broadcast_adapters.rb +3 -3
  9. data/lib/anycable/broadcast_adapters/redis.rb +2 -2
  10. data/lib/anycable/cli.rb +20 -4
  11. data/lib/anycable/config.rb +10 -5
  12. data/lib/anycable/exceptions_handling.rb +13 -9
  13. data/lib/anycable/health_server.rb +2 -3
  14. data/lib/anycable/middleware.rb +3 -0
  15. data/lib/anycable/middleware_chain.rb +2 -2
  16. data/lib/anycable/middlewares/check_version.rb +24 -0
  17. data/lib/anycable/rpc.rb +76 -0
  18. data/lib/anycable/rpc/rpc_pb.rb +54 -39
  19. data/lib/anycable/rpc/rpc_services_pb.rb +4 -3
  20. data/lib/anycable/rpc_handler.rb +77 -24
  21. data/lib/anycable/rspec.rb +6 -0
  22. data/lib/anycable/rspec/rpc_command_context.rb +20 -0
  23. data/lib/anycable/rspec/rpc_stub_context.rb +13 -0
  24. data/lib/anycable/rspec/with_grpc_server.rb +15 -0
  25. data/lib/anycable/server.rb +4 -46
  26. data/lib/anycable/socket.rb +39 -2
  27. data/lib/anycable/version.rb +1 -1
  28. metadata +32 -70
  29. data/.github/ISSUE_TEMPLATE.md +0 -25
  30. data/.github/PULL_REQUEST_TEMPLATE.md +0 -31
  31. data/.gitignore +0 -40
  32. data/.hound.yml +0 -3
  33. data/.rubocop.yml +0 -71
  34. data/.travis.yml +0 -12
  35. data/Gemfile +0 -8
  36. data/Makefile +0 -5
  37. data/PITCHME.md +0 -139
  38. data/PITCHME.yaml +0 -1
  39. data/Rakefile +0 -8
  40. data/anycable.gemspec +0 -35
  41. data/assets/Memory3.png +0 -0
  42. data/assets/Memory5.png +0 -0
  43. data/assets/RTT3.png +0 -0
  44. data/assets/RTT5.png +0 -0
  45. data/assets/Scheme1.png +0 -0
  46. data/assets/Scheme2.png +0 -0
  47. data/assets/cpu_chart.gif +0 -0
  48. data/assets/cpu_chart2.gif +0 -0
  49. data/assets/evlms.png +0 -0
  50. data/benchmarks/.gitignore +0 -2
  51. data/benchmarks/2017-02-12.md +0 -308
  52. data/benchmarks/2018-03-04.md +0 -192
  53. data/benchmarks/2018-05-27-rpc-bench.md +0 -57
  54. data/benchmarks/2018-10-27.md +0 -181
  55. data/benchmarks/HowTo.md +0 -23
  56. data/benchmarks/ansible.cfg +0 -9
  57. data/benchmarks/assets/2018-10-27-action-cable-rss.png +0 -0
  58. data/benchmarks/assets/2018-10-27-action-cable-rtt.png +0 -0
  59. data/benchmarks/assets/2018-10-27-anycable-rss.png +0 -0
  60. data/benchmarks/assets/2018-10-27-anycable-rtt.png +0 -0
  61. data/benchmarks/assets/2018-10-27-async-rss.png +0 -0
  62. data/benchmarks/assets/2018-10-27-async-rtt.png +0 -0
  63. data/benchmarks/assets/2018-10-27-falcon-cable-rss.png +0 -0
  64. data/benchmarks/assets/2018-10-27-falcon-cable-rtt.png +0 -0
  65. data/benchmarks/assets/2018-10-27-iodine-cable-rss.png +0 -0
  66. data/benchmarks/assets/2018-10-27-iodine-cable-rtt.png +0 -0
  67. data/benchmarks/assets/2018-10-27-plezi-rss.png +0 -0
  68. data/benchmarks/assets/2018-10-27-plezi-rtt.png +0 -0
  69. data/benchmarks/bench.png +0 -0
  70. data/benchmarks/benchmark.yml +0 -69
  71. data/benchmarks/hosts +0 -5
  72. data/benchmarks/rtt_plot.py +0 -74
  73. data/benchmarks/rtt_plot_test.py +0 -16
  74. data/benchmarks/servers.yml +0 -58
  75. data/circle.yml +0 -8
  76. data/etc/bug_report_template.rb +0 -76
  77. data/lib/anycable/handler/capture_exceptions.rb +0 -39
  78. data/protos/rpc.proto +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f38ac8ce1378f75f5e1b4379c51254a346a2576fdb8326e6e2efb5d1820e857f
4
- data.tar.gz: 0fa60623686123be319a92c8548b82ae4c3bf9ddadade0234cb3d69118599cd3
3
+ metadata.gz: 65d07fe802d850f89351ed8c054d2cba9c393b36f7a5aa318183362f09d53e58
4
+ data.tar.gz: b4167ba77ce930ddcb77a9e38d205215fb3ec085a93bfd3876f2bf8a5e669373
5
5
  SHA512:
6
- metadata.gz: 18014f2f1193f3e4f2984e4800b14097e131f9b93e413cada4f29805295c1b8153f75d9e7b00b843feb7e66c34c1ffa3e6c24d5494f3c0e516dc693ed39acb94
7
- data.tar.gz: c27a42de1a8b6539a4906e75afe3cea4ac4a5e39c1a006ed06ba106f0b0f99d51b7052a93e54cbfe8ab72114f7b43f34f692214009038a82f7839e614e960b15
6
+ metadata.gz: 456af4dd28de6d32a8436ce8702ddb3ba5523b25b531bce8dac00c5bf6cd181e79c57e4d4a89d1a2c1ff3e21eda1108be3f023c65edcf1bbf5790594216ae971
7
+ data.tar.gz: b25fa2a291a6cd6bbf4734c9c59dcf991dead19c0e25c004ac696ec524e6de63bb5ea4251f8d06ce1d21699a44e178a7e445bfedcd4d70179535c6648ed67854
@@ -1,8 +1,95 @@
1
1
  # Change log
2
2
 
3
- ## master
3
+ ## 🚧 1.0.0 (_coming soon_)
4
4
 
5
- ## 0.6.0-dev
5
+ - **RPC schema has changed**. ([@palkan][])
6
+
7
+ Using `anycable-go` v1.x is required.
8
+
9
+ - **Ruby 2.5+ is required**. ([@palkan][])
10
+
11
+ - Added RPC proto version check. ([@palkan][])
12
+
13
+ Server must sent `protov` metadata with the supported versions (comma-separated list). If there is no matching version an exception is raised.
14
+
15
+ Current RPC proto version is **v1**.
16
+
17
+ - Added `request` support to channels. ([@palkan][])
18
+
19
+ Now you can access `request` object in channels, too (e.g., to read headers/cookies/URL/etc).
20
+
21
+ - Change default server address from `[::]:50051` to `127.0.0.1:50051`. ([@palkan][])
22
+
23
+ See [#71](https://github.com/anycable/anycable/pull/71).
24
+
25
+ ## 0.6.4 (2020-01-24)
26
+
27
+ - Fix Ruby 2.7 warnings. ([@palkan])
28
+
29
+ – Add `REMOTE_ADDR` socket env variable using a synthetic header passed from a websocket
30
+ server. ([@sponomarev][])
31
+
32
+ Recreating a request object in your custom connection factory using `Rack::Request` or
33
+ `ActionDispatch::Request` (already implemented in [anycable-rails](https://github.com/anycable/anycable-rails))
34
+ gives you an access to `request.ip` with the properly set IP address.
35
+
36
+ - Align socket env to be more compatibile with Rack Spec ([@sponomarev][])
37
+
38
+ Provide as much env details as possible to be able to reconstruct the full
39
+ request object in a custom connection factory.
40
+
41
+ ## 0.6.3 (2019-03-26)
42
+
43
+ - Relax `redis` gem version requirement. ([@palkan][])
44
+
45
+ Use the same restriction as Action Cable does (`>= 3`).
46
+
47
+ ## 0.6.2 (2019-03-15)
48
+
49
+ - Add GRPC service method name and message content to exception notifications ([@sponomarev][])
50
+
51
+ `Anycable.capture_exception` allows accessing GRPC service method name and message content
52
+ on which an exception was captured. It can be used for exceptions grouping in your tracker and
53
+ providing additional data to investigate a root of a problem.
54
+
55
+ Example:
56
+
57
+ ```ruby
58
+ AnyCable.capture_exception do |ex, method, message|
59
+ Honeybadger.notify(ex, component: "any_cable", action: method, params: message)
60
+ end
61
+ ```
62
+
63
+ Usage of a handler proc with just a single argument is preserved for the sake of compatibility.
64
+
65
+ - Add deprecation warning to default host usage ([@sponomarev][])
66
+
67
+ Exposing AnyCable publicly is considered to be harmful and planned to be changed
68
+ in future versions.
69
+
70
+ - Allow running the server as a detachable daemon ([@sponomarev][])
71
+
72
+ Server is fully managed by the binary itself.
73
+
74
+ ```
75
+ # Start anycable daemon
76
+ $ bundle exec anycabled start
77
+
78
+ # Pass cli options to anycable through daemon. Separate daemon options and anycable options with `--`
79
+ $ bundle exec anycabled start -- --rpc-host 127.0.0.1:31337
80
+
81
+ # Stop anycable daemon
82
+ $ bundle exec anycabled stop
83
+
84
+ # See more anycable daemon options
85
+ $ bundle exec anycabled
86
+ ```
87
+
88
+ ## 0.6.1 (2019-01-05)
89
+
90
+ - [Fix #63](https://github.com/anycable/anycable-rails/issues/63) Load `anyway_config` after application boot to make sure that all frameworks dependent functionality is loaded. ([@palkan][])
91
+
92
+ ## 0.6.0 (2018-11-15)
6
93
 
7
94
  ### Features
8
95
 
@@ -13,7 +100,7 @@ AnyCable allows you to use custom broadcasting adapters (Redis is used by defaul
13
100
  ```ruby
14
101
  # Specify by name (tries to load `AnyCable::BroadcastAdapters::MyAdapter` from
15
102
  # "anycable/broadcast_adapters/my_adapter")
16
- AnyCable.broadcast_adapter = :my_adapter, { option: "value" }
103
+ AnyCable.broadcast_adapter = :my_adapter, {option: "value"}
17
104
  # or provide an instance (should respond_to #broadcast)
18
105
  AnyCable.broadcast_adapter = MyAdapter.new
19
106
  ```
@@ -77,6 +164,10 @@ See [docs](https://docs.anycable.io/#/./middlewares).
77
164
 
78
165
  See [docs](https://docs.anycable.io/#/./health_checking).
79
166
 
167
+ - Added hook to run code only within RPC server context.
168
+
169
+ Use `AnyCable.configure_server { ... }` to run code only when RPC server is running.
170
+
80
171
  ### API changes
81
172
 
82
173
  **NOTE**: the old API is still working but deprecated (you'll see a notice).
@@ -108,7 +199,7 @@ Minor fixes.
108
199
 
109
200
  - [#28](https://github.com/anycable/anycable/issues/28) Support arbitrary headers. ([@palkan][])
110
201
 
111
- Previously we hardcoded only "Cookie" header. Now we add all passed headers by WebSocket server to request env.
202
+ Previously we hardcoded only "Cookie" header. Now we add all passed headers by WebSocket server to request env.
112
203
 
113
204
  - [#27](https://github.com/anycable/anycable/issues/27) Add `error_msg` to RPC responses. ([@palkan][])
114
205
 
@@ -122,7 +213,7 @@ We provide `error_msg` only when request status is `ERROR`.
122
213
 
123
214
  - [#25](https://github.com/anycable/anycable/issues/25) Improve logging and exceptions handling. ([@palkan][])
124
215
 
125
- Default logger logs to STDOUT with `info` level by default but can be configured to log to file with
216
+ Default logger logs to STDOUT with `info` level by default but can be configured to log to file with
126
217
  any severity.
127
218
 
128
219
  GRPC logging is turned off by default (can be turned on through `log_grpc` configuration parameter).
@@ -189,3 +280,4 @@ Implement `Disconnect` handler, which invokes `Connection#disconnect` (along wit
189
280
  [@sadovnik]: https://github.com/sadovnik
190
281
  [@accessd]: https://github.com/accessd
191
282
  [@DarthSim]: https://github.com/DarthSim
283
+ [@sponomarev]: https://github.com/sponomarev
@@ -1,4 +1,4 @@
1
- Copyright 2017 palkan
1
+ Copyright 2017-2019 Vladimir Dementyev
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -9,15 +9,15 @@
9
9
 
10
10
  AnyCable allows you to use any WebSocket server (written in any language) as a replacement for your Ruby server (such as Faye, ActionCable, etc).
11
11
 
12
- AnyCable uses ActionCable protocol, so you can use ActionCable [JavaScript client](https://www.npmjs.com/package/actioncable) without any monkey-patching.
12
+ AnyCable uses the same protocol as ActionCable, so you can use its [JavaScript client](https://www.npmjs.com/package/actioncable) without any monkey-patching.
13
13
 
14
14
  <a href="https://evilmartians.com/">
15
15
  <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
16
16
 
17
17
  ## Requirements
18
18
 
19
- - Ruby >= 2.4
20
- - Redis (for brodcasting, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
19
+ - Ruby >= 2.5
20
+ - Redis (for broadcasting, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
21
21
 
22
22
  ## Usage
23
23
 
@@ -33,6 +33,8 @@ Check out our 📑 [Documentation](https://docs.anycable.io).
33
33
 
34
34
  ## Talks
35
35
 
36
+ - High-speed cables for Ruby, RubyConf 2018, [slides](https://speakerdeck.com/palkan/rubyconf-2018-high-speed-cables-for-ruby) and [video](https://www.youtube.com/watch?v=8XRcOZXOzV4) (EN)
37
+
36
38
  - One cable to rule them all, RubyKaigi 2018, [slides](https://speakerdeck.com/palkan/rubykaigi-2018-anycable-one-cable-to-rule-them-all) and [video](https://www.youtube.com/watch?v=jXCPuNICT8s) (EN)
37
39
 
38
40
  - Wroc_Love.rb 2018 [slides](https://speakerdeck.com/palkan/wroc-love-dot-rb-2018-cables-cables-cables) and [video](https://www.youtube.com/watch?v=AUxFFOehiy0) (EN)
@@ -50,22 +52,27 @@ Check out our 📑 [Documentation](https://docs.anycable.io).
50
52
 
51
53
  - Install required GRPC gems:
52
54
 
53
- ```
55
+ ```sh
54
56
  gem install grpc
55
57
  gem install grpc-tools
56
58
  ```
57
59
 
58
60
  - Re-generate GRPC files (if necessary):
59
61
 
60
- ```
62
+ ```sh
61
63
  make
62
64
  ```
63
65
 
64
66
  ## Contributing
65
67
 
66
- Bug reports and pull requests are welcome on GitHub at https://github.com/anycable/anycable.
68
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/anycable/anycable](https://github.com/anycable/anycable).
67
69
 
68
70
  Please, provide reproduction script (using [this template](https://github.com/anycable/anycable/blob/master/etc/bug_report_template.rb)) when submitting bugs if possible.
69
71
 
70
72
  ## License
73
+
71
74
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
75
+
76
+ ## Security Contact
77
+
78
+ To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require_relative "../lib/anycable/cli"
3
+ require "anycable/cli"
4
4
 
5
5
  begin
6
6
  cli = AnyCable::CLI.new
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "anycable/cli"
4
+
5
+ begin
6
+ require "daemons"
7
+ rescue LoadError
8
+ raise <<~MSG
9
+ You need to add gem 'daemons' to your Gemfile if you want to use `anycabled`:
10
+
11
+ # Gemfile
12
+ gem "daemons", "~> 1.3", require: false
13
+ MSG
14
+ end
15
+
16
+ options = {
17
+ dir: "tmp/pids",
18
+ log_output: false
19
+ }
20
+
21
+ # Preserve current directory. We need it inside the server.
22
+ current_dir = Dir.pwd
23
+
24
+ # Clean ARGV from daemon command and args
25
+ _, _, args = Daemons::Controller.split_argv(ARGV)
26
+
27
+ Daemons.run_proc("anycable", options) do
28
+ Dir.chdir current_dir
29
+ AnyCable::CLI.new.run(args)
30
+ end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "anycable/version"
4
- require "anycable/config"
5
4
  require "logger"
6
5
 
7
6
  require "anycable/exceptions_handling"
@@ -39,7 +38,12 @@ module AnyCable
39
38
  end
40
39
 
41
40
  def config
42
- @config ||= Config.new
41
+ @config ||= begin
42
+ # Load anyway_config as later as possible
43
+ # to make sure all framework-dependent patches are loaded
44
+ require "anycable/config"
45
+ Config.new
46
+ end
43
47
  end
44
48
 
45
49
  def configure
@@ -52,12 +56,14 @@ module AnyCable
52
56
  ExceptionsHandling << block
53
57
  end
54
58
 
55
- def error_handlers
56
- warn <<~DEPRECATION
57
- Using `AnyCable.error_handlers` is deprecated!
58
- Please, use `AnyCable.capture_exception` instead.
59
- DEPRECATION
60
- ExceptionsHandling
59
+ # Register a callback to be invoked before
60
+ # the server starts
61
+ def configure_server(&block)
62
+ server_callbacks << block
63
+ end
64
+
65
+ def server_callbacks
66
+ @server_callbacks ||= []
61
67
  end
62
68
 
63
69
  def broadcast_adapter
@@ -89,8 +95,7 @@ module AnyCable
89
95
  attr_writer :middleware
90
96
  end
91
97
 
98
+ require "anycable/middlewares/check_version"
99
+
92
100
  self.middleware = MiddlewareChain.new
93
101
  end
94
-
95
- # Backward compatibility
96
- Anycable = AnyCable
@@ -17,16 +17,16 @@ module AnyCable
17
17
  # We couldn't require the adapter itself.
18
18
  if e.path == path_to_adapter
19
19
  raise e.class, "Couldn't load the '#{adapter}' broadcast adapter for AnyCable",
20
- e.backtrace
20
+ e.backtrace
21
21
  # Bubbled up from the adapter require.
22
22
  else
23
23
  raise e.class, "Error loading the '#{adapter}' broadcast adapter for AnyCable",
24
- e.backtrace
24
+ e.backtrace
25
25
  end
26
26
  end
27
27
  end
28
28
 
29
- BroadcastAdapters.const_get(adapter_class_name, false).new(options || {})
29
+ BroadcastAdapters.const_get(adapter_class_name, false).new(**(options || {}))
30
30
  end
31
31
  # rubocop: enable Metrics/AbcSize, Metrics/MethodLength
32
32
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "redis", ">= 4.0"
3
+ gem "redis", ">= 3"
4
4
 
5
5
  require "redis"
6
6
  require "json"
@@ -34,7 +34,7 @@ module AnyCable
34
34
  def broadcast(stream, payload)
35
35
  redis_conn.publish(
36
36
  channel,
37
- { stream: stream, data: payload }.to_json
37
+ {stream: stream, data: payload}.to_json
38
38
  )
39
39
  end
40
40
  end
@@ -23,7 +23,7 @@ module AnyCable
23
23
  attr_reader :server, :health_server
24
24
 
25
25
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
26
- def run(args)
26
+ def run(args = {})
27
27
  @at_stop = []
28
28
 
29
29
  extra_options = parse_cli_options!(args)
@@ -34,11 +34,13 @@ module AnyCable
34
34
 
35
35
  parse_gem_options!(extra_options)
36
36
 
37
- logger.info "Starting AnyCable gRPC server (pid: #{Process.pid})"
37
+ configure_server!
38
+
39
+ logger.info "Starting AnyCable gRPC server (pid: #{Process.pid}, workers_num: #{config.rpc_pool_size})"
38
40
 
39
41
  print_versions!
40
42
 
41
- logger.info "Serving #{defined?(::Rails) ? 'Rails ' : ''}application from #{boot_file}"
43
+ logger.info "Serving #{defined?(::Rails) ? "Rails " : ""}application from #{boot_file}"
42
44
 
43
45
  verify_connection_factory!
44
46
 
@@ -46,6 +48,8 @@ module AnyCable
46
48
 
47
49
  log_errors!
48
50
 
51
+ use_version_check! if config.version_check_enabled?
52
+
49
53
  @server = AnyCable::Server.new(
50
54
  host: config.rpc_host,
51
55
  **config.to_grpc_params,
@@ -122,7 +126,7 @@ module AnyCable
122
126
  end
123
127
 
124
128
  def print_versions!
125
- logger.info "AnyCable version: #{AnyCable::VERSION}"
129
+ logger.info "AnyCable version: #{AnyCable::VERSION} (proto_version: #{AnyCable::PROTO_VERSION})"
126
130
  logger.info "gRPC version: #{GRPC::VERSION}"
127
131
  end
128
132
 
@@ -156,6 +160,18 @@ module AnyCable
156
160
  APP_CANDIDATES.detect { |path| File.exist?(path) }
157
161
  end
158
162
 
163
+ def configure_server!
164
+ AnyCable.server_callbacks.each(&:call)
165
+ end
166
+
167
+ def use_version_check!
168
+ require "anycable/middlewares/check_version"
169
+
170
+ AnyCable.middleware.use(
171
+ AnyCable::Middlewares::CheckVersion.new(AnyCable::PROTO_VERSION)
172
+ )
173
+ end
174
+
159
175
  def start_health_server!
160
176
  @health_server = AnyCable::HealthServer.new(
161
177
  server,
@@ -10,8 +10,8 @@ module AnyCable
10
10
 
11
11
  attr_config(
12
12
  ### gRPC options
13
- rpc_host: "[::]:50051",
14
- # For defaults see https://github.com/grpc/grpc/blob/master/src/ruby/lib/grpc/generic/rpc_server.rb#L162-L170
13
+ rpc_host: "127.0.0.1:50051",
14
+ # For defaults see https://github.com/grpc/grpc/blob/51f0d35509bcdaba572d422c4f856208162022de/src/ruby/lib/grpc/generic/rpc_server.rb#L186-L216
15
15
  rpc_pool_size: GRPC::RpcServer::DEFAULT_POOL_SIZE,
16
16
  rpc_max_waiting_requests: GRPC::RpcServer::DEFAULT_MAX_WAITING_REQUESTS,
17
17
  rpc_poll_period: GRPC::RpcServer::DEFAULT_POLL_PERIOD,
@@ -32,9 +32,14 @@ module AnyCable
32
32
 
33
33
  ### Health check options
34
34
  http_health_port: nil,
35
- http_health_path: "/health"
35
+ http_health_path: "/health",
36
+
37
+ ### Misc options
38
+ version_check_enabled: true
36
39
  )
37
40
 
41
+ alias version_check_enabled? version_check_enabled
42
+
38
43
  ignore_options :rpc_server_args
39
44
  flag_options :log_grpc, :debug
40
45
 
@@ -69,7 +74,7 @@ module AnyCable
69
74
 
70
75
  # Build Redis parameters
71
76
  def to_redis_params
72
- { url: redis_url }.tap do |params|
77
+ {url: redis_url}.tap do |params|
73
78
  next if redis_sentinels.nil?
74
79
 
75
80
  raise ArgumentError, "redis_sentinels must be an array; got #{redis_sentinels}" unless
@@ -100,7 +105,7 @@ module AnyCable
100
105
 
101
106
  raise ArgumentError, "Invalid Sentinel value: #{sentinel}" if matches.nil?
102
107
 
103
- { "host" => matches[1], "port" => matches[2].to_i }
108
+ {"host" => matches[1], "port" => matches[2].to_i}
104
109
  end
105
110
  end
106
111
  end