power_strip 0.1.2 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 18c31760b6c3e4d748e3ae3c241c84a10fd98370
4
- data.tar.gz: c5e036376ee22d757e3b3ce0faa9a6614dbdb3ba
3
+ metadata.gz: 0c9e3d8262f810ab4fb28ccf752acbfafcaa6628
4
+ data.tar.gz: fcfa3d47d3739d813a03ae51664bd6efa68be337
5
5
  SHA512:
6
- metadata.gz: efd68a3521ef9fad7fab697a061a323c6e1710d12ab5240bb3f1be25e1755fc4c4eba8fe84e0494a2765de32e4572ff4ca16333da9f00fa80adb6574437cd849
7
- data.tar.gz: c2f32e98035971efe15be863c4a1ca51cca7f05c9f602b559f8733d2668b91a18cbdb097f0448e07c01534533c7ac141de3067a1181e44001b5b6182ebcbd9d9
6
+ metadata.gz: 4f2e2aff4dbc161af1a06d9e1f26284e6202ccb238c4ac9e4870ef437a2b09cb69ac6a617a2e5945b0571de26e9e86c69ffad212c2c7fbdf72aaac2cd8d9ef2b
7
+ data.tar.gz: fff40297418a13a67dc4d0ecbe7fd2b8f30d7aa2a91306c04c6d570a45c08d3fe1a414b54f6846bf184e2e7504f206b8017e6adb21aaed0c03b6394c87c55306
data/lib/power_strip.rb CHANGED
@@ -30,12 +30,18 @@ module PowerStrip
30
30
  def on event_name, channel:, &block
31
31
  app.on event_name, channel: channel, &block
32
32
  end
33
+
34
+ class Channel
35
+ def on message, &block
36
+ PowerStrip.on(message, channel: name, &block)
37
+ end
38
+ end
33
39
  end
34
40
 
35
41
  begin
36
42
  require 'opal'
37
43
  Opal.append_path File.expand_path('../../opal', __FILE__)
38
- rescue
44
+ rescue LoadError
39
45
  require 'sprockets'
40
46
  Sprockets.append_path File.expand_path('../js', __FILE__)
41
47
  end
@@ -5,6 +5,7 @@ require 'json'
5
5
 
6
6
  require 'power_strip/channel_list'
7
7
  require 'power_strip/message'
8
+ require 'power_strip/connection'
8
9
 
9
10
  module PowerStrip
10
11
  class App
@@ -22,8 +23,10 @@ module PowerStrip
22
23
  handlers[event] = []
23
24
  end
24
25
  end
26
+ @connections = {}
25
27
  end
26
28
 
29
+ # omg I'm so sorry this method looks like this.
27
30
  def call env
28
31
  if Faye::WebSocket.websocket? env
29
32
  socket = Faye::WebSocket.new(env)
@@ -31,46 +34,50 @@ module PowerStrip
31
34
  subscriptions = Set.new
32
35
 
33
36
  socket.on :message do |event|
34
- message = Message.new(JSON.parse(event.data))
35
- channel_name = message.channel
36
- channel = channels[channel_name]
37
-
38
- case message.event
39
- when '@subscribe'
40
- channel << socket
41
- subscriptions << channel_name
42
-
43
- socket.send({
44
- event: :subscribed,
45
- channel: channel_name,
46
- }.to_json)
47
- when '@unsubscribe'
48
- channels[channel_name].delete socket
49
- if channels[channel_name].empty?
50
- channels.delete channel_name
51
- end
52
-
53
- subscriptions.delete channel_name
54
-
55
- socket.send({
56
- event: :unsubscribed,
57
- channel: channel_name,
58
- }.to_json)
59
- else
60
- @handlers[channel_name][message.event].each do |callback|
61
- begin
62
- callback[message, socket]
63
- rescue => e
64
- warn "[PowerStrip] #{e.inspect}"
37
+ begin
38
+ message = Message.new(JSON.parse(event.data))
39
+ channel_name = message.channel
40
+ channel = channels[channel_name]
41
+
42
+ case message.event
43
+ when '@subscribe'
44
+ channel << socket
45
+ subscriptions << channel
46
+
47
+ socket.send({
48
+ event: :subscribed,
49
+ channel: channel_name,
50
+ }.to_json)
51
+ when '@unsubscribe'
52
+ subscriptions.delete channel
53
+ channel.delete socket
54
+
55
+ socket.send({
56
+ event: :unsubscribed,
57
+ channel: channel_name,
58
+ }.to_json)
59
+ else
60
+ @handlers[channel_name][message.event].each do |callback|
61
+ begin
62
+ callback[message, @connections[socket]]
63
+ rescue => e
64
+ warn "[PowerStrip] #{e.inspect}"
65
+ end
65
66
  end
