actioncable 5.0.0.beta1.1 → 5.0.0.beta2

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -3
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +60 -44
  5. data/lib/action_cable.rb +2 -1
  6. data/lib/action_cable/channel/base.rb +2 -2
  7. data/lib/action_cable/channel/periodic_timers.rb +3 -3
  8. data/lib/action_cable/channel/streams.rb +4 -4
  9. data/lib/action_cable/connection.rb +4 -1
  10. data/lib/action_cable/connection/base.rb +22 -21
  11. data/lib/action_cable/connection/client_socket.rb +150 -0
  12. data/lib/action_cable/connection/identification.rb +1 -1
  13. data/lib/action_cable/connection/internal_channel.rb +6 -6
  14. data/lib/action_cable/connection/stream.rb +59 -0
  15. data/lib/action_cable/connection/stream_event_loop.rb +94 -0
  16. data/lib/action_cable/connection/subscriptions.rb +0 -1
  17. data/lib/action_cable/connection/web_socket.rb +14 -8
  18. data/lib/action_cable/engine.rb +3 -3
  19. data/lib/action_cable/gem_version.rb +1 -1
  20. data/lib/action_cable/remote_connections.rb +1 -1
  21. data/lib/action_cable/server.rb +0 -4
  22. data/lib/action_cable/server/base.rb +19 -22
  23. data/lib/action_cable/server/broadcasting.rb +1 -8
  24. data/lib/action_cable/server/configuration.rb +25 -5
  25. data/lib/action_cable/server/connections.rb +3 -5
  26. data/lib/action_cable/server/worker.rb +42 -13
  27. data/lib/action_cable/subscription_adapter.rb +8 -0
  28. data/lib/action_cable/subscription_adapter/async.rb +22 -0
  29. data/lib/action_cable/subscription_adapter/base.rb +28 -0
  30. data/lib/action_cable/subscription_adapter/evented_redis.rb +67 -0
  31. data/lib/action_cable/subscription_adapter/inline.rb +35 -0
  32. data/lib/action_cable/subscription_adapter/postgresql.rb +106 -0
  33. data/lib/action_cable/subscription_adapter/redis.rb +163 -0
  34. data/lib/action_cable/subscription_adapter/subscriber_map.rb +53 -0
  35. data/lib/assets/compiled/action_cable.js +473 -0
  36. data/lib/rails/generators/channel/channel_generator.rb +6 -1
  37. metadata +21 -99
  38. data/lib/action_cable/process/logging.rb +0 -10
  39. data/lib/assets/javascripts/action_cable.coffee.erb +0 -23
  40. data/lib/assets/javascripts/action_cable/connection.coffee +0 -84
  41. data/lib/assets/javascripts/action_cable/connection_monitor.coffee +0 -84
  42. data/lib/assets/javascripts/action_cable/consumer.coffee +0 -31
  43. data/lib/assets/javascripts/action_cable/subscription.coffee +0 -68
  44. data/lib/assets/javascripts/action_cable/subscriptions.coffee +0 -78
@@ -5,11 +5,16 @@ module Rails
5
5
 
6
6
  argument :actions, type: :array, default: [], banner: "method method"
7
7
 
8
+ class_option :assets, type: :boolean
9
+
8
10
  check_class_collision suffix: "Channel"
9
11
 
10
12
  def create_channel_file
11
13
  template "channel.rb", File.join('app/channels', class_path, "#{file_name}_channel.rb")
12
- template "assets/channel.coffee", File.join('app/assets/javascripts/channels', class_path, "#{file_name}.coffee")
14
+
15
+ if options[:assets]
16
+ template "assets/channel.coffee", File.join('app/assets/javascripts/channels', class_path, "#{file_name}.coffee")
17
+ end
13
18
  end
14
19
 
15
20
  protected
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actioncable
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.beta1.1
4
+ version: 5.0.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pratik Naik
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-01-25 00:00:00.000000000 Z
12
+ date: 2016-02-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -17,42 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 5.0.0.beta1.1
20
+ version: 5.0.0.beta2
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 5.0.0.beta1.1
27
+ version: 5.0.0.beta2
28
28
  - !ruby/object:Gem::Dependency
29
- name: coffee-rails
29
+ name: nio4r
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: 4.1.0
34
+ version: '1.2'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: 4.1.0
42
- - !ruby/object:Gem::Dependency
43
- name: faye-websocket
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: 0.10.0
49
- type: :runtime
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: 0.10.0
41
+ version: '1.2'
56
42
  - !ruby/object:Gem::Dependency
