anycable 0.6.1 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -2
  3. data/bin/anycable +1 -1
  4. data/bin/anycabled +30 -0
  5. data/lib/anycable/broadcast_adapters/redis.rb +1 -1
  6. data/lib/anycable/cli.rb +1 -1
  7. data/lib/anycable/config.rb +4 -2
  8. data/lib/anycable/exceptions_handling.rb +9 -3
  9. data/lib/anycable/rpc_handler.rb +27 -4
  10. data/lib/anycable/server.rb +22 -6
  11. data/lib/anycable/version.rb +1 -1
  12. metadata +7 -56
  13. data/.github/ISSUE_TEMPLATE.md +0 -25
  14. data/.github/PULL_REQUEST_TEMPLATE.md +0 -31
  15. data/.gitignore +0 -40
  16. data/.hound.yml +0 -3
  17. data/.rubocop.yml +0 -71
  18. data/.travis.yml +0 -16
  19. data/Gemfile +0 -8
  20. data/Makefile +0 -5
  21. data/PITCHME.md +0 -139
  22. data/PITCHME.yaml +0 -1
  23. data/Rakefile +0 -8
  24. data/anycable.gemspec +0 -35
  25. data/assets/Memory3.png +0 -0
  26. data/assets/Memory5.png +0 -0
  27. data/assets/RTT3.png +0 -0
  28. data/assets/RTT5.png +0 -0
  29. data/assets/Scheme1.png +0 -0
  30. data/assets/Scheme2.png +0 -0
  31. data/assets/cpu_chart.gif +0 -0
  32. data/assets/cpu_chart2.gif +0 -0
  33. data/assets/evlms.png +0 -0
  34. data/benchmarks/.gitignore +0 -2
  35. data/benchmarks/2017-02-12.md +0 -308
  36. data/benchmarks/2018-03-04.md +0 -192
  37. data/benchmarks/2018-05-27-rpc-bench.md +0 -57
  38. data/benchmarks/2018-10-27.md +0 -181
  39. data/benchmarks/HowTo.md +0 -23
  40. data/benchmarks/ansible.cfg +0 -9
  41. data/benchmarks/assets/2018-10-27-action-cable-rss.png +0 -0
  42. data/benchmarks/assets/2018-10-27-action-cable-rtt.png +0 -0
  43. data/benchmarks/assets/2018-10-27-anycable-rss.png +0 -0
  44. data/benchmarks/assets/2018-10-27-anycable-rtt.png +0 -0
  45. data/benchmarks/assets/2018-10-27-async-rss.png +0 -0
  46. data/benchmarks/assets/2018-10-27-async-rtt.png +0 -0
  47. data/benchmarks/assets/2018-10-27-falcon-cable-rss.png +0 -0
  48. data/benchmarks/assets/2018-10-27-falcon-cable-rtt.png +0 -0
  49. data/benchmarks/assets/2018-10-27-iodine-cable-rss.png +0 -0
  50. data/benchmarks/assets/2018-10-27-iodine-cable-rtt.png +0 -0
  51. data/benchmarks/assets/2018-10-27-plezi-rss.png +0 -0
  52. data/benchmarks/assets/2018-10-27-plezi-rtt.png +0 -0
  53. data/benchmarks/bench.png +0 -0
  54. data/benchmarks/benchmark.yml +0 -69
  55. data/benchmarks/hosts +0 -5
  56. data/benchmarks/rtt_plot.py +0 -74
  57. data/benchmarks/rtt_plot_test.py +0 -16
  58. data/benchmarks/servers.yml +0 -58
  59. data/circle.yml +0 -8
  60. data/etc/bug_report_template.rb +0 -76
  61. data/lib/anycable/handler/capture_exceptions.rb +0 -39
  62. data/protos/rpc.proto +0 -55
