anycable-rack-server 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,6 +4,17 @@ require "anycable/rack/logging"
4
4
 
5
5
  module AnyCable
6
6
  module Rack
7
+ # Wrapper for outgoing data used to correctly set the WS frame type
8
+ class BinaryFrame
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def to_s
14
+ @data.to_s
15
+ end
16
+ end
17
+
7
18
  # Socket wrapper
8
19
  class Socket
9
20
  include Logging
@@ -15,21 +26,23 @@ module AnyCable
15
26
  @socket = socket
16
27
  @version = version
17
28
 
18
- @_open_handlers = []
29
+ @_open_handlers = []
19
30
  @_message_handlers = []
20
- @_close_handlers = []
21
- @_error_handlers = []
22
- @_active = true
31
+ @_close_handlers = []
32
+ @_error_handlers = []
33
+ @_active = true
23
34
  end
24
35
 
25
- def transmit(data, type: :text)
36
+ def transmit(data, type: nil)
37
+ # p "DATA: #{data.class} — #{data.to_s}"
38
+ type ||= data.is_a?(BinaryFrame) ? :binary : :text
26
39
  frame = WebSocket::Frame::Outgoing::Server.new(
27
40
  version: version,
28
41
  data: data,
29
42
  type: type
30
43
  )
31
44
  socket.write(frame.to_s)
32
- rescue IOError, Errno::EPIPE, Errno::ETIMEDOUT => e
45
+ rescue Exception => e # rubocop:disable Lint/RescueException
33
46
  log(:error, "Socket send failed: #{e}")
34
47
  close
35
48
  end
@@ -62,13 +75,11 @@ module AnyCable
62
75
  @_open_handlers.each(&:call)
63
76
  each_frame do |data|
64
77
  @_message_handlers.each do |handler|
65
- begin
66
- handler.call(data)
67
- rescue => e # rubocop: disable Style/RescueStandardError
68
- log(:error, "Socket receive failed: #{e}")
69
- @_error_handlers.each { |eh| eh.call(e, data) }
70
- close
71
- end
78
+ handler.call(data)
79
+ rescue => e # rubocop: disable Style/RescueStandardError
80
+ log(:error, "Socket receive failed: #{e}")
81
+ @_error_handlers.each { |eh| eh.call(e, data) }
82
+ close
72
83
  end
73
84
  end
74
85
  ensure
@@ -104,7 +115,7 @@ module AnyCable
104
115
  frame = WebSocket::Frame::Outgoing::Server.new(version: version, type: :close, code: 1000)
105
116
  socket.write(frame.to_s) if frame.supported?
106
117
  socket.close
107
- rescue IOError, Errno::EPIPE, Errno::ETIMEDOUT
118
+ rescue Exception # rubocop:disable Lint/RescueException
108
119
  # already closed
109
120
  end
110
121
 
@@ -113,8 +124,7 @@ module AnyCable
113
124
  Thread.current.abort_on_exception = true
114
125
  loop do
115
126
  sleep 5
116
- time = Time.now.to_i
117
- transmit({ message: time, type: :ping }.to_json)
127
+ transmit nil, type: :ping
118
128
  end
119
129
  end
120
130
 
@@ -137,7 +147,7 @@ module AnyCable
137
147
 
138
148
  framebuffer << data
139
149
 
140
- while frame = framebuffer.next
150
+ while frame = framebuffer.next # rubocop:disable Lint/AssignmentInCondition
141
151
  case frame.type
142
152
  when :close
143
153
  return
@@ -146,8 +156,8 @@ module AnyCable
146
156
  end
147
157
  end
148
158
  end
149
- rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNRESET, IOError, Errno::EBADF => e
150
- log(:error, "Socket frame error: #{e}")
159
+ rescue Exception => e # rubocop:disable Lint/RescueException
160
+ log(:error, "Socket frame error: #{e}\n #{e.backtrace.take(4).join("\n")}")
151
161
  nil # client disconnected or timed out
152
162
  end
153
163
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AnyCable
4
4
  module Rack