57
43
  name: websocket-driver
58
44
  requirement: !ruby/object:Gem::Requirement
@@ -67,76 +53,6 @@ dependencies:
67
53
  - - "~>"
68
54
  - !ruby/object:Gem::Version
69
55
  version: 0.6.1
70
- - !ruby/object:Gem::Dependency
71
- name: celluloid
72
- requirement: !ruby/object:Gem::Requirement
73
- requirements:
74
- - - "~>"
75
- - !ruby/object:Gem::Version
76
- version: 0.17.2
77
- type: :runtime
78
- prerelease: false
79
- version_requirements: !ruby/object:Gem::Requirement
80
- requirements:
81
- - - "~>"
82
- - !ruby/object:Gem::Version
83
- version: 0.17.2
84
- - !ruby/object:Gem::Dependency
85
- name: em-hiredis
86
- requirement: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - "~>"
89
- - !ruby/object:Gem::Version
90
- version: 0.3.0
91
- type: :runtime
92
- prerelease: false
93
- version_requirements: !ruby/object:Gem::Requirement
94
- requirements:
95
- - - "~>"
96
- - !ruby/object:Gem::Version
97
- version: 0.3.0
98
- - !ruby/object:Gem::Dependency
99
- name: redis
100
- requirement: !ruby/object:Gem::Requirement
101
- requirements:
102
- - - "~>"
103
- - !ruby/object:Gem::Version
104
- version: '3.0'
105
- type: :runtime
106
- prerelease: false
107
- version_requirements: !ruby/object:Gem::Requirement
108
- requirements:
109
- - - "~>"
110
- - !ruby/object:Gem::Version
111
- version: '3.0'
112
- - !ruby/object:Gem::Dependency
113
- name: puma
114
- requirement: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- version: '0'
119
- type: :development
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: mocha
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: '0'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- version: '0'
140
56
  description: Structure many real-time application concerns into channels over a single
141
57
  WebSocket connection.
142
58
  email:
@@ -160,16 +76,18 @@ files:
160
76
  - lib/action_cable/connection.rb
161
77
  - lib/action_cable/connection/authorization.rb
162
78
  - lib/action_cable/connection/base.rb
79
+ - lib/action_cable/connection/client_socket.rb
163
80
  - lib/action_cable/connection/identification.rb
164
81
  - lib/action_cable/connection/internal_channel.rb
165
82
  - lib/action_cable/connection/message_buffer.rb
83
+ - lib/action_cable/connection/stream.rb
84
+ - lib/action_cable/connection/stream_event_loop.rb
166
85
  - lib/action_cable/connection/subscriptions.rb
167
86
  - lib/action_cable/connection/tagged_logger_proxy.rb
168
87
  - lib/action_cable/connection/web_socket.rb
169
88
  - lib/action_cable/engine.rb
170
89
  - lib/action_cable/gem_version.rb
171
90
  - lib/action_cable/helpers/action_cable_helper.rb
172
- - lib/action_cable/process/logging.rb
173
91
  - lib/action_cable/remote_connections.rb
174
92
  - lib/action_cable/server.rb
175
93
  - lib/action_cable/server/base.rb
@@ -178,13 +96,16 @@ files:
178
96
  - lib/action_cable/server/connections.rb
179
97
  - lib/action_cable/server/worker.rb
180
98
  - lib/action_cable/server/worker/active_record_connection_management.rb
99
+ - lib/action_cable/subscription_adapter.rb
100
+ - lib/action_cable/subscription_adapter/async.rb
101
+ - lib/action_cable/subscription_adapter/base.rb
102
+ - lib/action_cable/subscription_adapter/evented_redis.rb
103
+ - lib/action_cable/subscription_adapter/inline.rb
104
+ - lib/action_cable/subscription_adapter/postgresql.rb
105
+ - lib/action_cable/subscription_adapter/redis.rb
106
+ - lib/action_cable/subscription_adapter/subscriber_map.rb
181
107
  - lib/action_cable/version.rb
