myxi 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/myxi.rb +5 -0
- data/lib/myxi/action.rb +8 -1
- data/lib/myxi/default_actions.rb +22 -2
- data/lib/myxi/environment.rb +21 -0
- data/lib/myxi/railtie.rb +8 -0
- data/lib/myxi/server.rb +24 -3
- data/lib/myxi/session.rb +25 -5
- data/lib/myxi/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f04936ddd50485e99372aa1248f99bf41fbc6c61
|
4
|
+
data.tar.gz: 16b9d860964f5f8c733697cc13001977949ca541
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0aabc52d678b70c8fc7d929bb00d9b876b5fc8a7c847cc9d7f8be0f3350a21579f7cb309cc88d1b25f9f57dc6f2effe74de9e59278ae97143a7932822ae265f8
|
7
|
+
data.tar.gz: 4e9b22ef5ba86dc807a8f8240a510c40ae2602fde0f47f9cc177e9a1857724b0114ab0fc2e21395d87c6595b483718dca8bd9a2e05b90924198f58f7ab63b5d7
|
data/lib/myxi.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
require 'myxi/exchange'
|
2
|
+
require 'myxi/railtie' if defined?(Rails)
|
3
|
+
|
1
4
|
module Myxi
|
2
5
|
class << self
|
3
6
|
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
4
9
|
#
|
5
10
|
# Return a bunny client instance which will be used by the web socket service.
|
6
11
|
# This can be overriden if you already have a connection RabbitMQ available
|
data/lib/myxi/action.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'myxi/environment'
|
2
|
+
|
1
3
|
module Myxi
|
2
4
|
class Action
|
3
5
|
|
@@ -13,7 +15,12 @@ module Myxi
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def execute(session, payload = {})
|
16
|
-
|
18
|
+
environment = Environment.new(session, payload)
|
19
|
+
environment.instance_exec(session, payload, &@block)
|
20
|
+
rescue Environment::Error => e
|
21
|
+
session.send('Error', :error => e.class.to_s.split('::').last)
|
22
|
+
rescue => e
|
23
|
+
session.send('InternalError', :error => e.class.to_s, :message => e.message)
|
17
24
|
end
|
18
25
|
|
19
26
|
end
|
data/lib/myxi/default_actions.rb
CHANGED
@@ -1,13 +1,33 @@
|
|
1
1
|
Myxi::Action.add(:Subscribe) do |session, payload|
|
2
|
-
|
2
|
+
if payload['routing_keys'].is_a?(Array)
|
3
|
+
for key in payload['routing_keys']
|
4
|
+
session.subscribe(payload['exchange'], key)
|
5
|
+
end
|
6
|
+
else
|
7
|
+
session.subscribe(payload['exchange'], payload['routing_key'])
|
8
|
+
end
|
3
9
|
end
|
4
10
|
|
5
11
|
Myxi::Action.add(:Unsubscribe) do |session, payload|
|
6
12
|
if payload['exchange'] && payload['routing_key']
|
7
|
-
|
13
|
+
if payload['routing_keys'].is_a?(Array)
|
14
|
+
for key in payload['routing_keys']
|
15
|
+
session.unsubscribe(payload['exchange'], key)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
session.unsubscribe(payload['exchange'], payload['routing_key'])
|
19
|
+
end
|
8
20
|
elsif payload['exchange'] && payload['routing_key'].nil?
|
9
21
|
session.unsubscribe_all_for_exchange(payload['exchange'])
|
10
22
|
else
|
11
23
|
session.unsubscribe_all
|
12
24
|
end
|
13
25
|
end
|
26
|
+
|
27
|
+
Myxi::Action.add(:ListSubscriptions) do |session, payload|
|
28
|
+
session.send "YourSubscriptions", :subscriptions => session.subscriptions
|
29
|
+
end
|
30
|
+
|
31
|
+
Myxi::Action.add(:Ping) do |session, payload|
|
32
|
+
session.send "Pong", :time => Time.now.to_i
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Myxi
|
2
|
+
class Environment
|
3
|
+
|
4
|
+
class Error < StandardError; end
|
5
|
+
class AuthRequired < Error; end
|
6
|
+
|
7
|
+
def initialize(session, payload = {})
|
8
|
+
@session, @payload = session, payload
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :session
|
12
|
+
attr_reader :payload
|
13
|
+
|
14
|
+
def auth_required!
|
15
|
+
if session.auth_object.nil?
|
16
|
+
raise AuthRequired, "Authentication is required for this action"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/myxi/railtie.rb
ADDED
data/lib/myxi/server.rb
CHANGED
@@ -19,14 +19,30 @@ module Myxi
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
def sessions
|
23
|
+
@sessions ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def monitor_sessions
|
27
|
+
unless options[:touch_interval] == 0
|
28
|
+
Thread.new do
|
29
|
+
loop do
|
30
|
+
sessions.each(&:touch)
|
31
|
+
sleep options[:touch_interval] || 60
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
22
37
|
def run
|
23
38
|
Myxi::Exchange.declare_all
|
24
39
|
port = (options[:port] || ENV['MYXI_PORT'] || ENV['PORT'] || 5005).to_i
|
25
40
|
puts "Running Myxi Web Socket Server on 0.0.0.0:#{port}"
|
41
|
+
monitor_sessions
|
26
42
|
EM.run do
|
27
43
|
EM::WebSocket.run(:host => options[:bind_address] || ENV['MYXI_BIND_ADDRESS'] || '0.0.0.0', :port => port) do |ws|
|
28
44
|
|
29
|
-
session = Session.new(ws)
|
45
|
+
sessions << session = Session.new(self, ws)
|
30
46
|
|
31
47
|
ws.onopen do |handshake|
|
32
48
|
case handshake.path
|
@@ -36,7 +52,10 @@ module Myxi
|
|
36
52
|
|
37
53
|
session.queue = Myxi.channel.queue("", :exclusive => true)
|
38
54
|
session.queue.subscribe do |delivery_info, properties, body|
|
39
|
-
|
55
|
+
if hash = JSON.parse(body) rescue nil
|
56
|
+
hash['mq'] = {'e' => delivery_info.exchange, 'rk' => delivery_info.routing_key}
|
57
|
+
ws.send(hash.to_json.force_encoding('UTF-8'))
|
58
|
+
end
|
40
59
|
end
|
41
60
|
else
|
42
61
|
log "[#{session.id}] Invalid path"
|
@@ -48,11 +67,13 @@ module Myxi
|
|
48
67
|
ws.onclose do
|
49
68
|
log "[#{session.id}] Disconnected"
|
50
69
|
session.queue.delete if session.queue
|
70
|
+
sessions.delete(session)
|
51
71
|
end
|
52
72
|
|
53
73
|
ws.onmessage do |msg|
|
54
74
|
if ws.state == :connected
|
55
|
-
|
75
|
+
json = JSON.parse(msg) rescue nil
|
76
|
+
if json.is_a?(Hash)
|
56
77
|
session.tag = json['tag'] || nil
|
57
78
|
payload = json['payload'] || {}
|
58
79
|
if action = Myxi::Action::ACTIONS[json['action'].to_sym]
|
data/lib/myxi/session.rb
CHANGED
@@ -4,12 +4,14 @@ require 'myxi/exchange'
|
|
4
4
|
module Myxi
|
5
5
|
class Session
|
6
6
|
|
7
|
-
def initialize(ws)
|
7
|
+
def initialize(server, ws)
|
8
|
+
@server = server
|
8
9
|
@ws = ws
|
9
10
|
@id = SecureRandom.hex(8)
|
10
11
|
end
|
11
12
|
|
12
13
|
attr_reader :id
|
14
|
+
attr_reader :server
|
13
15
|
attr_reader :ws
|
14
16
|
attr_accessor :queue
|
15
17
|
attr_accessor :auth_object
|
@@ -26,7 +28,7 @@ module Myxi
|
|
26
28
|
# Send an event back to the client on this session
|
27
29
|
#
|
28
30
|
def send(name, payload = {})
|
29
|
-
ws.send({:event => name, :tag => tag, :payload => payload}.to_json)
|
31
|
+
ws.send({:event => name, :tag => tag, :payload => payload}.to_json.force_encoding('UTF-8'))
|
30
32
|
end
|
31
33
|
|
32
34
|
#
|
@@ -38,7 +40,7 @@ module Myxi
|
|
38
40
|
queue.bind(exchange.exchange_name.to_s, :routing_key => routing_key.to_s)
|
39
41
|
subscriptions[exchange_name.to_s] ||= []
|
40
42
|
subscriptions[exchange_name.to_s] << routing_key.to_s
|
41
|
-
|
43
|
+
server.log "[#{id}] Subscribed to #{exchange_name} / #{routing_key}"
|
42
44
|
send('Subscribed', :exchange => exchange_name, :routing_key => routing_key)
|
43
45
|
else
|
44
46
|
send('Error', :error => 'SubscriptionDenied', :exchange => exchange_name, :routing_key => routing_key)
|
@@ -51,12 +53,13 @@ module Myxi
|
|
51
53
|
#
|
52
54
|
# Unsubscribe this session from the given exchange name and routing key
|
53
55
|
#
|
54
|
-
def unsubscribe(exchange_name, routing_key)
|
56
|
+
def unsubscribe(exchange_name, routing_key, auto = false)
|
55
57
|
queue.unbind(exchange_name.to_s, :routing_key => routing_key.to_s)
|
56
58
|
if subscriptions[exchange_name.to_s]
|
57
59
|
subscriptions[exchange_name.to_s].delete(routing_key.to_s)
|
58
60
|
end
|
59
|
-
|
61
|
+
server.log "[#{id}] Unsubscribed from #{exchange_name}/#{routing_key}"
|
62
|
+
send('Unsubscribed', :exchange_name => exchange_name, :routing_key => routing_key, :auto => auto)
|
60
63
|
end
|
61
64
|
|
62
65
|
#
|
@@ -79,5 +82,22 @@ module Myxi
|
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
85
|
+
#
|
86
|
+
# Called by the server every so often whenever this session is active. This
|
87
|
+
# should verify that subscriptions are still valid etc...
|
88
|
+
#
|
89
|
+
def touch
|
90
|
+
subscriptions.each do |exchange_name, routing_keys|
|
91
|
+
if exchange = Myxi::Exchange::EXCHANGES[exchange_name.to_sym]
|
92
|
+
routing_keys.each do |routing_key|
|
93
|
+
unless exchange.can_subscribe?(routing_key, self.auth_object)
|
94
|
+
puts "[#{id}] Session is not longer allowed to subscibe to #{exchange_name}/#{routing_key}"
|
95
|
+
unsubscribe(exchange_name, routing_key, true)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
82
102
|
end
|
83
103
|
end
|
data/lib/myxi/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: myxi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Cooke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|
@@ -60,7 +60,9 @@ files:
|
|
60
60
|
- lib/myxi.rb
|
61
61
|
- lib/myxi/action.rb
|
62
62
|
- lib/myxi/default_actions.rb
|
63
|
+
- lib/myxi/environment.rb
|
63
64
|
- lib/myxi/exchange.rb
|
65
|
+
- lib/myxi/railtie.rb
|
64
66
|
- lib/myxi/server.rb
|
65
67
|
- lib/myxi/session.rb
|
66
68
|
- lib/myxi/version.rb
|
@@ -89,3 +91,4 @@ signing_key:
|
|
89
91
|
specification_version: 4
|
90
92
|
summary: A RabbitMQ-based web socket server & framework
|
91
93
|
test_files: []
|
94
|
+
has_rdoc:
|