5
- VERSION = "0.1.0"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,71 +1,92 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-rack-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yulia Oletskaya
8
- autorequire:
8
+ - Vladimir Dementyev
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2019-01-14 00:00:00.000000000 Z
12
+ date: 2021-05-14 00:00:00.000000000 Z
12
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: anyway_config
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 2.1.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 2.1.0
13
28
  - !ruby/object:Gem::Dependency
14
29
  name: anycable
15
30
  requirement: !ruby/object:Gem::Requirement
16
31
  requirements:
17
- - - "~>"
32
+ - - ">"
18
33
  - !ruby/object:Gem::Version
19
- version: '0.6'
34
+ version: 1.0.99
35
+ - - "<"
36
+ - !ruby/object:Gem::Version
37
+ version: '2.0'
20
38
  type: :runtime
21
39
  prerelease: false
22
40
  version_requirements: !ruby/object:Gem::Requirement
23
41
  requirements:
24
- - - "~>"
42
+ - - ">"
43
+ - !ruby/object:Gem::Version
44
+ version: 1.0.99
45
+ - - "<"
25
46
  - !ruby/object:Gem::Version
26
- version: '0.6'
47
+ version: '2.0'
27
48
  - !ruby/object:Gem::Dependency
28
- name: websocket
49
+ name: connection_pool
29
50
  requirement: !ruby/object:Gem::Requirement
30
51
  requirements:
31
52
  - - "~>"
32
53
  - !ruby/object:Gem::Version
33
- version: '1.2'
54
+ version: '2.2'
34
55
  type: :runtime
35
56
  prerelease: false
36
57
  version_requirements: !ruby/object:Gem::Requirement
37
58
  requirements:
38
59
  - - "~>"
39
60
  - !ruby/object:Gem::Version
40
- version: '1.2'
61
+ version: '2.2'
41
62
  - !ruby/object:Gem::Dependency
42
- name: redis
63
+ name: websocket
43
64
  requirement: !ruby/object:Gem::Requirement
44
65
  requirements:
45
66
  - - "~>"
46
67
  - !ruby/object:Gem::Version
47
- version: '4'
68
+ version: '1.2'
48
69
  type: :runtime
49
70
  prerelease: false
50
71
  version_requirements: !ruby/object:Gem::Requirement
51
72
  requirements:
52
73
  - - "~>"
53
74
  - !ruby/object:Gem::Version
54
- version: '4'
75
+ version: '1.2'
55
76
  - !ruby/object:Gem::Dependency
56
77
  name: anyt
57
78
  requirement: !ruby/object:Gem::Requirement
58
79
  requirements:
59
- - - "~>"
80
+ - - ">="
60
81
  - !ruby/object:Gem::Version
61
- version: 0.8.4
82
+ version: '0'
62
83
  type: :development
63
84
  prerelease: false
64
85
  version_requirements: !ruby/object:Gem::Requirement
65
86
  requirements:
66
- - - "~>"
87
+ - - ">="
67
88
  - !ruby/object:Gem::Version
68
- version: 0.8.4
89
+ version: '0'
69
90
  - !ruby/object:Gem::Dependency
70
91
  name: minitest
71
92
  requirement: !ruby/object:Gem::Requirement
@@ -96,32 +117,46 @@ dependencies:
96
117
  version: '0'
97
118
  - !ruby/object:Gem::Dependency
98
119
  name: rake
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '13.0'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '13.0'
132
+ - !ruby/object:Gem::Dependency
133
+ name: redis
99
134
  requirement: !ruby/object:Gem::Requirement
100
135
  requirements:
101
136
  - - "~>"
102
137
  - !ruby/object:Gem::Version
103
- version: '12.3'
138
+ version: '4'
104
139
  type: :development
105
140
  prerelease: false
106
141
  version_requirements: !ruby/object:Gem::Requirement
107
142
  requirements:
108
143
  - - "~>"
109
144
  - !ruby/object:Gem::Version
110
- version: '12.3'
145
+ version: '4'
111
146
  - !ruby/object:Gem::Dependency
112
147
  name: rubocop
113
148
  requirement: !ruby/object:Gem::Requirement
