anycable-rack-server 0.0.1 → 0.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.
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'anycable/rack-server/logging'
3
+ require "anycable/rack/logging"
4
4
 
5
5
  module AnyCable
6
- module RackServer
6
+ module Rack
7
+ # Socket wrapper
7
8
  class Socket
8
9
  include Logging
9
10
  attr_reader :version, :socket
@@ -14,11 +15,11 @@ module AnyCable
14
15
  @socket = socket
15
16
  @version = version
16
17
 
17
- @_open_handlers = []
18
+ @_open_handlers = []
18
19
  @_message_handlers = []
19
- @_close_handlers = []
20
- @_error_handlers = []
21
- @_active = true
20
+ @_close_handlers = []
21
+ @_error_handlers = []
22
+ @_active = true
22
23
  end
23
24
 
24
25
  def transmit(data, type: :text)
@@ -28,13 +29,13 @@ module AnyCable
28
29
  type: type
29
30
  )
30
31
  socket.write(frame.to_s)
31
- rescue IOError, Errno::EPIPE, Errno::ETIMEDOUT => e
32
+ rescue Exception => e # rubocop:disable Lint/RescueException
32
33
  log(:error, "Socket send failed: #{e}")
33
34
  close
34
35
  end
35
36
 
36
37
  def request
37
- @_request ||= ::Rack::Request.new(@env)
38
+ @request ||= ::Rack::Request.new(@env)
38
39
  end
39
40
 
40
41
  def onopen(&block)
@@ -53,22 +54,19 @@ module AnyCable
53
54
  @_error_handlers << block
54
55
  end
55
56
 
56
- # rubocop: disable Metrics/MethodLength
57
57
  def listen
58
58
  keepalive
59
59
  Thread.new do
60
- Thread.current.abort_on_exception = true
60
+ Thread.current.report_on_exception = true
61
61
  begin
62
62
  @_open_handlers.each(&:call)
63
63
  each_frame do |data|
64
64
  @_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
65
+ handler.call(data)
66
+ rescue => e # rubocop: disable Style/RescueStandardError
67
+ log(:error, "Socket receive failed: #{e}")
68
+ @_error_handlers.each { |eh| eh.call(e, data) }
69
+ close
72
70
  end
73
71
  end
74
72
  ensure
@@ -76,7 +74,6 @@ module AnyCable
76
74
  end
77
75
  end
78
76
  end
79
- # rubocop: enable Metrics/MethodLength
80
77
 
81
78
  def close
82
79
  return unless @_active
@@ -105,7 +102,7 @@ module AnyCable
105
102
  frame = WebSocket::Frame::Outgoing::Server.new(version: version, type: :close, code: 1000)
106
103
  socket.write(frame.to_s) if frame.supported?
107
104
  socket.close
108
- rescue IOError, Errno::EPIPE, Errno::ETIMEDOUT # rubocop:disable Lint/HandleExceptions
105
+ rescue Exception # rubocop:disable Lint/RescueException
109
106
  # already closed
110
107
  end
111
108
 
@@ -114,8 +111,7 @@ module AnyCable
114
111
  Thread.current.abort_on_exception = true
115
112
  loop do
116
113
  sleep 5
117
- time = Time.now.to_i
118
- transmit({ message: time, type: :ping }.to_json)
114
+ transmit nil, type: :ping
119
115
  end
120
116
  end
121
117
 
@@ -124,24 +120,21 @@ module AnyCable
124
120
  end
125
121
  end
126
122
 
127
- # rubocop:disable Metrics/AbcSize
128
- # rubocop:disable Metrics/CyclomaticComplexity
129
- # rubocop:disable Metrics/PerceivedComplexity
130
- # rubocop:disable Metrics/MethodLength
131
123
  def each_frame
132
124
  framebuffer = WebSocket::Frame::Incoming::Server.new(version: version)
133
125
  while IO.select([socket])
134
126
  if socket.respond_to?(:recvfrom)
135
127
  data, _addrinfo = socket.recvfrom(2000)
136
128
  else
137
- data, _addrinfo = socket.readpartial(2000), socket.peeraddr
129
+ data = socket.readpartial(2000)
130
+ _addrinfo = socket.peeraddr
138
131
  end
139
132
 
