anycable 0.5.2 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +166 -2
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +19 -60
  5. data/bin/anycable +13 -0
  6. data/bin/anycabled +30 -0
  7. data/lib/anycable.rb +69 -18
  8. data/lib/anycable/broadcast_adapters.rb +33 -0
  9. data/lib/anycable/broadcast_adapters/redis.rb +42 -0
  10. data/lib/anycable/cli.rb +329 -0
  11. data/lib/anycable/config.rb +93 -17
  12. data/lib/anycable/exceptions_handling.rb +37 -0
  13. data/lib/anycable/health_server.rb +52 -31
  14. data/lib/anycable/middleware.rb +19 -0
  15. data/lib/anycable/middleware_chain.rb +58 -0
  16. data/lib/anycable/rpc/rpc_pb.rb +1 -1
  17. data/lib/anycable/rpc/rpc_services_pb.rb +1 -1
  18. data/lib/anycable/rpc_handler.rb +77 -32
  19. data/lib/anycable/server.rb +132 -39
  20. data/lib/anycable/socket.rb +1 -1
  21. data/lib/anycable/version.rb +2 -2
  22. metadata +34 -59
  23. data/.gitignore +0 -40
  24. data/.hound.yml +0 -3
  25. data/.rubocop.yml +0 -71
  26. data/.travis.yml +0 -13
  27. data/Gemfile +0 -8
  28. data/Makefile +0 -5
  29. data/PITCHME.md +0 -139
  30. data/PITCHME.yaml +0 -1
  31. data/Rakefile +0 -8
  32. data/anycable.gemspec +0 -32
  33. data/assets/Memory3.png +0 -0
  34. data/assets/Memory5.png +0 -0
  35. data/assets/RTT3.png +0 -0
  36. data/assets/RTT5.png +0 -0
  37. data/assets/Scheme1.png +0 -0
  38. data/assets/Scheme2.png +0 -0
  39. data/assets/cpu_chart.gif +0 -0
  40. data/assets/cpu_chart2.gif +0 -0
  41. data/assets/evlms.png +0 -0
  42. data/benchmarks/.gitignore +0 -1
  43. data/benchmarks/2017-02-12.md +0 -308
  44. data/benchmarks/2018-03-04.md +0 -192
  45. data/benchmarks/2018-05-27-rpc-bench.md +0 -57
  46. data/benchmarks/HowTo.md +0 -23
  47. data/benchmarks/ansible.cfg +0 -9
  48. data/benchmarks/benchmark.yml +0 -67
  49. data/benchmarks/hosts +0 -5
  50. data/benchmarks/servers.yml +0 -36
  51. data/circle.yml +0 -8
  52. data/etc/bug_report_template.rb +0 -76
  53. data/lib/anycable/handler/exceptions_handling.rb +0 -43
  54. data/lib/anycable/pubsub.rb +0 -26
  55. data/protos/rpc.proto +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '079d557557d69550f4a490d8fcbcd35b922df102af44c076ea14bc92bff5dda3'
4
- data.tar.gz: 29339983ff86ec5f52959397b566926c00d7116fa8dd56dc4933bac4bd526689
3
+ metadata.gz: 6b624b0695335efdb861cfdb90b16caa0b2ddd67698a0ac813a81e9ae98a52eb
4
+ data.tar.gz: b70e2b622120da3ae2df10049e6145d958d84d78ab8a080943a8e50aab4cf983
5
5
  SHA512:
6
- metadata.gz: a4fdb1f8ccbb3c633996c4aae85ce60263ab5c8f68f13909d93ef2ebe390e5124901b2832221b7fdd809fef1e3ae04628e4e5437aa6f262da51248041b5d0030
7
- data.tar.gz: ba3d770e79aa4775e894d2f568787f62d96f1e699828549e0dba1880a85597e01e565fe0781a51b1da42f7cd359cc7580846c7c01f297ee498e4cbfacfba8329
6
+ metadata.gz: 97619fd72a53a84608f47b9a99504b080731a0b8915667007d9cf3240feda2a880b0cdcb67acddefec14c34fbbd169c812a4dc310ef4d0b3757c818471ae019c
7
+ data.tar.gz: efb598ebbd08e0de7574f0de3690b0c7caf11812f3b2afcde26aee5c8bff8a4607cd3a9b791cc978df458d00c37155d23d520118ffc38af98f1e7c9e66760d88
@@ -2,6 +2,169 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.6.4 (2020-01-24)
6
+
7
+ - Fix Ruby 2.7 warnings. ([@palkan])
8
+
9
+ – Add `REMOTE_ADDR` socket env variable using a synthetic header passed from a websocket
10
+ server. ([@sponomarev][])
11
+
12
+ Recreating a request object in your custom connection factory using `Rack::Request` or
13
+ `ActionDispatch::Request` (already implemented in [anycable-rails](https://github.com/anycable/anycable-rails))
14
+ gives you an access to `request.ip` with the properly set IP address.
15
+
16
+ - Align socket env to be more compatibile with Rack Spec ([@sponomarev][])
17
+
18
+ Provide as much env details as possible to be able to reconstruct the full
19
+ request object in a custom connection factory.
20
+
21
+ ## 0.6.3 (2019-03-26)
22
+
23
+ - Relax `redis` gem version requirement. ([@palkan][])
24
+
25
+ Use the same restriction as Action Cable does (`>= 3`).
26
+
27
+ ## 0.6.2 (2019-03-15)
28
+
29
+ - Add GRPC service method name and message content to exception notifications ([@sponomarev][])
30
+
31
+ `Anycable.capture_exception` allows accessing GRPC service method name and message content
32
+ on which an exception was captured. It can be used for exceptions grouping in your tracker and
33
+ providing additional data to investigate a root of a problem.
34
+
35
+ Example:
36
+
37
+ ```ruby
38
+ AnyCable.capture_exception do |ex, method, message|
39
+ Honeybadger.notify(ex, component: "any_cable", action: method, params: message)
40
+ end
41
+ ```
42
+
43
+ Usage of a handler proc with just a single argument is preserved for the sake of compatibility.
44
+
45
+ - Add deprecation warning to default host usage ([@sponomarev][])
46
+
47
+ Exposing AnyCable publicly is considered to be harmful and planned to be changed
48
+ in future versions.
49
+
50
+ - Allow running the server as a detachable daemon ([@sponomarev][])
51
+
52
+ Server is fully managed by the binary itself.
53
+
54
+ ```
55
+ # Start anycable daemon
56
+ $ bundle exec anycabled start
57
+
58
+ # Pass cli options to anycable through daemon. Separate daemon options and anycable options with `--`
59
+ $ bundle exec anycabled start -- --rpc-host 127.0.0.1:31337
60
+
61
+ # Stop anycable daemon
62
+ $ bundle exec anycabled stop
63
+
64
+ # See more anycable daemon options
65
+ $ bundle exec anycabled
66
+ ```
67
+
68
+ ## 0.6.1 (2019-01-05)
69
+
70
+ - [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][])
71
+
72
+ ## 0.6.0 (2018-11-15)
73
+
74
+ ### Features
75
+
76
+ #### Broadcast adapters
77
+
78
+ AnyCable allows you to use custom broadcasting adapters (Redis is used by default):
79
+
80
+ ```ruby
81
+ # Specify by name (tries to load `AnyCable::BroadcastAdapters::MyAdapter` from
82
+ # "anycable/broadcast_adapters/my_adapter")
83
+ AnyCable.broadcast_adapter = :my_adapter, { option: "value" }
84
+ # or provide an instance (should respond_to #broadcast)
85
+ AnyCable.broadcast_adapter = MyAdapter.new
86
+ ```
87
+
88
+ **Breaking:** to use Redis adapter you must ensure that it is present in your Gemfile; AnyCable gem doesn't have `redis` as a dependency anymore.
89
+
90
+ #### CLI
91
+
92
+ AnyCable now ships with a CLI–`anycable`.
93
+
94
+ Use it to run a gRPC server:
95
+
96
+ ```sh
97
+ # run anycable and load app from app.rb
98
+ bundle exec anycable -r app.rb
99
+ # or
100
+ bundle exec anycable --require app.rb
101
+ ```
102
+
103
+ All configuration options are also supported as CLI options (see `anycable -h` for more information).
104
+
105
+ The only required options is the application file to load (`-r/--require`).
106
+
107
+ You can omit it if you want to load an app form `./config/environment.rb` (e.g. with Rails) or `./config/anycable.rb`.
108
+
109
+ AnyCable CLI also allows you to run a separate command (process) from within a RPC server:
110
+
111
+ ```sh
112
+ $ bundle exec anycable --server-command "anycable-go -p 3334"
113
+ ```
114
+
115
+ #### Configuration
116
+
117
+ - Default server host is changed from `localhost:50051` to `0.0.0.0:50051`
118
+ - Expose gRPC server parameters via `rpc_*` config params:
119
+
120
+ ```ruby
121
+ AnyCable.configure do |config|
122
+ config.rpc_pool_size = 120
123
+ config.rpc_max_waiting_requests = 10
124
+ # etc
125
+ end
126
+ ```
127
+ - `REDIS_URL` env is used by default if present (and no `ANYCABLE_REDIS_URL` specified)
128
+ - Make HTTP health check url configurable
129
+ - Add ability to pass Redis Sentinel config as array of string.
130
+
131
+ Now it's possible to pass Sentinel configuration via env vars:
132
+
133
+ ```sh
134
+ ANYCABLE_REDIS_SENTINELS=127.0.0.1:26380,127.0.0.1:26381 bundle exec anycable
135
+ ```
136
+
137
+ #### Other
138
+
139
+ - Added middlewares support
140
+
141
+ See [docs](https://docs.anycable.io/#/./middlewares).
142
+
143
+ - Added gRPC health checker.
144
+
145
+ See [docs](https://docs.anycable.io/#/./health_checking).
146
+
147
+ - Added hook to run code only within RPC server context.
148
+
149
+ Use `AnyCable.configure_server { ... }` to run code only when RPC server is running.
150
+
151
+ ### API changes
152
+
153
+ **NOTE**: the old API is still working but deprecated (you'll see a notice).
154
+
155
+ - Use `AnyCable` instead of `Anycable`
156
+
157
+ - New API for registering error handlers:
158
+
159
+ ```ruby
160
+ AnyCable.capture_exception do |ex|
161
+ Honeybadger.notify(ex)
162
+ end
163
+ ```
164
+
165
+ - `AnyCable::Server.start` is deprecated
166
+
167
+
5
168
  ## 0.5.2 (2018-09-06)
6
169
 
7
170
  - [#48](https://github.com/anycable/anycable/pull/48) Add HTTP health server ([@DarthSim][])
@@ -16,7 +179,7 @@ Minor fixes.
16
179
 
17
180
  - [#28](https://github.com/anycable/anycable/issues/28) Support arbitrary headers. ([@palkan][])
18
181
 
19
- Previously we hardcoded only "Cookie" header. Now we add all passed headers by WebSocket server to request env.
182
+ Previously we hardcoded only "Cookie" header. Now we add all passed headers by WebSocket server to request env.
20
183
 
21
184
  - [#27](https://github.com/anycable/anycable/issues/27) Add `error_msg` to RPC responses. ([@palkan][])
22
185
 
@@ -30,7 +193,7 @@ We provide `error_msg` only when request status is `ERROR`.
30
193
 
31
194
  - [#25](https://github.com/anycable/anycable/issues/25) Improve logging and exceptions handling. ([@palkan][])
32
195
 
33
- Default logger logs to STDOUT with `info` level by default but can be configured to log to file with
196
+ Default logger logs to STDOUT with `info` level by default but can be configured to log to file with
34
197
  any severity.
35
198
 
36
199
  GRPC logging is turned off by default (can be turned on through `log_grpc` configuration parameter).
@@ -97,3 +260,4 @@ Implement `Disconnect` handler, which invokes `Connection#disconnect` (along wit
97
260
  [@sadovnik]: https://github.com/sadovnik
98
261
  [@accessd]: https://github.com/accessd
99
262
  [@DarthSim]: https://github.com/DarthSim
263
+ [@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
@@ -1,40 +1,27 @@
1
- [![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/anycable/anycable/master?grs=github) [![Gem Version](https://badge.fury.io/rb/anycable.svg)](https://rubygems.org/gems/anycable) [![Build Status](https://travis-ci.org/anycable/anycable.svg?branch=master)](https://travis-ci.org/anycable/anycable) [![Circle CI](https://circleci.com/gh/anycable/anycable/tree/master.svg?style=svg)](https://circleci.com/gh/anycable/anycable/tree/master)
1
+ [![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/anycable/anycable/master?grs=github) [![Gem Version](https://badge.fury.io/rb/anycable.svg)](https://rubygems.org/gems/anycable) [![Build Status](https://travis-ci.org/anycable/anycable.svg?branch=master)](https://travis-ci.org/anycable/anycable)
2
2
  [![Gitter](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/anycable/Lobby)
3
+ [![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](https://docs.anycable.io)
3
4
 
4
- # Anycable
5
+ # AnyCable
5
6
 
6
- AnyCable allows you to use any WebSocket server (written in any language) as a replacement for your Ruby server (such as Faye, ActionCable, etc).
7
+ <img align="right" height="150" width="129"
8
+ title="AnyCable logo" src="https://docs.anycable.io/assets/images/logo.svg">
7
9
 
8
- AnyCable uses ActionCable protocol, so you can use ActionCable [JavaScript client](https://www.npmjs.com/package/actioncable) without any monkey-patching.
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).
9
11
 
10
- **NOTE**: Since version 0.4.0 this repository contains only core functionality and cannot be used separately as is.
11
- Rails plug-n-play integration has been extracted to [anycable-rails](https://github.com/anycable/anycable-rails) gem.
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.
12
13
 
13
14
  <a href="https://evilmartians.com/">
14
15
  <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
15
16
 
16
17
  ## Requirements
17
18
 
18
- - Ruby >= 2.3, <= 2.5
19
- - Redis (for brodcasting, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
20
-
21
- Or you can try to [build it from source](https://github.com/grpc/grpc/blob/master/INSTALL.md#build-from-source).
19
+ - Ruby >= 2.4
20
+ - Redis (for broadcasting, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
22
21
 
23
- For MacOS there is also [the same problem](https://github.com/google/protobuf/issues/4098) with `google-protobuf` that can be solved
24
- the following way:
25
-
26
- ```ruby
27
- # Gemfile
28
- git 'https://github.com/google/protobuf' do
29
- gem 'google-protobuf'
30
- end
31
- ```
22
+ ## Usage
32
23
 
33
- ## How It Works?
34
-
35
- ![](https://s3.amazonaws.com/anycable/Scheme.png)
36
-
37
- Read our [Wiki](https://github.com/anycable/anycable/wiki) for more.
24
+ Check out our 📑 [Documentation](https://docs.anycable.io).
38
25
 
39
26
  ## Links
40
27
 
@@ -46,6 +33,8 @@ Read our [Wiki](https://github.com/anycable/anycable/wiki) for more.
46
33
 
47
34
  ## Talks
48
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
+
49
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)
50
39
 
51
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)
@@ -54,46 +43,11 @@ Read our [Wiki](https://github.com/anycable/anycable/wiki) for more.
54
43
 
55
44
  - RailsClub Moscow 2016 [slides](https://speakerdeck.com/palkan/railsclub-moscow-2016-anycable) and [video](https://www.youtube.com/watch?v=-k7GQKuBevY&list=PLiWUIs1hSNeOXZhotgDX7Y7qBsr24cu7o&index=4) (RU)
56
45
 
57
-
58
46
  ## Compatible WebSocket servers
59
47
 
60
- - [Anycable Go](https://github.com/anycable/anycable-go)
48
+ - [AnyCable Go](https://github.com/anycable/anycable-go)
61
49
  - [ErlyCable](https://github.com/anycable/erlycable)
62
50
 
63
- ## Configuration
64
-
65
- Anycable uses [anyway_config](https://github.com/palkan/anyway_config), thus it is also possible to set configuration variables through `secrets.yml` or environment vars.
66
-
67
- ### Example with redis sentinel
68
-
69
- ```yaml
70
- rpc_host: "localhost:50123"
71
- redis_url: "redis://redis-1-1:6379/2"
72
- redis_sentinels:
73
- - { host: 'redis-1-1', port: 26379 }
74
- - { host: 'redis-1-2', port: 26379 }
75
- - { host: 'redis-1-3', port: 26379 }
76
- ```
77
-
78
- ## ActionCable Compatibility
79
-
80
- This is the compatibility list for the AnyCable gem, not for AnyCable servers (which may not support some of the features yet).
81
-
82
- Feature | Status
83
- -------------------------|--------
84
- Connection Identifiers | +
85
- Connection Request (cookies, params) | +
86
- Disconnect Handling | +
87
- Subscribe to channels | +
88
- Parameterized subscriptions | +
89
- Unsubscribe from channels | +
90
- [Subscription Instance Variables](http://edgeapi.rubyonrails.org/classes/ActionCable/Channel/Streams.html) | -
91
- Performing Channel Actions | +
92
- Streaming | +
93
- [Custom stream callbacks](http://edgeapi.rubyonrails.org/classes/ActionCable/Channel/Streams.html) | -
94
- Broadcasting | +
95
- Custom pubsub adapter | Only redis
96
-
97
51
  ## Build
98
52
 
99
53
  - Install required GRPC gems:
@@ -117,3 +71,8 @@ Please, provide reproduction script (using [this template](https://github.com/an
117
71
 
118
72
  ## License
119
73
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
74
+
75
+ ## Security Contact
76
+
77
+ To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
78
+
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "anycable/cli"
4
+
5
+ begin
6
+ cli = AnyCable::CLI.new
7
+ cli.run(ARGV)
8
+ rescue => e
9
+ raise e if $DEBUG
10
+ STDERR.puts e.message
11
+ STDERR.puts e.backtrace.join("\n")
12
+ exit 1
13
+ end
@@ -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,59 +1,110 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "anycable/version"
4
- require "anycable/config"
5
4
  require "logger"
6
5
 
7
- # Anycable allows to use any websocket service (written in any language) as a replacement
6
+ require "anycable/exceptions_handling"
7
+ require "anycable/broadcast_adapters"
8
+
9
+ require "anycable/middleware_chain"
10
+
11
+ require "anycable/server"
12
+
13
+ # AnyCable allows to use any websocket service (written in any language) as a replacement
8
14
  # for ActionCable server.
9
15
  #
10
- # Anycable includes a gRPC server, which is used by external WS server to execute commands
16
+ # AnyCable includes a gRPC server, which is used by external WS server to execute commands
11
17
  # (authentication, subscription authorization, client-to-server messages).
12
18
  #
13
- # Broadcasting messages to WS is done through Redis Pub/Sub.
14
- module Anycable
19
+ # Broadcasting messages to WS is done through _broadcast adapter_ (Redis Pub/Sub by default).
20
+ module AnyCable
15
21
  class << self
16
22
  # Provide connection factory which
17
23
  # is a callable object with build
18
24
  # a Connection object
19
25
  attr_accessor :connection_factory
20
26
 
21
- def logger=(logger)
22
- @logger = logger
23
- end
27
+ attr_writer :logger
28
+
29
+ attr_reader :middleware
24
30
 
25
31
  def logger
26
32
  return @logger if instance_variable_defined?(:@logger)
27
- log_output = Anycable.config.log_file || STDOUT
33
+
34
+ log_output = AnyCable.config.log_file || STDOUT
28
35
  @logger = Logger.new(log_output).tap do |logger|
29
- logger.level = Anycable.config.log_level
36
+ logger.level = AnyCable.config.log_level
30
37
  end
31
38
  end
32
39
 
33
40
  def config
34
- @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
35
47
  end
36
48
 
37
49
  def configure
38
50
  yield(config) if block_given?
39
51
  end
40
52
 
53
+ # Register a custom block that will be called
54
+ # when an exception is raised during gRPC call
55
+ def capture_exception(&block)
56
+ ExceptionsHandling << block
57
+ end
58
+
41
59
  def error_handlers
42
- return @error_handlers if instance_variable_defined?(:@error_handlers)
43
- @error_handlers = []
60
+ warn <<~DEPRECATION
61
+ Using `AnyCable.error_handlers` is deprecated!
62
+ Please, use `AnyCable.capture_exception` instead.
63
+ DEPRECATION
64
+ ExceptionsHandling
65
+ end
66
+
67
+ # Register a callback to be invoked before
68
+ # the server starts
69
+ def configure_server(&block)
70
+ server_callbacks << block
44
71
  end
45
72
 
46
- def pubsub
47
- @pubsub ||= PubSub.new
73
+ def server_callbacks
74
+ @server_callbacks ||= []
75
+ end
76
+
77
+ def broadcast_adapter
78
+ self.broadcast_adapter = :redis unless instance_variable_defined?(:@broadcast_adapter)
79
+ @broadcast_adapter
80
+ end
81
+
82
+ def broadcast_adapter=(adapter)
83
+ if adapter.is_a?(Symbol) || adapter.is_a?(Array)
84
+ adapter = BroadcastAdapters.lookup_adapter(adapter)
85
+ end
86
+
87
+ unless adapter.respond_to?(:broadcast)
88
+ raise ArgumentError, "BroadcastAdapter must implement #broadcast method. " \
89
+ "#{adapter.class} doesn't implement it."
90
+ end
91
+
92
+ @broadcast_adapter = adapter
48
93
  end
49
94
 
50
95
  # Raw broadcast message to the channel, sends only string!
51
96
  # To send hash or object use ActionCable.server.broadcast instead!
52
97
  def broadcast(channel, payload)
53
- pubsub.broadcast(channel, payload)
98
+ broadcast_adapter.broadcast(channel, payload)
54
99
  end
100
+
101
+ private
102
+
103
+ attr_writer :middleware
55
104
  end
105
+
106
+ self.middleware = MiddlewareChain.new
56
107
  end
57
108
 
58
- require "anycable/server"
59
- require "anycable/pubsub"
109
+ # Backward compatibility
110
+ Anycable = AnyCable