@@ -1,9 +0,0 @@
1
- [defaults]
2
- deprecation_warnings = False
3
- inventory = ./hosts
4
- allow_world_readable_tmpfiles = True
5
- gathering=smart
6
- transport=paramiko
7
-
8
- [ssh_connection]
9
- pipelining = True
Binary file
@@ -1,69 +0,0 @@
1
- ---
2
- - name: Benchmark Client
3
- hosts: benchmark
4
- sudo: yes
5
- remote_user: ubuntu
6
- gather_facts: False
7
- vars:
8
- server_host: '172.31.21.207'
9
- hostname: ws-bench-client
10
- local_ips: ['172.31.19.119', '172.31.19.120', '172.31.17.121', '172.31.17.122']
11
- # local_ips_str: '-l 172.31.19.119 -l 172.31.19.120 -l 172.31.17.121 -l 172.31.17.122'
12
- local_ips_str: ''
13
- steps: 10
14
- step_size: 1000
15
- sample_size: 100
16
- concurrency: 8
17
- payload_size: 200
18
- prepare: False
19
- log_file: "./last_bench.log"
20
- tasks:
21
- - name: Prepare the machine
22
- tags: prepare
23
- block:
24
- - hostname:
25
- name: "{{ hostname }}"
26
- - lineinfile:
27
- path: /etc/hosts
28
- line: '127.0.0.1 {{ hostname }}'
29
- state: present
30
- - shell: ip addr add {{ item }}/20 dev eth0
31
- with_items: "{{ local_ips }}"
32
-
33
- - name: Print Action Cable command
34
- debug: msg="bin/websocket-bench broadcast {{ local_ips_str }} --concurrent {{ concurrency }} --sample-size {{ sample_size }} --step-size {{ step_size }} --payload-padding {{ payload_size }} --total-steps {{ steps }} --origin http://0.0.0.0 ws://{{ server_host }}:3334/cable --server-type=actioncable"
35
- tags: action_cable
36
-
37
- - name: Action Cable benchmark
38
- become_user: deplo
39
- shell: bin/websocket-bench broadcast {{ local_ips_str }} --concurrent {{ concurrency }} --sample-size {{ sample_size }} --step-size {{ step_size }} --payload-padding {{ payload_size }} --total-steps {{ steps }} --origin http://0.0.0.0 ws://{{ server_host }}:3334/cable --server-type=actioncable
40
- register: bench
41
- tags: action_cable
42
- args:
43
- chdir: /webapps/anycable_bench
44
- ignore_errors: yes
45
-
46
- - name: Print base command
47
- debug: msg="bin/websocket-bench broadcast {{ local_ips_str }} --concurrent {{ concurrency }} --sample-size {{ sample_size }} --step-size {{ step_size }} --payload-padding {{ payload_size }} --total-steps {{ steps }} ws://{{ server_host }}:3334/cable"
48
- tags: base
49
-
50
- - name: Base benchmark
51
- become_user: deplo
52
- shell: bin/websocket-bench broadcast {{ local_ips_str }} --concurrent {{ concurrency }} --sample-size {{ sample_size }} --step-size {{ step_size }} --payload-padding {{ payload_size }} --total-steps {{ steps }} ws://{{ server_host }}:3334/cable
53
- register: bench
54
- tags: base
55
- args:
56
- chdir: /webapps/anycable_bench
57
- ignore_errors: yes
58
-
59
- - name: Benchmark results (stdout)
60
- debug: var=bench.stdout_lines
61
- tags:
62
- - action_cable
63
- - base
64
-
65
- - name: Benchmark results (stderr)
66
- debug: var=bench.stderr_lines
67
- tags:
68
- - action_cable
69
- - base
@@ -1,5 +0,0 @@
1
- [benchmark]
2
- ec2-18-202-197-244.eu-west-1.compute.amazonaws.com ansible_ssh_private_key_file=/Users/palkan/.ssh/macos-dev
3
-
4
- [servers]
5
- ec2-34-255-216-103.eu-west-1.compute.amazonaws.com ansible_ssh_private_key_file=/Users/palkan/.ssh/macos-dev
@@ -1,74 +0,0 @@
1
- #coding: utf-8
2
-
3
- import sys
4
- import os
5
- import re
6
- import argparse
7
-
8
- def process_file(input_file):
9
- log = {}
10
- log['clients'] = []
11
- log['95per'] = []
12
- log['min'] = []
13
- log['med'] = []
14
- log['max'] = []
15
-
16
- for line in input_file:
17
- point = parse_line(line)
18
- if point:
19
- log['clients'].append(point['clients'])
20
- log['95per'].append(point['95per'])
21
- log['min'].append(point['min'])
22
- log['med'].append(point['med'])
23
- log['max'].append(point['max'])
24
- return log
25
-
26
- def parse_line(line):
27
- # clients: 1000 95per-rtt: 1328ms min-rtt: 2ms median-rtt: 457ms max-rtt: 1577ms
28
- matches = re.search('clients:\s+(\d+)\s+95per\-rtt:\s+(\d+)ms\s+min\-rtt:\s+(\d+)ms\s+median\-rtt:\s+(\d+)ms\s+max\-rtt:\s+(\d+)ms', line)
29
- if matches:
30
- return {
31
- 'clients': int(matches.group(1)),
32
- '95per': int(matches.group(2)),
33
- 'min': int(matches.group(3)),
34
- 'med': int(matches.group(4)),
35
- 'max': int(matches.group(5))
36
- }
37
- return False
38
-
39
- def generate_plot(log, output):
40
- import matplotlib.patches as mpatches
41
- import matplotlib.pyplot as plt
42
-
43
- with plt.rc_context({'backend': 'Agg'}):
44
-
45
- fig = plt.figure()
46
- ax = fig.add_subplot(1, 1, 1)
47
-
48
- ax.plot(log['clients'], log['95per'], '-', lw=1, color='r', label='95 percentile')
49
- ax.plot(log['clients'], log['med'], '-', lw=1, color='green', dashes=[10, 5], label='Median')
50
- ax.plot(log['clients'], log['max'], '-', lw=1, color='grey', label='Max')
51
-
52
- ax.set_ylabel('RTT ms', color='r')
53
- ax.set_xlabel('clients num')
54
- ax.set_ylim(0., max(log['max']) * 1.1)
55
-
56
- handles, labels = ax.get_legend_handles_labels()
57
- ax.legend(handles, labels, bbox_to_anchor=(0.4, 1))
58
-
59
- ax.grid()
60
-
61
- fig.savefig(output)
62
-
63
- if __name__ == "__main__":
64
- parser = argparse.ArgumentParser(description='Generate RTT chart')
65
- parser.add_argument('-i', dest='inputfile', type=argparse.FileType('r'), help='input file containing benchmark results', required=True)
66
- parser.add_argument('-o', dest='outputfile', type=argparse.FileType('w'), help='output file to write resulted chart PNG', required=True)
67
-
68
- args = parser.parse_args()
69
-
70
- data = process_file(args.inputfile)
71
-
72
- generate_plot(data, args.outputfile)
73
-
74
- print('Done')
@@ -1,16 +0,0 @@
1
- import unittest
2
- import os
3
- import rtt_plot
4
-
5
- class TestRttPlot(unittest.TestCase):
6
- def test_parse_line(self):
7
- self.assertEqual(
8
- { 'clients': 1000, '95per': 1328, 'min': 2, 'med': 457, 'max': 1577 },
9
- rtt_plot.parse_line(' "clients: 1000 95per-rtt: 1328ms min-rtt: 2ms median-rtt: 457ms max-rtt: 1577ms"')
10
- )
11
- self.assertFalse(
12
- rtt_plot.parse_line('2018/10/28 02:24:13 Missing received broadcasts: expected 23100000, got 23005351')
13
- )
14
-
15
- if __name__ == '__main__':
16
- unittest.main()
@@ -1,58 +0,0 @@
1
- ---
2
- - name: Benchmark Servers
3
- hosts: servers
4
- sudo: yes
5
- remote_user: ubuntu
6
- gather_facts: False
7
- vars:
8
- web_concurrency: 8
9
- tasks:
10
- - name: Kill servers
11
- shell: pid=$(lsof -i:{{item}} -t); kill -TERM $pid || kill -KILL $pid
12
- tags:
13
- - action_cable
14
- - anycable
15
- - plezi
16
- - iodine_cable
17
- - falcon_cable
18
- - falcon_async
19
- - kill
20
- with_items:
21
- - "3334"
22
- ignore_errors: true
23
- - name: Run Action Cable
24
- become_user: deplo
25
- tags: action_cable
26
- command: bash -lc "WEB_CONCURRENCY={{ web_concurrency }} bundle exec rails s -p 3334 -e production"
27
- args:
28
- chdir: /webapps/anycable_bench/ruby/action-cable-server
29
- - name: Run Anycable Go
30
- become_user: deplo
31
- tags: anycable
32
- shell: bash -lc "ANYCABLE_GO_BIN="anycable-go-0.6.0-alpha" ANYCABLE_PORT="3334" bundle exec bin/anycable"
33
- args:
34
- chdir: /webapps/anycable_bench/ruby/action-cable-server
35
- - name: Run Iodine/Plezi
36
- become_user: deplo
37
- tags: plezi
38
- shell: bash -lc "bundle exec iodine -p 3334 -w {{ web_concurrency }} -t 16"
39
- args:
40
- chdir: /webapps/anycable_bench/ruby/plezi-iodine
41
- - name: Run Iodine/ActionCable
42
- become_user: deplo
43
- tags: iodine_cable
44
- shell: bash -lc "RAILS_ENV=production bundle exec iodine -p 3334 -w {{ web_concurrency }} -t 16"
45
- args:
46
- chdir: /webapps/anycable_bench/ruby/action-cable-server
47
- - name: Run Falcon/ActionCable
48
- become_user: deplo
49
- tags: falcon_cable
50
- shell: bash -lc "RAILS_ENV=production bundle exec falcon serve -b http://0.0.0.0:3334"
51
- args:
52
- chdir: /webapps/anycable_bench/ruby/action-cable-server
53
- - name: Run Falcon/Async
54
- become_user: deplo
55
- tags: falcon_async
56
- shell: bash -lc "bundle exec falcon serve -b http://0.0.0.0:3334"
57
- args:
58
- chdir: /webapps/anycable_bench/ruby/falcon
data/circle.yml DELETED
@@ -1,8 +0,0 @@
1
- machine:
2
- ruby:
3
- version: 2.3.0
4
-
5
- dependencies:
6
- pre:
7
- - gem install bundler -v 1.11.2
8
-
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/inline"
4
-
5
- # This reproduction script is based on `anyt` gem
6
- # (https://github.com/anycable/anyt).
7
- #
8
- # See more test examples here:
9
- # https://github.com/anycable/anyt/tree/master/lib/anyt/tests
10
-
11
- gemfile(true) do
12
- source "https://rubygems.org"
13
-
14
- gem "anyt"
15
- end
16
-
17
- require "anyt"
18
- require "anyt/cli"
19
- require "anycable-rails"
20
-
21
- # WebSocket server url
22
- ENV['ANYT_TARGET_URL'] ||= "ws://localhost:8080/cable"
23
-
24
- # Command to launch WebSocket server.
25
- # Comment this line if you want to run WebSocket server manually
26
- ENV['ANYT_COMMAND'] ||= "anycable-go"
27
-
28
- ActionCable.server.config.logger = Rails.logger = AnyCable.logger
29
-
30
- # Test scenario
31
- feature "issue_xyz" do
32
- # This block defines an anonymous channel to test against
33
- channel do
34
- # def subscribed
35
- # stream_from "a"
36
- # end
37
- #
38
- # def perform(data)
39
- # # ...
40
- # end
41
- end
42
-
43
- # You can use minitest/spec features here
44
- before do
45
- # `channel` contains identifier of the anonymous channel defined above
46
- subscribe_request = { command: "subscribe", identifier: { channel: channel }.to_json }
47
-
48
- # `client` represents a websocket client connected to a server
49
- client.send(subscribe_request)
50
-
51
- ack = {
52
- "identifier" => { channel: channel }.to_json, "type" => "confirm_subscription"
53
- }
54
-
55
- # `receive` method returns the first message from the incoming messages queue;
56
- # waits 5s when no messages available
57
- assert_equal ack, client.receive
58
- end
59
-
60
- # describe you bug scenario here
61
- scenario %{
62
- Should work
63
- } do
64
- # ...
65
- end
66
- end
67
-
68
- # Required setup/teardown
69
- begin
70
- Anyt::RPC.start
71
- Anyt::Command.run if Anyt.config.command
72
- Anyt::Tests.run
73
- ensure
74
- Anyt::Command.stop if Anyt.config.command
75
- Anyt::RPC.stop
76
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "anycable/rpc/rpc_pb"
4
-
5
- module AnyCable
6
- module Handler # :nodoc:
7
- # Handle app-level errors.
8
- #
9
- # NOTE: this functionality couldn't be implemeted
10
- # as middleware, 'cause interceptors do not support
11
- # aborting the call and returning a data
12
- module CaptureExceptions
13
- RESPONSE_CLASS = {
14
- command: AnyCable::CommandResponse,
15
- connect: AnyCable::ConnectionResponse,
16
- disconnect: AnyCable::DisconnectResponse
17
- }.freeze
18
-
19
- RESPONSE_CLASS.keys.each do |mid|
20
- module_eval <<~CODE, __FILE__, __LINE__ + 1
21
- def #{mid}(*)
22
- capture_exceptions(:#{mid}) { super }
23
- end
24
- CODE
25
- end
26
-
27
- def capture_exceptions(method_name)
28
- yield
29
- rescue StandardError => exp
30
- AnyCable::ExceptionsHandling.notify(exp)
31
-
32
- RESPONSE_CLASS.fetch(method_name).new(
33
- status: AnyCable::Status::ERROR,
34
- error_msg: exp.message
35
- )
36
- end
37
- end
38
- end
39
- end
@@ -1,55 +0,0 @@
1
- syntax = "proto3";
2
-
3
- package anycable;
4
-
5
- service RPC {
6
- rpc Connect (ConnectionRequest) returns (ConnectionResponse) {}
7
- rpc Command (CommandMessage) returns (CommandResponse) {}
8
- rpc Disconnect (DisconnectRequest) returns (DisconnectResponse) {}
9
- }
10
-
11
- enum Status {
12
- ERROR = 0;
13
- SUCCESS = 1;
14
- FAILURE = 2;
15
- }
16
-
17
- message ConnectionRequest {
18
- string path = 1;
19
- map<string,string> headers = 2;
20
- }
21
-
22
- message ConnectionResponse {
23
- Status status = 1;
24
- string identifiers = 2;
25
- repeated string transmissions = 3;
26
- string error_msg = 4;
27
- }
28
-
29
- message CommandMessage {
30
- string command = 1;
31
- string identifier = 2;
32
- string connection_identifiers = 3;
33
- string data = 4;
34
- }
35
-
36
- message CommandResponse {
37
- Status status = 1;
38
- bool disconnect = 2;
39
- bool stop_streams = 3;
40
- repeated string streams = 4;
41
- repeated string transmissions = 5;
42
- string error_msg = 6;
43
- }
44
-
45
- message DisconnectRequest {
46
- string identifiers = 1;
47
- repeated string subscriptions = 2;
48
- string path = 3;
49
- map<string,string> headers = 4;
50
- }
51
-
52
- message DisconnectResponse {
53
- Status status = 1;
54
- string error_msg = 2;
55
- }