140
133
  break if data.empty?
141
134
 
142
135
  framebuffer << data
143
136
 
144
- while frame = framebuffer.next
137
+ while frame = framebuffer.next # rubocop:disable Lint/AssignmentInCondition
145
138
  case frame.type
146
139
  when :close
147
140
  return
@@ -150,7 +143,7 @@ module AnyCable
150
143
  end
151
144
  end
152
145
  end
153
- rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNRESET, IOError, Errno::EBADF => e
146
+ rescue Exception => e # rubocop:disable Lint/RescueException
154
147
  log(:error, "Socket frame error: #{e}")
155
148
  nil # client disconnected or timed out
156
149
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AnyCable
4
- module RackServer
5
- VERSION = '0.0.1'
4
+ module Rack
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,99 +1,162 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-rack-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.3.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-06 00:00:00.000000000 Z
12
+ date: 2021-05-12 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
+ - - ">"
33
+ - !ruby/object:Gem::Version
34
+ version: 1.0.99
35
+ - - "<"
18
36
  - !ruby/object:Gem::Version
19
- version: '0.6'
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'
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'
89
+ version: '0'
69
90
  - !ruby/object:Gem::Dependency
70
91
  name: minitest
71
92
  requirement: !ruby/object:Gem::Requirement
72
93
  requirements:
73
94
  - - "~>"
74
95
  - !ruby/object:Gem::Version
75
- version: '5.11'
96
+ version: '5.10'
76
97
  type: :development
77
98
  prerelease: false
78
99
  version_requirements: !ruby/object:Gem::Requirement
79
100
  requirements:
80
101
  - - "~>"
81
102
  - !ruby/object:Gem::Version
82
- version: '5.11'
103
+ version: '5.10'
104
+ - !ruby/object:Gem::Dependency
105
+ name: puma
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
83
118
  - !ruby/object:Gem::Dependency
84
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
85
134
  requirement: !ruby/object:Gem::Requirement
86
135
  requirements:
87
136
  - - "~>"
88
137
  - !ruby/object:Gem::Version
89
- version: '12.3'
138
+ version: '4'
90
139
  type: :development
91
140
  prerelease: false
92
141
  version_requirements: !ruby/object:Gem::Requirement
93
142
  requirements:
94
143
  - - "~>"
95
144
  - !ruby/object:Gem::Version
96
- version: '12.3'
145
+ version: '4'
146
+ - !ruby/object:Gem::Dependency
147
+ name: rubocop
148
+ requirement: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0.80'
153
+ type: :development
154
+ prerelease: false
155
+ version_requirements: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0.80'
97
160
  description: AnyCable-compatible Ruby Rack middleware
98
161
  email: yulia.oletskaya@gmail.com
99
162
  executables: []
@@ -103,24 +166,28 @@ files:
103
166
  - LICENSE
104
167
  - README.md
105
168
  - lib/anycable-rack-server.rb
106
- - lib/anycable/rack-server.rb
107
- - lib/anycable/rack-server/broadcast_subscribers/redis_subscriber.rb
108
- - lib/anycable/rack-server/coders/json.rb
109
- - lib/anycable/rack-server/connection.rb
110
- - lib/anycable/rack-server/errors.rb
111
- - lib/anycable/rack-server/hub.rb
112
- - lib/anycable/rack-server/logging.rb
113
- - lib/anycable/rack-server/middleware.rb
114
- - lib/anycable/rack-server/pinger.rb
115
- - lib/anycable/rack-server/rpc/client.rb
116
- - lib/anycable/rack-server/rpc/rpc.proto
117
- - lib/anycable/rack-server/socket.rb
118
- - lib/anycable/rack-server/version.rb
119
- homepage:
169
+ - lib/anycable/rack/broadcast_subscribers/base_subscriber.rb
170
+ - lib/anycable/rack/broadcast_subscribers/http_subscriber.rb
171
+ - lib/anycable/rack/broadcast_subscribers/redis_subscriber.rb
172
+ - lib/anycable/rack/coders/json.rb
173
+ - lib/anycable/rack/config.rb
174
+ - lib/anycable/rack/connection.rb
175
+ - lib/anycable/rack/errors.rb
176
+ - lib/anycable/rack/hub.rb
177
+ - lib/anycable/rack/logging.rb
178
+ - lib/anycable/rack/middleware.rb
179
+ - lib/anycable/rack/pinger.rb
180
+ - lib/anycable/rack/railtie.rb
181
+ - lib/anycable/rack/rpc/client.rb
182
+ - lib/anycable/rack/rpc/rpc.proto
183
+ - lib/anycable/rack/server.rb
184
+ - lib/anycable/rack/socket.rb
185
+ - lib/anycable/rack/version.rb
186
+ homepage:
120
187
  licenses:
