anyt-core 1.3.0

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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +38 -0
  4. data/bin/anyt +17 -0
  5. data/bin/console +7 -0
  6. data/bin/setup +8 -0
  7. data/lib/anyt/cli.rb +211 -0
  8. data/lib/anyt/client.rb +146 -0
  9. data/lib/anyt/command.rb +83 -0
  10. data/lib/anyt/config.rb +41 -0
  11. data/lib/anyt/dummy/application.rb +86 -0
  12. data/lib/anyt/dummy/config.ru +16 -0
  13. data/lib/anyt/dummy/routes.rb +4 -0
  14. data/lib/anyt/dummy/tmp/development_secret.txt +1 -0
  15. data/lib/anyt/dummy/tmp/local_secret.txt +1 -0
  16. data/lib/anyt/ext/minitest.rb +151 -0
  17. data/lib/anyt/remote_control.rb +33 -0
  18. data/lib/anyt/rpc.rb +44 -0
  19. data/lib/anyt/tests/core/ping_test.rb +23 -0
  20. data/lib/anyt/tests/core/welcome_test.rb +10 -0
  21. data/lib/anyt/tests/features/channel_state_test.rb +81 -0
  22. data/lib/anyt/tests/features/remote_disconnect_test.rb +35 -0
  23. data/lib/anyt/tests/features/server_restart_test.rb +30 -0
  24. data/lib/anyt/tests/request/channel_test.rb +28 -0
  25. data/lib/anyt/tests/request/connection_test.rb +54 -0
  26. data/lib/anyt/tests/request/disconnect_reasons_test.rb +25 -0
  27. data/lib/anyt/tests/request/disconnection_test.rb +148 -0
  28. data/lib/anyt/tests/streams/broadcast_test.rb +65 -0
  29. data/lib/anyt/tests/streams/multiple_clients_test.rb +61 -0
  30. data/lib/anyt/tests/streams/multiple_test.rb +60 -0
  31. data/lib/anyt/tests/streams/single_test.rb +83 -0
  32. data/lib/anyt/tests/streams/stop_test.rb +57 -0
  33. data/lib/anyt/tests/subscriptions/ack_test.rb +39 -0
  34. data/lib/anyt/tests/subscriptions/params_test.rb +29 -0
  35. data/lib/anyt/tests/subscriptions/perform_test.rb +60 -0
  36. data/lib/anyt/tests/subscriptions/transmissions_test.rb +32 -0
  37. data/lib/anyt/tests.rb +62 -0
  38. data/lib/anyt/utils/async_helpers.rb +16 -0
  39. data/lib/anyt/utils.rb +3 -0
  40. data/lib/anyt/version.rb +5 -0
  41. data/lib/anyt.rb +14 -0
  42. metadata +167 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cd161ab373ec324f2d6ab9f17419858fae589bee036122ce1dac7039999ba360