66
67
  end
68
+ rescue JSON::ParserError
69
+ # Ignore invalid JSON
67
70
  end
68
71
  end
69
72
 
73
+ socket.on :open do
74
+ @connections[socket] = Connection.new(socket)
75
+ end
76
+
70
77
  socket.on :close do
71
- subscriptions.each do |channel_name|
72
- channels[channel_name].delete socket
73
- end
78
+ # Remove this connection from all channels it was subscribed to.
79
+ subscriptions.each { |channel| channel.delete socket }
80
+ @connections.delete socket
74
81
  end
75
82
 
76
83
  socket.rack_response
@@ -6,8 +6,9 @@ module PowerStrip
6
6
  class Channel
7
7
  attr_reader :name, :sockets
8
8
 
9
- def initialize(name, redis:)
9
+ def initialize(name, channel_list: {}, redis:)
10
10
  @name = name
11
+ @channel_list = channel_list
11
12
  @redis = redis
12
13
  @sockets = Set.new
13
14
  end
@@ -18,6 +19,13 @@ module PowerStrip
18
19
 
19
20
  def delete socket
20
21
  @sockets.delete socket
22
+
23
+ # Tell the channel list to GC this channel
24
+ @channel_list.delete @name if empty?
25
+ end
26
+
27
+ def empty?
28
+ @sockets.empty?
21
29
  end
22
30
 
23
31
  def send event, message
@@ -5,7 +5,11 @@ module PowerStrip
5
5
  def initialize(redis:)
6
6
  @redis = redis
7
7
  @channels = Hash.new do |hash, channel|
8
- hash[channel.to_s] = Channel.new(channel, redis: redis)
8
+ hash[channel.to_s] = Channel.new(
9
+ channel,
10
+ channel_list: self,
11
+ redis: redis,
12
+ )
9
13
  end
10
14
  end
11
15
 
@@ -20,5 +24,9 @@ module PowerStrip
20
24
  def delete channel_name
21
25
  @channels.delete channel_name.to_s
22
26
  end
27
+
28
+ def has_channel? channel_name
29
+ @channels.key? channel_name.to_s
30
+ end
23
31
  end
24
32
  end
@@ -0,0 +1,22 @@
1
+ module PowerStrip
2
+ class Connection
3
+ attr_reader :metadata
4
+
5
+ def initialize socket
6
+ @socket = socket
7
+ @metadata = {}
8
+ end
9
+
10
+ def [] attribute
11
+ @metadata[attribute]
12
+ end
13
+
14
+ def []= attribute, value
15
+ @metadata[attribute] = value
16
+ end
17
+
18
+ def method_missing *args, &block
19
+ @socket.public_send *args, &block
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module PowerStrip
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
data/opal/power_strip.rb CHANGED
@@ -9,18 +9,36 @@ module PowerStrip
9
9
  @url = url
10
10
  @socket = Bowser.websocket(url)
11
11
  @socket.autoreconnect!
12
- @subscriptions = []
12
+ @subscriptions = {}
13
13
 
14
- @socket.on(:open) { @subscriptions.each(&:subscribe) }
14
+ @socket.on :open do
15
+ @subscriptions.each { |name, channel| channel.subscribe }
16
+ end
17
+ @socket.on :message do |event|
18
+ message = Message.new(event.data)
19
+ channel = @subscriptions[message.channel]
20
+
21
+ if channel
22
+ channel.receive_message message
23
+ end
24
+ end
15
25
  end
16
26
 
17
27
  def subscribe channel_name
18
- channel = Channel.new(channel_name, @socket)
19
- @subscriptions << channel
28
+ channel = Channel.new(channel_name, self)
20
29
 
