power_strip 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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