4
+ data.tar.gz: b94fb021fab87a9d97f0a1bd3502142e969dd8982662805b0c0f5695ae7e7f45
5
+ SHA512:
6
+ metadata.gz: 3bdbfe03f6aaa1bd8ae6e1cf606e900e56ed06b3e8dda894c73bd89df6484ceeb14e18be2f697f83ea1407a9a24734da32d4988baef423fd84780a201feb55ff
7
+ data.tar.gz: 7f7d8927b2f2d19734c101f91a5beecaeabea5dfed0b7346abdcd0feab50e2daaddafbb5a3b8041c5eed90c4dc443d68a8d1b5f303647680ed3577b92539a708
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016-2020 palkan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ [![Cult Of Martians](http://cultofmartians.com/assets/badges/badge.svg)](https://cultofmartians.com/tasks/anycable-conformance-tool.html#task)
2
+ [![Gem Version](https://badge.fury.io/rb/anyt.svg)](https://rubygems.org/gems/anyt)
3
+ ![Test](https://github.com/anycable/anyt/workflows/Test/badge.svg)
4
+
5
+ # Action Cable / AnyCable conformance testing tool
6
+
7
+ AnyT is a command-line tool to test your Action Cable or [AnyCable](http://anycable.io)-compatible WebSocket servers.
8
+
9
+ It contains a set of tests to determine which features are supported by the implementation under consideration.
10
+
11
+ ## Installation
12
+
13
+ ```sh
14
+ gem install anyt
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ You should provide a command to run the server and the target URL for WebSocket clients:
20
+
21
+ ```sh
22
+ anyt -c "anycable-go" --target-url="ws://localhost:8080/cable"
23
+ ```
24
+
25
+ By default it launches gRPC server on `localhost:50051` and use local Redis instance for broadcasts (`localhost:6379`).
26
+
27
+ For more options run:
28
+
29
+ ```sh
30
+ anyt -h
31
+ ```
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/anycable/anyt/issues.
36
+
37
+ ## License
38
+ The library is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/bin/anyt ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'anyt'
6
+ require 'anyt/cli'
7
+
8
+ begin
9
+ exit_code = Anyt::Cli.run
10
+ rescue => e
11
+ puts 'Bummer! There is an error:'
12
+ puts e
13
+ puts e.backtrace.take(10).join("\n")
14
+ exit 1
15
+ end
16
+
17
+ exit exit_code
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'anyt'
5
+ require 'irb'
6
+
7
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/anyt/cli.rb ADDED
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "optparse"
5
+
6
+ require "anyt/version"
7
+ require "anyt/remote_control"
8
+ require "anyt/rpc"
9
+ require "anyt/command"
10
+ require "anyt/tests"
11
+
12
+ $stdout.sync = true
13
+
14
+ module Anyt
15
+ module Cli # :nodoc:
16
+ DUMMY_ROOT = ::File.expand_path(
17
+ "config.ru",
18
+ ::File.join(::File.dirname(__FILE__), "dummy")
19
+ )
20
+
21
+ RAILS_COMMAND = "bundle exec puma #{DUMMY_ROOT} -t #{ENV.fetch("RAILS_MAX_THREADS", 5)}"
22
+
23
+ class << self
24
+ # CLI entrypoint
25
+ def run(args = ARGV)
26
+ parse_options!(args)
27
+
28
+ ActionCable.server.config.logger = Rails.logger = AnyCable.logger
29
+
30
+ result = 1
31
+
32
+ $stdout.puts "Starting AnyT v#{Anyt::VERSION} (pid: #{Process.pid})\n"
33
+
34
+ begin
35
+ # "Enable" AnyCable as early as possible to activate all the features in tests
36
+ unless Anyt.config.use_action_cable
37
+ ActionCable.server.config.cable = {"adapter" => "any_cable"}
38
+ require "anycable-rails"
39
+ end
40
+
41
+ # Load all test scenarios
42
+ Tests.load_tests unless @skip_tests
43
+
44
+ Rails.application.initialize!
45
+
46
+ # Start RPC server (unless specified otherwise, e.g. when
47
+ # we want to test Action Cable itself)
48
+ unless @skip_rpc
49
+ http_rpc = AnyCable.config.http_rpc_mount_path.present?
50
+
51
+ @rpc_command =
52
+ if http_rpc
53
+ Command.new(RAILS_COMMAND)
54
+ else
55
+ RPC.new
56
+ end
57
+
58
+ @rpc_command.start
59
+
60
+ if @only_rpc
61
+ if http_rpc
62
+ wait_till_terminated
63
+ else
64
+ @rpc_command.server.wait_till_terminated
65
+ end
66
+ return
67
+ end
68
+ end
69
+
70
+ # Start webosocket server under test
71
+ @command = Command.default
72
+ @command.run
73
+
74
+ unless @skip_tests
75
+ # Run tests
76
+ result = Tests.run ? 0 : 1
77
+ end
78
+
79
+ wait_till_terminated if @only_rails
80
+ rescue Interrupt => e
81
+ $stdout.puts "#{e.message}. Good-bye!"
82
+ ensure
83
+ @rpc_command&.stop unless @skip_rpc
84
+ @command&.stop
85
+ end
86
+
87
+ result
88
+ end
89
+
90
+ private
91
+
92
+ def parse_options!(args)
93
+ parser =
94
+ OptionParser.new do |cli|
95
+ cli.banner = <<~BANNER
96
+ Anyt – AnyCable websocket server conformance tool.
97
+
98
+ Usage: anyt [options]
99
+
100
+ Options:
101
+ BANNER
102
+
103
+ cli.on("-cCOMMAND", "--command=COMMAND", "Command to run WS server.") do |command|
104
+ Anyt.config.command = command
105
+ end
106
+
107
+ cli.on("--target-url=TARGET", "URL of target WebSocket server to test.") do |target|
108
+ Anyt.config.target_url = target
109
+ end
110
+
111
+ cli.on("--redis-url=REDIS_URL", "Redis server URL.") do |redis|
112
+ AnyCable.config.redis_url = redis
113
+ end
114
+
115
+ cli.on("--skip-rpc", TrueClass, "Do not run RPC server") do |flag|
116
+ @skip_rpc = flag
117
+ end
118
+
119
+ cli.on("--only-rpc", TrueClass, "Run only RPC server") do |flag|
120
+ @only_rpc = flag
121
+ end
122
+
123
+ cli.on("--only-rails", TrueClass, "Run only Rails server") do
124
+ @skip_rpc = true
125
+ @only_rails = true
126
+ @skip_tests = true
127
+
128
+ configure_rails_command!
129
+ end
130
+
131
+ cli.on("--self-check", "Run tests again Action Cable itself") do
132
+ @skip_rpc = true
133
+
134
+ configure_rails_command!
135
+ end
136
+
137
+ cli.on("--only test1,test2,test3", Array, "Run only specified tests") do |only_tests|
138
+ Anyt.config.only_tests = only_tests
139
+ end
140
+
141
+ cli.on("--except test1,test2,test3", Array, "Exclude specified tests") do |except_tests|
142
+ Anyt.config.except_tests = except_tests
143
+ end
144
+
145
+ cli.on("--wait-command=TIMEOUT", Integer,
146
+ "Number of seconds to wait for WS server initialization") do |timeout|
147
+ Anyt.config.wait_command = timeout
148
+ end
149
+
150
+ cli.on("--timeout-multiplier=VALUE", Float,
151
+ "Default exceptation timeouts multiplier") do |val|
152
+ Anyt.config.timeout_multiplier = val
153
+ end
154
+
155
+ cli.on("-rPATH", "--require=PATH",
156
+ "Path to additional tests (e.g. features/*.rb") do |path|
157
+ Anyt.config.tests_relative_path = path
158
+ ENV["ANYT_TESTS_RELATIVE_PATH"] = path
159
+ end
160
+
161
+ cli.on("--debug", "Enable debug mode.") do
162
+ AnyCable.config.debug = true
163
+ end
164
+
165
+ cli.on("-h", "--help", "Show this message.") do
166
+ puts cli
167
+ exit
168
+ end
169
+
170
+ cli.on("--version", "Print version.") do
171
+ puts Anyt::VERSION
172
+ exit
173
+ end
174
+ end
175
+
176
+ parser.parse!(args)
177
+ rescue OptionParser::InvalidOption => e
178
+ unknown_option = e.args.first
179
+ puts "This option looks unfamiliar: #{unknown_option}. A typo?"
180
+ puts "Use `anyt --help` to list all available options."
181
+ exit 1
182
+ end
183
+
184
+ def configure_rails_command!
185
+ Anyt.config.command = RAILS_COMMAND
186
+ Anyt.config.use_action_cable = true
187
+ end
188
+
189
+ def wait_till_terminated
190
+ self_read = setup_signals
191
+
192
+ while readable_io = IO.select([self_read]) # rubocop:disable Lint/AssignmentInCondition, Lint/IncompatibleIoSelectWithFiberScheduler
193
+ signal = readable_io.first[0].gets.strip
194
+ raise Interrupt, "SIG#{signal} received"
195
+ end
196
+ end
197
+
198
+ def setup_signals
199
+ self_read, self_write = IO.pipe
200
+
201
+ %w[INT TERM].each do |signal|
202
+ trap signal do
203
+ self_write.puts signal
204
+ end
205
+ end
206
+
207
+ self_read
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "anyt"
4
+
5
+ module Anyt
6
+ # Synchronous websocket client
7
+ # Based on https://github.com/rails/rails/blob/v5.0.1/actioncable/test/client_test.rb
8
+ class Client
9
+ require "websocket-client-simple"
10
+ require "concurrent"
11
+
12
+ class Error < StandardError; end
13
+
14
+ class TimeoutError < Error; end
15
+
16
+ class DisconnectedError < Error
17
+ attr_reader :event
18
+
19
+ def initialize(event)
20
+ @event = event
21
+ if event
22
+ super("WebSocket disconnected (code=#{event.code}, reason=#{event.data})")
23
+ else
24
+ super("WebSocket disconnected abnormally")
25
+ end
26
+ end
27
+ end
28
+
29
+ WAIT_WHEN_EXPECTING_EVENT = 5
30
+ WAIT_WHEN_NOT_EXPECTING_EVENT = 0.5
31
+
32
+ private attr_reader :logger
33
+
34
+ attr_reader :url
35
+
36
+ def initialize(
37
+ ignore: [], url: Anyt.config.target_url, qs: "",
38
+ cookies: "", headers: {},
39
+ protocol: "actioncable-v1-json",
40
+ timeout_multiplier: Anyt.config.timeout_multiplier,
41
+ logger: AnyCable.logger
42
+ )
43
+ @logger = logger
44
+ ignore_message_types = @ignore_message_types = ignore
45
+ messages = @messages = Queue.new
46
+ closed = @closed = Concurrent::Event.new
47
+ has_messages = @has_messages = Concurrent::Semaphore.new(0)
48
+
49
+ @timeout_multiplier = timeout_multiplier
50
+
51
+ headers = headers.merge("cookie" => cookies)
52
+ headers["Sec-WebSocket-Protocol"] = protocol
53
+
54
+ open = Concurrent::Promise.new
55
+
56
+ @url = url
57
+
58
+ if !qs.empty?
59
+ @url += @url.include?("?") ? "&" : "?"
60
+ @url += qs
61
+ end
62
+
63
+ @ws = WebSocket::Client::Simple.connect(
64
+ @url,
65
+ headers: headers
66
+ ) do |ws|
67
+ ws.on(:error) do |event|
68
+ event = RuntimeError.new(event.message) unless event.is_a?(Exception)
69
+
70
+ if open.pending?
71
+ open.fail(event)
72
+ else
73
+ messages << event
74
+ has_messages.release
75
+ end
76
+ end
77
+
78
+ ws.on(:open) do |_event|
79
+ open.set(true)
80
+ end
81
+
82
+ ws.on(:message) do |event|
83
+ next if event.type == :ping
84
+ if event.type == :close
85
+ messages << DisconnectedError.new(event)
86
+ has_messages.release
87
+ closed.set
88
+ else
89
+ message = JSON.parse(event.data)
90
+
91
+ next if ignore_message_types.include?(message["type"])
92
+
93
+ logger.debug "Message received: #{message}"
94
+
95
+ messages << message
96
+ has_messages.release
97
+ end
98
+ end
99
+
100
+ ws.on(:close) do |_event|
101
+ closed.set
102
+ end
103
+ end
104
+
105
+ open.wait!(WAIT_WHEN_EXPECTING_EVENT * @timeout_multiplier)
106
+ end
107
+ # rubocop: enable Metrics/BlockLength
108
+ # rubocop: enable Metrics/AbcSize
109
+ # rubocop: enable Metrics/MethodLength
110
+
111
+ def receive(timeout: WAIT_WHEN_EXPECTING_EVENT)
112
+ timeout *= @timeout_multiplier
113
+
114
+ unless @has_messages.try_acquire(1, timeout)
115
+ raise DisconnectedError if closed?
116
+ raise TimeoutError, "Timed out to receive message"
117
+ end
118
+
119
+ msg = @messages.pop(true)
120
+ raise msg if msg.is_a?(Exception) || msg.is_a?(Error)
121
+
122
+ msg
123
+ end
124
+
125
+ def send(message)
126
+ @ws.send(JSON.generate(message))
127
+ end
128
+
129
+ def close(allow_messages: false)
130
+ sleep WAIT_WHEN_NOT_EXPECTING_EVENT * @timeout_multiplier
131
+
132
+ raise "#{@messages.size} messages unprocessed" unless allow_messages || @messages.empty?
133
+
134
+ @ws.close
135
+ wait_for_close
136
+ end
137
+
138
+ def wait_for_close
139
+ @closed.wait(WAIT_WHEN_EXPECTING_EVENT * @timeout_multiplier)
140
+ end
141
+
142
+ def closed?
143
+ @closed.set?
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "childprocess"
4
+
5
+ module Anyt
6
+ # Runs system command (websocket server)
7
+ class Command
8
+ class << self
9
+ attr_reader :instance
10
+
11
+ def default
12
+ @instance ||= new
13
+ end
14
+
15
+ def restart
16
+ instance&.restart
17
+ end
18
+ end
19
+
20
+ attr_reader :cmd
21
+
22
+ def initialize(cmd = Anyt.config.command)
23
+ @cmd = cmd
24
+ end
25
+
26
+ def run
27
+ return if running?
28
+
29
+ return unless cmd
30
+
31
+ AnyCable.logger.debug "Running command: #{cmd}"
32
+
33
+ @process = ChildProcess.build(*cmd.split(/\s+/))
34
+
35
+ process.io.inherit! if AnyCable.config.debug
36
+
37
+ process.detach = true
38
+
39
+ process.environment["ANYCABLE_DEBUG"] = "1" if AnyCable.config.debug?
40
+ process.environment["ANYT_REMOTE_CONTROL_PORT"] = Anyt.config.remote_control_port
41
+ process.environment["ACTION_CABLE_ADAPTER"] = "any_cable" unless Anyt.config.use_action_cable
42
+
43
+ process.start
44
+
45
+ AnyCable.logger.debug "Command PID: #{process.pid}"
46
+
47
+ sleep Anyt.config.wait_command
48
+ raise "Command failed to start" unless running?
49
+ end
50
+
51
+ alias_method :start, :run
52
+
53
+ # rubocop: enable Metrics/MethodLength
54
+ # rubocop: enable Metrics/AbcSize
55
+
56
+ def restart
57
+ return unless running?
58
+
59
+ AnyCable.logger.debug "Restarting command PID: #{process.pid}"
60
+
61
+ stop
62
+ process.wait
63
+
64
+ run
65
+ end
66
+
67
+ def stop
68
+ return unless running?
69
+
70
+ AnyCable.logger.debug "Terminate PID: #{process.pid}"
71
+
72
+ process.stop
73
+ end
74
+
75
+ def running?
76
+ process&.alive?
77
+ end
78
+
79
+ private
80
+
81
+ attr_reader :process
82
+ end
83
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "anyway"
4
+
5
+ module Anyt
6
+ # Anyt configuration
7
+ class Config < Anyway::Config
8
+ attr_config :command,
9
+ :only_tests,
10
+ :except_tests,
11
+ :tests_relative_path,
12
+ remote_control_port: 8919,
13
+ use_action_cable: false,
14
+ target_url: "ws://localhost:9292/cable",
15
+ wait_command: 2,
16
+ timeout_multiplier: 1
17
+
18
+ coerce_types only_tests: {type: :string, array: true}
19
+ coerce_types except_tests: {type: :string, array: true}
20
+
21
+ def tests_path
22
+ return unless tests_relative_path
23
+
24
+ File.expand_path(tests_relative_path, Dir.pwd)
25
+ end
26
+
27
+ def filter_tests?
28
+ only_tests || except_tests
29
+ end
30
+
31
+ def tests_filter
32
+ only_rxp = /(#{only_tests.join("|")})/ if only_tests
33
+ except_rxp = /(#{except_tests.join("|")})/ if except_tests
34
+
35
+ @tests_filter ||= lambda do |path|
36
+ (only_rxp.nil? || only_rxp.match?(path)) &&
37
+ (except_rxp.nil? || !except_rxp.match?(path))
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+ require "action_controller/railtie"
5
+ require "action_cable/engine"
6
+
7
+ require "redis"
8
+ require "anycable-rails"
9
+
10
+ require "action_dispatch/middleware/cookies"
11
+
12
+ class TestApp < Rails::Application
13
+ config.load_defaults 7.0
14
+
15
+ config.logger = Logger.new($stdout)
16
+ config.log_level = AnyCable.config.log_level
17
+ config.eager_load = true
18
+
19
+ config.paths["config/routes.rb"] << File.join(__dir__, "routes.rb")
20
+ end
21
+
22
+ DISCONNECT_DELAY = ENV["ANYCABLE_DISCONNECT_DELAY"].to_f
23
+
24
+ module ApplicationCable
25
+ class Connection < ActionCable::Connection::Base
26
+ delegate :params, to: :request
27
+
28
+ identified_by :uid
29
+
30
+ def connect
31
+ logger.debug "Connected"
32
+ Anyt::ConnectHandlers.call(self)
33
+ end
34
+
35
+ def disconnect
36
+ if DISCONNECT_DELAY > 0
37
+ sleep DISCONNECT_DELAY
38
+ end
39
+ logger.debug "Disconnected"
40
+ end
41
+ end
42
+ end
43
+
44
+ module ApplicationCable
45
+ class Channel < ActionCable::Channel::Base
46
+ end
47
+ end
48
+
49
+ ECHO_DELAY = ENV["ANYCABLE_BENCHMARK_ECHO_DELAY"].to_f
50
+
51
+ # BenchmarkChannel is useful when running Rails app only or RPC only
52
+ class BenchmarkChannel < ApplicationCable::Channel
53
+ def subscribed
54
+ stream_from "all#{stream_id}"
55
+ end
56
+
57
+ def echo(data)
58
+ if ECHO_DELAY > 0
59
+ sleep ECHO_DELAY
60
+ end
61
+ transmit data
62
+ end
63
+
64
+ def broadcast(data)
65
+ ActionCable.server.broadcast "all#{stream_id}", data
66
+ data["action"] = "broadcastResult"
67
+ transmit data
68
+ end
69
+
70
+ def counter(data)
71
+ num = data.fetch("num", 100).to_i
72
+ num.times { ActionCable.server.broadcast "all", {text: "Count: #{_1}"} }
73
+ end
74
+
75
+ private
76
+
77
+ def stream_id
78
+ params[:id] || ""
79
+ end
80
+ end
81
+
82
+ ActionCable.server.config.cable = {"adapter" => ENV.fetch("ACTION_CABLE_ADAPTER", "redis")}
83
+ ActionCable.server.config.connection_class = -> { ApplicationCable::Connection }
84
+ ActionCable.server.config.disable_request_forgery_protection = true
85
+ ActionCable.server.config.logger =
86
+ Rails.logger
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "application"
4
+
5
+ require_relative "../tests"
6
+ require_relative "../remote_control"
7
+
8
+ # Start remote control
9
+ Anyt::RemoteControl::Server.start(Anyt.config.remote_control_port)
10
+
11
+ # Load channels from tests
12
+ Anyt::Tests.load_all_tests
13
+
14
+ Rails.application.initialize!
15
+
16
+ run Rails.application
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ end
@@ -0,0 +1 @@
1
+ fe2ecbcf229d5547a64bcdaa9ef4e543404ca3fc9d4ee83aaa7ddab34b6a378fe090c2b1836c9ebd3e5ebbf01c239ddac95e219358baaefc1afaa04cd07bf78c
@@ -0,0 +1 @@
1
+ 8e4e6bba332e819bd6597b2e8961ca1c0ef0c9bcb3401214ea22155b729e262534cefed3012024f57b098e0756baddea2d145675da33f31a0844df44c9230141