121
188
  - MIT
122
189
  metadata: {}
123
- post_install_message:
190
+ post_install_message:
124
191
  rdoc_options: []
125
192
  require_paths:
126
193
  - lib
@@ -135,9 +202,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
202
  - !ruby/object:Gem::Version
136
203
  version: '0'
137
204
  requirements: []
138
- rubyforge_project:
139
- rubygems_version: 2.7.6
140
- signing_key:
205
+ rubygems_version: 3.2.15
206
+ signing_key:
141
207
  specification_version: 4
142
- summary: Anycable Rack Server
208
+ summary: AnyCable Rack Server
143
209
  test_files: []
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'set'
4
- require 'json'
5
- require 'anycable'
6
- require 'websocket'
7
- require 'securerandom'
8
- require 'anycable/rack-server/hub'
9
- require 'anycable/rack-server/pinger'
10
- require 'anycable/rack-server/errors'
11
- require 'anycable/rack-server/middleware'
12
- require 'anycable/rack-server/broadcast_subscribers/redis_subscriber'
13
- require 'anycable/rack-server/coders/json'
14
-
15
- module AnyCable
16
- module RackServer
17
- DEFAULT_OPTIONS = {
18
- headers: ['cookie', 'x-api-token']
19
- }.freeze
20
-
21
- class << self
22
- attr_reader :broadcast_subscriber,
23
- :coder,
24
- :hub,
25
- :middleware,
26
- :pinger,
27
- :server_id
28
-
29
- def start(options = {})
30
- options = DEFAULT_OPTIONS.merge(options)
31
- @hub = Hub.new
32
- @pinger = Pinger.new
33
- @coder = Coders::JSON
34
-
35
- rpc_host = unpack_host(AnyCable.config.rpc_host)
36
- headers = parse_env_headers || options[:headers]
37
-
38
- @server_id = "anycable-rack-server-#{SecureRandom.hex}"
39
- @middleware = Middleware.new(
40
- nil,
41
- pinger: pinger,
42
- hub: hub,
43
- coder: coder,
44
- rpc_host: rpc_host,
45
- headers: headers,
46
- server_id: server_id
47
- )
48
-
49
- broadcast_subscribe
50
-
51
- @_started = true
52
- end
53
-
54
- def started?
55
- @_started == true
56
- end
57
-
58
- def stop
59
- return unless started?
60
-
61
- @_started = false
62
- broadcast_subscriber.unsubscribe(@_redis_channel)
63
- pinger.stop
64
-
65
- hub.sockets.each do |socket|
66
- hub.remove_socket(socket)
67
- socket.close
68
- end
69
- end
70
-
71
- private
72
-
73
- def broadcast_subscribe
74
- @_redis_params = AnyCable.config.to_redis_params
75
- @_redis_channel = AnyCable.config.redis_channel
76
-
77
- @broadcast_subscriber = BroadcastSubscribers::RedisSubscriber.new(
78
- hub: @hub,
79
- coder: @coder,
80
- options: @_redis_params
81
- )
82
-
83
- @broadcast_subscriber.subscribe(@_redis_channel)
84
- end
85
-
86
- def parse_env_headers
87
- headers = ENV['ANYCABLE_HEADERS'].to_s.split(',')
88
- return nil if headers.empty?
89
- headers
90
- end
91
-
92
- def unpack_host(str)
93
- str.gsub('[::]', '0.0.0.0')
94
- end
95
- end
96
- end
97
-
98
- class Rack
99
- def initialize(_app = nil, options = {})
100
- AnyCable::RackServer.start(options)
101
- end
102
-
103
- def call(env)
104
- AnyCable::RackServer.middleware.call(env)
105
- end
106
- end
107
- end