182
- - lib/assets/javascripts/action_cable.coffee.erb
183
- - lib/assets/javascripts/action_cable/connection.coffee
184
- - lib/assets/javascripts/action_cable/connection_monitor.coffee
185
- - lib/assets/javascripts/action_cable/consumer.coffee
186
- - lib/assets/javascripts/action_cable/subscription.coffee
187
- - lib/assets/javascripts/action_cable/subscriptions.coffee
108
+ - lib/assets/compiled/action_cable.js
188
109
  - lib/rails/generators/channel/USAGE
189
110
  - lib/rails/generators/channel/channel_generator.rb
190
111
  - lib/rails/generators/channel/templates/assets/channel.coffee
@@ -209,8 +130,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
130
  version: 1.3.1
210
131
  requirements: []
211
132
  rubyforge_project:
212
- rubygems_version: 2.5.1
133
+ rubygems_version: 2.5.2
213
134
  signing_key:
214
135
  specification_version: 4
215
136
  summary: WebSocket framework for Rails.
216
137
  test_files: []
138
+ has_rdoc:
@@ -1,10 +0,0 @@
1
- require 'action_cable/server'
2
- require 'eventmachine'
3
- require 'celluloid'
4
-
5
- EM.error_handler do |e|
6
- puts "Error raised inside the event loop: #{e.message}"
7
- puts e.backtrace.join("\n")
8
- end
9
-
10
- Celluloid.logger = ActionCable.server.logger
@@ -1,23 +0,0 @@
1
- #= require_self
2
- #= require action_cable/consumer
3
-
4
- @ActionCable =
5
- INTERNAL: <%= ActionCable::INTERNAL.to_json %>
6
-
7
- createConsumer: (url = @getConfig("url")) ->
8
- new ActionCable.Consumer @createWebSocketURL(url)
9
-
10
- getConfig: (name) ->
11
- element = document.head.querySelector("meta[name='action-cable-#{name}']")
12
- element?.getAttribute("content")
13
-
14
- createWebSocketURL: (url) ->
15
- if url and not /^wss?:/i.test(url)
16
- a = document.createElement("a")
17
- a.href = url
18
- # Fix populating Location properties in IE. Otherwise, protocol will be blank.
19
- a.href = a.href
20
- a.protocol = a.protocol.replace("http", "ws")
21
- a.href
22
- else
23
- url
@@ -1,84 +0,0 @@
1
- # Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.
2
-
3
- {message_types} = ActionCable.INTERNAL
4
-
5
- class ActionCable.Connection
6
- @reopenDelay: 500
7
-
8
- constructor: (@consumer) ->
9
- @open()
10
-
11
- send: (data) ->
12
- if @isOpen()
13
- @webSocket.send(JSON.stringify(data))
14
- true
15
- else
16
- false
17
-
18
- open: =>
19
- if @webSocket and not @isState("closed")
20
- throw new Error("Existing connection must be closed before opening")
21
- else
22
- @webSocket = new WebSocket(@consumer.url)
23
- @installEventHandlers()
24
- true
25
-
26
- close: ->
27
- @webSocket?.close()
28
-
29
- reopen: ->
30
- if @isState("closed")
31
- @open()
32
- else
33
- try
34
- @close()
35
- finally
36
- setTimeout(@open, @constructor.reopenDelay)
37
-
38
- isOpen: ->
39
- @isState("open")
40
-
41
- # Private
42
-
43
- isState: (states...) ->
44
- @getState() in states
45
-
46
- getState: ->
47
- return state.toLowerCase() for state, value of WebSocket when value is @webSocket?.readyState
48
- null
49
-
50
- installEventHandlers: ->
51
- for eventName of @events
52
- handler = @events[eventName].bind(this)
53
- @webSocket["on#{eventName}"] = handler
54
- return
55
-
56
- events:
57
- message: (event) ->
58
- {identifier, message, type} = JSON.parse(event.data)
59
-
60
- switch type
61
- when message_types.confirmation
62
- @consumer.subscriptions.notify(identifier, "connected")
63
- when message_types.rejection
64
- @consumer.subscriptions.reject(identifier)
65
- else
66
- @consumer.subscriptions.notify(identifier, "received", message)
67
-
68
- open: ->
69
- @disconnected = false
70
- @consumer.subscriptions.reload()
71
-
72
- close: ->
73
- @disconnect()
74
-
75
- error: ->
76
- @disconnect()
77
-
78
- disconnect: ->
79
- return if @disconnected
80
- @disconnected = true
81
- @consumer.subscriptions.notifyAll("disconnected")
82
-
83
- toJSON: ->
84
- state: @getState()
@@ -1,84 +0,0 @@
1
- # Responsible for ensuring the cable connection is in good health by validating the heartbeat pings sent from the server, and attempting
2
- # revival reconnections if things go astray. Internal class, not intended for direct user manipulation.
3
- class ActionCable.ConnectionMonitor
4
- @pollInterval:
5
- min: 3
6
- max: 30
7
-
8
- @staleThreshold: 6 # Server::Connections::BEAT_INTERVAL * 2 (missed two pings)
9
-
10
- identifier: ActionCable.INTERNAL.identifiers.ping
11
-
12
- constructor: (@consumer) ->
13
- @consumer.subscriptions.add(this)
14
- @start()
15
-
16
- connected: ->
17
- @reset()
18
- @pingedAt = now()
19
- delete @disconnectedAt
20
-
21
- disconnected: ->
22
- @disconnectedAt = now()
23
-
24
- received: ->
25
- @pingedAt = now()
26
-
27
- reset: ->
28
- @reconnectAttempts = 0
29
-
30
- start: ->
31
- @reset()
32
- delete @stoppedAt
33
- @startedAt = now()
34
- @poll()
35
- document.addEventListener("visibilitychange", @visibilityDidChange)
36
-
37
- stop: ->
38
- @stoppedAt = now()
39
- document.removeEventListener("visibilitychange", @visibilityDidChange)
40
-
41
- poll: ->
42
- setTimeout =>
43
- unless @stoppedAt
44
- @reconnectIfStale()
45
- @poll()
46
- , @getInterval()
47
-
48
- getInterval: ->
49
- {min, max} = @constructor.pollInterval
50
- interval = 5 * Math.log(@reconnectAttempts + 1)
51
- clamp(interval, min, max) * 1000
52
-
53
- reconnectIfStale: ->
54
- if @connectionIsStale()
55
- @reconnectAttempts++
56
- unless @disconnectedRecently()
57
- @consumer.connection.reopen()
58
-
59
- connectionIsStale: ->
60
- secondsSince(@pingedAt ? @startedAt) > @constructor.staleThreshold
61
-
62
- disconnectedRecently: ->
63
- @disconnectedAt and secondsSince(@disconnectedAt) < @constructor.staleThreshold
64
-
65
- visibilityDidChange: =>
66
- if document.visibilityState is "visible"
67
- setTimeout =>
68
- if @connectionIsStale() or not @consumer.connection.isOpen()
69
- @consumer.connection.reopen()
70
- , 200
71
-
72
- toJSON: ->
73
- interval = @getInterval()
74
- connectionIsStale = @connectionIsStale()
75
- {@startedAt, @stoppedAt, @pingedAt, @reconnectAttempts, connectionIsStale, interval}
76
-
77
- now = ->
78
- new Date().getTime()
79
-
80
- secondsSince = (time) ->
81
- (now() - time) / 1000
82
-
83
- clamp = (number, min, max) ->
84
- Math.max(min, Math.min(max, number))
@@ -1,31 +0,0 @@
1
- #= require action_cable/connection
2
- #= require action_cable/connection_monitor
3
- #= require action_cable/subscriptions
4
- #= require action_cable/subscription
5
-
6
- # The ActionCable.Consumer establishes the connection to a server-side Ruby Connection object. Once established,
7
- # the ActionCable.ConnectionMonitor will ensure that its properly maintained through heartbeats and checking for stale updates.
8
- # The Consumer instance is also the gateway to establishing subscriptions to desired channels through the #createSubscription
9
- # method.
10
- #
11
- # The following example shows how this can be setup:
12
- #
13
- # @App = {}
14
- # App.cable = ActionCable.createConsumer "ws://example.com/accounts/1"
15
- # App.appearance = App.cable.subscriptions.create "AppearanceChannel"
16
- #
17
- # For more details on how you'd configure an actual channel subscription, see ActionCable.Subscription.
18
- class ActionCable.Consumer
19
- constructor: (@url) ->
20
- @subscriptions = new ActionCable.Subscriptions this
21
- @connection = new ActionCable.Connection this
22
- @connectionMonitor = new ActionCable.ConnectionMonitor this
23
-
24
- send: (data) ->
25
- @connection.send(data)
26
-
27
- inspect: ->
28
- JSON.stringify(this, null, 2)
29
-
30
- toJSON: ->
31
- {@url, @subscriptions, @connection, @connectionMonitor}