114
149
  requirements:
115
- - - "~>"
150
+ - - ">="
116
151
  - !ruby/object:Gem::Version
117
- version: 0.60.0
152
+ version: '0.80'
118
153
  type: :development
119
154
  prerelease: false
120
155
  version_requirements: !ruby/object:Gem::Requirement
121
156
  requirements:
122
- - - "~>"
157
+ - - ">="
123
158
  - !ruby/object:Gem::Version
124
- version: 0.60.0
159
+ version: '0.80'
125
160
  description: AnyCable-compatible Ruby Rack middleware
126
161
  email: yulia.oletskaya@gmail.com
127
162
  executables: []
@@ -131,8 +166,12 @@ files:
131
166
  - LICENSE
132
167
  - README.md
133
168
  - lib/anycable-rack-server.rb
169
+ - lib/anycable/rack/broadcast_subscribers/base_subscriber.rb
170
+ - lib/anycable/rack/broadcast_subscribers/http_subscriber.rb
134
171
  - lib/anycable/rack/broadcast_subscribers/redis_subscriber.rb
135
172
  - lib/anycable/rack/coders/json.rb
173
+ - lib/anycable/rack/coders/msgpack.rb
174
+ - lib/anycable/rack/config.rb
136
175
  - lib/anycable/rack/connection.rb
137
176
  - lib/anycable/rack/errors.rb
138
177
  - lib/anycable/rack/hub.rb
@@ -142,15 +181,14 @@ files:
142
181
  - lib/anycable/rack/railtie.rb
143
182
  - lib/anycable/rack/rpc/client.rb
144
183
  - lib/anycable/rack/rpc/rpc.proto
145
- - lib/anycable/rack/rpc_runner.rb
146
184
  - lib/anycable/rack/server.rb
147
185
  - lib/anycable/rack/socket.rb
148
186
  - lib/anycable/rack/version.rb
149
- homepage:
187
+ homepage:
150
188
  licenses:
151
189
  - MIT
152
190
  metadata: {}
153
- post_install_message:
191
+ post_install_message:
154
192
  rdoc_options: []
155
193
  require_paths:
156
194
  - lib
@@ -165,9 +203,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
203
  - !ruby/object:Gem::Version
166
204
  version: '0'
167
205
  requirements: []
168
- rubyforge_project:
169
- rubygems_version: 2.7.6
170
- signing_key:
206
+ rubygems_version: 3.2.15
207
+ signing_key:
171
208
  specification_version: 4
172
- summary: Anycable Rack Server
209
+ summary: AnyCable Rack Server
173
210
  test_files: []
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "anycable"
4
- require "anycable/rack/logging"
5
-
6
- $stdout.sync = true
7
-
8
- module AnyCable
9
- module Rack
10
- # Runs AnyCable CLI in a separate process
11
- module RPCRunner
12
- class << self
13
- include Logging
14
-
15
- attr_accessor :running, :pid
16
-
17
- def run(root_dir:, command_args: [], rpc_host: "[::]:50051", env: {})
18
- return if @running
19
-
20
- command_args << "--rpc-host=\"#{rpc_host}\""
21
-
22
- command = "bundle exec anycable #{command_args.join(' ')}"
23
-
24
- log(:info, "Running AnyCable (from #{root_dir}): #{command}")
25
-
26
- out = AnyCable.config.debug? ? STDOUT : IO::NULL
27
-
28
- @pid = Dir.chdir(root_dir) do
29
- Process.spawn(
30
- env,
31
- command,
32
- out: out,
33
- err: out
34
- )
35
- end
36
-
37
- log(:debug) { "AnyCable PID: #{pid}" }
38
-
39
- @running = true
40
-
41
- at_exit { stop }
42
- end
43
-
44
- def stop
45
- return unless running
46
-
47
- log(:debug) { "Terminate PID: #{pid}" }
48
-
49
- Process.kill("SIGKILL", pid)
50
-
51
- @running = false
52
- end
53
-
54
- def running?
55
- running == true
56
- end
57
- end
58
- end
59
- end
60
- end