21
- if @socket.connected?
22
- channel.subscribe
23
- end
30
+ @subscriptions[channel_name] = channel
31
+ channel.subscribe
32
+
33
+ channel
34
+ end
35
+
36
+ def unsubscribe channel_name
37
+ channel = @subscriptions[channel_name]
38
+ return if channel.nil?
39
+
40
+ @subscriptions.delete channel
41
+ channel.unsubscribe
24
42
 
25
43
  channel
26
44
  end
@@ -38,39 +56,18 @@ module PowerStrip
38
56
 
39
57
  @socket.on native_event, &block
40
58
  end
41
- end
42
-
43
- Channel = Struct.new(:name, :socket) do
44
- def on event_name, &block
45
- socket.on :message do |event|
46
- message = Message.new(event.data)
47
-
48
- if message.channel == name && message.event == event_name
49
- block.call message
50
- end
51
- end
52
- end
53
-
54
- def subscribe
55
- socket.send_message(
56
- event: :@subscribe,
57
- channel: name,
58
- )
59
- end
60
59
 
61
- def method_missing event, message
60
+ def send_message channel=nil, event=nil, data=nil
62
61
  promise = Promise.new
63
62
 
64
- if socket.connected?
65
- socket.send_message({
66
- channel: name,
67
- event: event,
68
- data: message,
69
- }.select { |k,v| v })
63
+ if @socket.connected?
64
+ @socket.send_message({ channel: channel, event: event, data: data }
65
+ .select { |k,v| v })
70
66
  promise.resolve true
71
67
  else
72
68
  Bowser.window.delay 1 do
73
- send(event, message).then { promise.resolve true }
69
+ send_message(channel, event, data)
70
+ .then { promise.resolve true }
74
71
  end
75
72
  end
76
73
 
@@ -80,6 +77,42 @@ module PowerStrip
80
77
  end
81
78
  end
82
79
 
80
+ class Channel
81
+ attr_reader :name, :client
82
+
83
+ def initialize name, client
84
+ @name = name
85
+ @client = client
86
+ @handlers = Hash.new { |h, k| h[k] = [] }
87
+ end
88
+
89
+ def on event_name, handler=nil, &block
90
+ unless handler || block
91
+ raise ArgumentError, 'PowerStrip::Channel#on requires an event handler'
92
+ end
93
+
94
+ @handlers[event_name] << (handler || block)
95
+ end
96
+
97
+ def receive_message message
98
+ @handlers[message.event].each do |handler|
99
+ handler.call message
100
+ end
101
+ end
102
+
103
+ def subscribe
104
+ send :@subscribe, nil
105
+ end
106
+
107
+ def unsubscribe
108
+ send :@unsubscribe, nil
109
+ end
110
+
111
+ def send event, message=nil
112
+ client.send_message(name, event, message)
113
+ end
114
+ end
115
+
83
116
  class Message
84
117
  attr_reader :channel, :event, :data
85
118
 
data/power_strip.gemspec CHANGED
@@ -18,6 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_runtime_dependency "faye-websocket", "~> 0.10.4"
21
+ spec.add_runtime_dependency "grand_central"
22
+ spec.add_runtime_dependency "redis"
23
+ spec.add_runtime_dependency "sprockets", "~> 3.6.0"
21
24
 
22
25
  spec.add_development_dependency "bundler", "~> 1.12"
23
26
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: power_strip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Gaskins
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-15 00:00:00.000000000 Z
11
+ date: 2017-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -24,6 +24,48 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.10.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: grand_central
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sprockets
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.6.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.6.0
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: bundler
29
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +128,7 @@ files:
86
128
  - lib/power_strip/app.rb
87
129
  - lib/power_strip/channel.rb
88
130
  - lib/power_strip/channel_list.rb
131
+ - lib/power_strip/connection.rb
89
132
  - lib/power_strip/message.rb
90
133
  - lib/power_strip/version.rb
91
134
  - opal/power_strip.rb
@@ -109,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
152
  version: '0'
110
153
  requirements: []
111
154
  rubyforge_project:
112
- rubygems_version: 2.5.1
155
+ rubygems_version: 2.6.8
113
156
  signing_key:
114
157
  specification_version: 4
115
158
  summary: Push data from server to client with Ruby