alondra 0.0.3 → 0.0.4
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.
- data/Gemfile.lock +71 -75
- data/alondra.gemspec +2 -4
- data/app/assets/javascripts/alondra-client.js.coffee.erb +30 -26
- data/lib/alondra.rb +25 -13
- data/lib/alondra/command.rb +6 -4
- data/lib/alondra/connection.rb +1 -1
- data/lib/alondra/event.rb +21 -14
- data/lib/alondra/event_listener.rb +3 -3
- data/lib/alondra/log.rb +43 -0
- data/lib/alondra/message_queue.rb +6 -6
- data/lib/alondra/message_queue_client.rb +2 -2
- data/lib/alondra/push_controller.rb +8 -7
- data/lib/alondra/pushing.rb +6 -1
- data/lib/alondra/server.rb +9 -9
- data/lib/alondra/session_parser.rb +3 -3
- data/lib/generators/alondra/templates/alondra +8 -11
- data/test/dummy/app/views/chats/show.html.erb +1 -1
- data/test/integration/push_changes_test.rb +1 -1
- data/test/integration/push_messages_test.rb +2 -0
- data/test/models/channel_test.rb +1 -1
- metadata +35 -30
data/Gemfile.lock
CHANGED
|
@@ -1,138 +1,134 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
alondra (0.0.
|
|
4
|
+
alondra (0.0.4)
|
|
5
5
|
daemons
|
|
6
6
|
em-websocket
|
|
7
|
-
em-zeromq (= 0.2.
|
|
8
|
-
eventmachine (>= 1.0.0.beta.3)
|
|
9
|
-
ffi-rzmq (= 0.8.0)
|
|
7
|
+
em-zeromq (= 0.2.2)
|
|
10
8
|
rails (>= 3.1.0)
|
|
11
9
|
uuidtools
|
|
12
10
|
|
|
13
11
|
GEM
|
|
14
12
|
remote: http://rubygems.org/
|
|
15
13
|
specs:
|
|
16
|
-
actionmailer (3.
|
|
17
|
-
actionpack (= 3.
|
|
18
|
-
mail (~> 2.
|
|
19
|
-
actionpack (3.
|
|
20
|
-
activemodel (= 3.
|
|
21
|
-
activesupport (= 3.
|
|
14
|
+
actionmailer (3.2.0)
|
|
15
|
+
actionpack (= 3.2.0)
|
|
16
|
+
mail (~> 2.4.0)
|
|
17
|
+
actionpack (3.2.0)
|
|
18
|
+
activemodel (= 3.2.0)
|
|
19
|
+
activesupport (= 3.2.0)
|
|
22
20
|
builder (~> 3.0.0)
|
|
23
21
|
erubis (~> 2.7.0)
|
|
24
|
-
|
|
25
|
-
rack (~> 1.
|
|
22
|
+
journey (~> 1.0.0)
|
|
23
|
+
rack (~> 1.4.0)
|
|
26
24
|
rack-cache (~> 1.1)
|
|
27
|
-
rack-mount (~> 0.8.2)
|
|
28
25
|
rack-test (~> 0.6.1)
|
|
29
|
-
sprockets (~> 2.
|
|
30
|
-
activemodel (3.
|
|
31
|
-
activesupport (= 3.
|
|
26
|
+
sprockets (~> 2.1.2)
|
|
27
|
+
activemodel (3.2.0)
|
|
28
|
+
activesupport (= 3.2.0)
|
|
32
29
|
builder (~> 3.0.0)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
arel (~> 2.2.1)
|
|
30
|
+
activerecord (3.2.0)
|
|
31
|
+
activemodel (= 3.2.0)
|
|
32
|
+
activesupport (= 3.2.0)
|
|
33
|
+
arel (~> 3.0.0)
|
|
38
34
|
tzinfo (~> 0.3.29)
|
|
39
|
-
activeresource (3.
|
|
40
|
-
activemodel (= 3.
|
|
41
|
-
activesupport (= 3.
|
|
42
|
-
activesupport (3.
|
|
35
|
+
activeresource (3.2.0)
|
|
36
|
+
activemodel (= 3.2.0)
|
|
37
|
+
activesupport (= 3.2.0)
|
|
38
|
+
activesupport (3.2.0)
|
|
39
|
+
i18n (~> 0.6)
|
|
43
40
|
multi_json (~> 1.0)
|
|
44
41
|
addressable (2.2.6)
|
|
45
|
-
arel (
|
|
42
|
+
arel (3.0.2)
|
|
46
43
|
builder (3.0.0)
|
|
47
|
-
capybara (1.1.
|
|
44
|
+
capybara (1.1.2)
|
|
48
45
|
mime-types (>= 1.16)
|
|
49
46
|
nokogiri (>= 1.3.3)
|
|
50
47
|
rack (>= 1.0.0)
|
|
51
48
|
rack-test (>= 0.5.4)
|
|
52
49
|
selenium-webdriver (~> 2.0)
|
|
53
50
|
xpath (~> 0.1.4)
|
|
54
|
-
capybara-webkit (0.
|
|
51
|
+
capybara-webkit (0.8.0)
|
|
55
52
|
capybara (>= 1.0.0, < 1.2)
|
|
56
|
-
|
|
53
|
+
json
|
|
54
|
+
childprocess (0.3.0)
|
|
57
55
|
ffi (~> 1.0.6)
|
|
58
56
|
coffee-script (2.2.0)
|
|
59
57
|
coffee-script-source
|
|
60
58
|
execjs
|
|
61
|
-
coffee-script-source (1.
|
|
62
|
-
daemons (1.1.
|
|
63
|
-
em-websocket (0.3.
|
|
59
|
+
coffee-script-source (1.2.0)
|
|
60
|
+
daemons (1.1.8)
|
|
61
|
+
em-websocket (0.3.6)
|
|
64
62
|
addressable (>= 2.1.1)
|
|
65
63
|
eventmachine (>= 0.12.9)
|
|
66
|
-
em-zeromq (0.2.
|
|
67
|
-
eventmachine (>= 1.0.0.beta.
|
|
68
|
-
ffi
|
|
64
|
+
em-zeromq (0.2.2)
|
|
65
|
+
eventmachine (>= 1.0.0.beta.4)
|
|
66
|
+
ffi (>= 1.0.0)
|
|
67
|
+
ffi-rzmq (~> 0.9.0)
|
|
69
68
|
erubis (2.7.0)
|
|
70
69
|
eventmachine (1.0.0.beta.4)
|
|
71
|
-
execjs (1.
|
|
70
|
+
execjs (1.3.0)
|
|
72
71
|
multi_json (~> 1.0)
|
|
73
|
-
factory_girl (2.
|
|
72
|
+
factory_girl (2.5.0)
|
|
74
73
|
activesupport
|
|
75
|
-
ffi (1.0.
|
|
76
|
-
ffi-rzmq (0.
|
|
74
|
+
ffi (1.0.11)
|
|
75
|
+
ffi-rzmq (0.9.3)
|
|
76
|
+
ffi
|
|
77
77
|
hike (1.2.1)
|
|
78
78
|
i18n (0.6.0)
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
journey (1.0.0)
|
|
80
|
+
jquery-rails (2.0.0)
|
|
81
|
+
railties (>= 3.2.0.beta, < 5.0)
|
|
81
82
|
thor (~> 0.14)
|
|
82
|
-
json (1.6.
|
|
83
|
-
json_pure (1.6.1)
|
|
83
|
+
json (1.6.5)
|
|
84
84
|
launchy (2.0.5)
|
|
85
85
|
addressable (~> 2.2.6)
|
|
86
|
-
mail (2.
|
|
86
|
+
mail (2.4.4)
|
|
87
87
|
i18n (>= 0.4.0)
|
|
88
88
|
mime-types (~> 1.16)
|
|
89
89
|
treetop (~> 1.4.8)
|
|
90
90
|
mime-types (1.17.2)
|
|
91
|
-
multi_json (1.0.
|
|
92
|
-
mysql2 (0.3.
|
|
91
|
+
multi_json (1.0.4)
|
|
92
|
+
mysql2 (0.3.11)
|
|
93
93
|
nokogiri (1.5.0)
|
|
94
94
|
polyglot (0.3.3)
|
|
95
|
-
rack (1.
|
|
95
|
+
rack (1.4.1)
|
|
96
96
|
rack-cache (1.1)
|
|
97
97
|
rack (>= 0.4)
|
|
98
|
-
rack-mount (0.8.3)
|
|
99
|
-
rack (>= 1.0.0)
|
|
100
98
|
rack-ssl (1.3.2)
|
|
101
99
|
rack
|
|
102
100
|
rack-test (0.6.1)
|
|
103
101
|
rack (>= 1.0)
|
|
104
|
-
rails (3.
|
|
105
|
-
actionmailer (= 3.
|
|
106
|
-
actionpack (= 3.
|
|
107
|
-
activerecord (= 3.
|
|
108
|
-
activeresource (= 3.
|
|
109
|
-
activesupport (= 3.
|
|
102
|
+
rails (3.2.0)
|
|
103
|
+
actionmailer (= 3.2.0)
|
|
104
|
+
actionpack (= 3.2.0)
|
|
105
|
+
activerecord (= 3.2.0)
|
|
106
|
+
activeresource (= 3.2.0)
|
|
107
|
+
activesupport (= 3.2.0)
|
|
110
108
|
bundler (~> 1.0)
|
|
111
|
-
railties (= 3.
|
|
112
|
-
railties (3.
|
|
113
|
-
actionpack (= 3.
|
|
114
|
-
activesupport (= 3.
|
|
109
|
+
railties (= 3.2.0)
|
|
110
|
+
railties (3.2.0)
|
|
111
|
+
actionpack (= 3.2.0)
|
|
112
|
+
activesupport (= 3.2.0)
|
|
115
113
|
rack-ssl (~> 1.3.2)
|
|
116
114
|
rake (>= 0.8.7)
|
|
117
115
|
rdoc (~> 3.4)
|
|
118
116
|
thor (~> 0.14.6)
|
|
119
117
|
rake (0.9.2.2)
|
|
120
|
-
rdoc (3.
|
|
118
|
+
rdoc (3.12)
|
|
121
119
|
json (~> 1.4)
|
|
122
|
-
rubyzip (0.9.
|
|
123
|
-
sass (3.1.
|
|
124
|
-
sass-rails (3.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
ffi (= 1.0.9)
|
|
133
|
-
json_pure
|
|
120
|
+
rubyzip (0.9.5)
|
|
121
|
+
sass (3.1.12)
|
|
122
|
+
sass-rails (3.2.3)
|
|
123
|
+
railties (~> 3.2.0.beta)
|
|
124
|
+
sass (>= 3.1.10)
|
|
125
|
+
tilt (~> 1.3)
|
|
126
|
+
selenium-webdriver (2.17.0)
|
|
127
|
+
childprocess (>= 0.2.5)
|
|
128
|
+
ffi (~> 1.0.9)
|
|
129
|
+
multi_json (~> 1.0.4)
|
|
134
130
|
rubyzip
|
|
135
|
-
sprockets (2.
|
|
131
|
+
sprockets (2.1.2)
|
|
136
132
|
hike (~> 1.2)
|
|
137
133
|
rack (~> 1.0)
|
|
138
134
|
tilt (~> 1.1, != 1.3.0)
|
|
@@ -141,8 +137,8 @@ GEM
|
|
|
141
137
|
treetop (1.4.10)
|
|
142
138
|
polyglot
|
|
143
139
|
polyglot (>= 0.3.1)
|
|
144
|
-
tzinfo (0.3.
|
|
145
|
-
uglifier (1.
|
|
140
|
+
tzinfo (0.3.32)
|
|
141
|
+
uglifier (1.2.2)
|
|
146
142
|
execjs (>= 0.3.0)
|
|
147
143
|
multi_json (>= 1.0.2)
|
|
148
144
|
uuidtools (2.1.2)
|
data/alondra.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ Gem::Specification.new do |s|
|
|
|
4
4
|
s.name = "alondra"
|
|
5
5
|
s.summary = "Add real time capabilities to your rails app"
|
|
6
6
|
s.description = "Add real time capabilities to your rails app"
|
|
7
|
-
s.version = "0.0.
|
|
7
|
+
s.version = "0.0.4"
|
|
8
8
|
s.authors = ['Alberto F. Capel', 'Ryan LeCompte']
|
|
9
9
|
|
|
10
10
|
s.files = `git ls-files`.split("\n")
|
|
@@ -16,8 +16,6 @@ Gem::Specification.new do |s|
|
|
|
16
16
|
s.add_dependency('daemons')
|
|
17
17
|
s.add_dependency('uuidtools')
|
|
18
18
|
s.add_dependency('rails', '>= 3.1.0')
|
|
19
|
-
s.add_dependency('eventmachine', '>= 1.0.0.beta.3')
|
|
20
19
|
s.add_dependency('em-websocket')
|
|
21
|
-
s.add_dependency('
|
|
22
|
-
s.add_dependency('em-zeromq', '0.2.1')
|
|
20
|
+
s.add_dependency('em-zeromq', '0.2.2')
|
|
23
21
|
end
|
|
@@ -7,57 +7,61 @@
|
|
|
7
7
|
window.WEB_SOCKET_SWF_LOCATION = "<%= asset_path 'WebSocketMain.swf' %>"
|
|
8
8
|
|
|
9
9
|
class @AlondraClient
|
|
10
|
-
constructor: (
|
|
11
|
-
|
|
12
|
-
@
|
|
13
|
-
|
|
14
|
-
@url = "ws://#{
|
|
15
|
-
|
|
10
|
+
constructor: (@server, @channels=[], @token = null, @retry = 10000) ->
|
|
11
|
+
|
|
12
|
+
@channels = [@channels] unless @channels instanceof Array
|
|
13
|
+
|
|
14
|
+
@url = "ws://#{@server}"
|
|
16
15
|
@url += "?token=#{@token}" if @token
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
@connect()
|
|
19
18
|
|
|
20
|
-
subscribe: (channel)
|
|
19
|
+
subscribe: (channel) =>
|
|
20
|
+
if @socket.readyState == 0 # Socket is connecting
|
|
21
|
+
@channels.push(channel) # Schedule for later subscription
|
|
22
|
+
return
|
|
23
|
+
|
|
21
24
|
subscription =
|
|
22
25
|
command: 'subscribe'
|
|
23
26
|
channel: channel
|
|
24
27
|
|
|
25
28
|
@socket.send $.toJSON(subscription)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
@
|
|
30
|
+
|
|
31
|
+
connected: () =>
|
|
32
|
+
if @reconnectInterval
|
|
33
|
+
clearInterval(@reconnectInterval)
|
|
34
|
+
@reconnectInterval = null
|
|
35
|
+
|
|
36
|
+
@subscribe(channel) for channel in @channels
|
|
37
|
+
|
|
38
|
+
connect: =>
|
|
39
|
+
@socket = new WebSocket(@url)
|
|
40
|
+
|
|
41
|
+
@socket.onopen = @connected
|
|
39
42
|
|
|
40
43
|
@socket.onclose = () =>
|
|
41
44
|
this.reconnect()
|
|
42
45
|
|
|
43
|
-
|
|
44
46
|
@socket.onmessage = (message) =>
|
|
45
47
|
msg = $.parseJSON(message.data)
|
|
46
48
|
if msg.event
|
|
47
|
-
|
|
49
|
+
@process(msg)
|
|
48
50
|
else
|
|
49
|
-
|
|
51
|
+
@execute(msg)
|
|
50
52
|
|
|
51
53
|
|
|
52
54
|
@socket.onerror = (error) =>
|
|
53
|
-
|
|
55
|
+
@reconnect()
|
|
56
|
+
|
|
57
|
+
@
|
|
54
58
|
|
|
55
59
|
process: (serverEvent) ->
|
|
56
60
|
eventName = serverEvent.event
|
|
57
61
|
resourceType = serverEvent.resource_type
|
|
58
62
|
resource = serverEvent.resource
|
|
59
63
|
|
|
60
|
-
$(
|
|
64
|
+
$(@).trigger("#{eventName}.#{resourceType}", resource)
|
|
61
65
|
|
|
62
66
|
execute: (message) ->
|
|
63
67
|
eval(message.message)
|
data/lib/alondra.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require_relative 'alondra/log'
|
|
1
2
|
require_relative 'alondra/message'
|
|
2
3
|
require_relative 'alondra/event'
|
|
3
4
|
require_relative 'alondra/connection'
|
|
@@ -27,6 +28,13 @@ module Alondra
|
|
|
27
28
|
config.port = Rails.env == 'test' ? 12346 : 12345
|
|
28
29
|
config.host = 'localhost'
|
|
29
30
|
config.queue_socket = 'ipc:///tmp/alondra.ipc'
|
|
31
|
+
|
|
32
|
+
initializer "configure EM thread pool" do
|
|
33
|
+
# If we have more threads than db connections we will exhaust the conn pool
|
|
34
|
+
threadpool_size = ActiveRecord::Base.connection_pool.instance_variable_get :@size
|
|
35
|
+
threadpool_size -= 2 if threadpool_size > 2
|
|
36
|
+
EM.threadpool_size = threadpool_size
|
|
37
|
+
end
|
|
30
38
|
|
|
31
39
|
initializer "enable sessions for flash websockets" do
|
|
32
40
|
Rails.application.config.session_store :cookie_store, httponly: false
|
|
@@ -35,9 +43,13 @@ module Alondra
|
|
|
35
43
|
initializer "load listeners" do
|
|
36
44
|
listeners_dir = File.join(Rails.root, 'app', 'listeners')
|
|
37
45
|
|
|
38
|
-
|
|
46
|
+
Log.info "Loading event listeners in #{listeners_dir}"
|
|
39
47
|
Dir[File.join(listeners_dir, '*.rb')].each { |file| require_dependency file }
|
|
40
48
|
end
|
|
49
|
+
|
|
50
|
+
config.after_initialize do
|
|
51
|
+
PushController.send :include, Rails.application.routes.url_helpers
|
|
52
|
+
end
|
|
41
53
|
|
|
42
54
|
def self.start_server_in_new_thread!
|
|
43
55
|
Thread.new do
|
|
@@ -46,29 +58,29 @@ module Alondra
|
|
|
46
58
|
end
|
|
47
59
|
|
|
48
60
|
def self.start_server!
|
|
61
|
+
|
|
62
|
+
start_server_proc = Proc.new do
|
|
63
|
+
MessageQueue.instance.start_listening
|
|
64
|
+
Server.run
|
|
65
|
+
die_gracefully_on_signal
|
|
66
|
+
end
|
|
67
|
+
|
|
49
68
|
if EM.reactor_running?
|
|
50
|
-
EM.schedule
|
|
51
|
-
MessageQueue.instance.start_listening
|
|
52
|
-
Server.run
|
|
53
|
-
end
|
|
69
|
+
EM.schedule(start_server_proc)
|
|
54
70
|
else
|
|
55
|
-
|
|
56
|
-
EM.run
|
|
57
|
-
MessageQueue.instance.start_listening
|
|
58
|
-
Server.run
|
|
59
|
-
end
|
|
60
|
-
die_gracefully_on_signal
|
|
71
|
+
Log.info "starting EM reactor"
|
|
72
|
+
EM.run(start_server_proc)
|
|
61
73
|
end
|
|
62
74
|
end
|
|
63
75
|
|
|
64
76
|
def self.die_gracefully_on_signal
|
|
65
77
|
Signal.trap("INT") do
|
|
66
|
-
|
|
78
|
+
Log.warn "INT signal trapped. Shutting down EM reactor"
|
|
67
79
|
EM.stop
|
|
68
80
|
end
|
|
69
81
|
|
|
70
82
|
Signal.trap("TERM") do
|
|
71
|
-
|
|
83
|
+
Log.warn "TERM signal trapped. Shutting down EM reactor"
|
|
72
84
|
EM.stop
|
|
73
85
|
end
|
|
74
86
|
end
|
data/lib/alondra/command.rb
CHANGED
|
@@ -27,10 +27,12 @@ module Alondra
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def fire_event(event_type)
|
|
30
|
-
event_hash = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
event_hash = {
|
|
31
|
+
:event => event_type,
|
|
32
|
+
:resource => @connection.session,
|
|
33
|
+
:resource_type => @connection.session.class.name,
|
|
34
|
+
:channel => @channel_name
|
|
35
|
+
}
|
|
34
36
|
|
|
35
37
|
Event.new(event_hash, nil, connection).fire!
|
|
36
38
|
end
|
data/lib/alondra/connection.rb
CHANGED
data/lib/alondra/event.rb
CHANGED
|
@@ -11,20 +11,8 @@ module Alondra
|
|
|
11
11
|
@type = event_hash[:event].to_sym
|
|
12
12
|
@json_encoded = from_json
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
else
|
|
17
|
-
@resource = event_hash[:resource]
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
@resource_type = event_hash[:resource_type] || resource.class.name
|
|
21
|
-
|
|
22
|
-
if event_hash[:channel].present?
|
|
23
|
-
@channel_name = event_hash[:channel]
|
|
24
|
-
else
|
|
25
|
-
channel_type = type == :updated ? :member : :collection
|
|
26
|
-
Channel.default_name_for(resource, channel_type)
|
|
27
|
-
end
|
|
14
|
+
set_resource_from(event_hash)
|
|
15
|
+
set_channel_from(event_hash)
|
|
28
16
|
end
|
|
29
17
|
|
|
30
18
|
def channel
|
|
@@ -70,5 +58,24 @@ module Alondra
|
|
|
70
58
|
resource.assign_attributes(filtered_attributes, :without_protection => true)
|
|
71
59
|
resource
|
|
72
60
|
end
|
|
61
|
+
|
|
62
|
+
def set_resource_from(event_hash)
|
|
63
|
+
if Hash === event_hash[:resource]
|
|
64
|
+
@resource = fetch(event_hash[:resource_type], event_hash[:resource])
|
|
65
|
+
else
|
|
66
|
+
@resource = event_hash[:resource]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
@resource_type = event_hash[:resource_type] || resource.class.name
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def set_channel_from(event_hash)
|
|
73
|
+
if event_hash[:channel].present?
|
|
74
|
+
@channel_name = event_hash[:channel]
|
|
75
|
+
else
|
|
76
|
+
channel_type = type == :updated ? :member : :collection
|
|
77
|
+
Channel.default_name_for(resource, channel_type)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
73
80
|
end
|
|
74
81
|
end
|
|
@@ -64,9 +64,9 @@ module Alondra
|
|
|
64
64
|
begin
|
|
65
65
|
new_instance.instance_exec(event, &callback.proc)
|
|
66
66
|
rescue Exception => ex
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
Log.error 'Error while processing event listener callback'
|
|
68
|
+
Log.error ex.message
|
|
69
|
+
Log.error ex.backtrace.join("\n")
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
end
|
data/lib/alondra/log.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Alondra
|
|
2
|
+
module Log
|
|
3
|
+
extend self
|
|
4
|
+
|
|
5
|
+
NUMBER_TO_NAME_MAP = {0=>'DEBUG', 1=>'INFO', 2=>'WARN', 3=>'ERROR', 4=>'FATAL', 5=>'UNKNOWN'}
|
|
6
|
+
NUMBER_TO_COLOR_MAP = {0=>'0;37', 1=>'32', 2=>'33', 3=>'31', 4=>'31', 5=>'37'}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def debug(message)
|
|
10
|
+
add(ActiveSupport::BufferedLogger::Severity::DEBUG, message)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def info(message)
|
|
14
|
+
add(ActiveSupport::BufferedLogger::Severity::INFO, message)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def warn(message)
|
|
18
|
+
add(ActiveSupport::BufferedLogger::Severity::WARN, message)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def error(message)
|
|
22
|
+
add(ActiveSupport::BufferedLogger::Severity::ERROR, message)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def fatal(message)
|
|
26
|
+
add(ActiveSupport::BufferedLogger::Severity::FATAL, message)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def unkwon(message)
|
|
30
|
+
add(ActiveSupport::BufferedLogger::Severity::UNKNOWN, message)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def add(severity, message = nil, progname = 'ALONDRA')
|
|
36
|
+
sevstring = NUMBER_TO_NAME_MAP[severity]
|
|
37
|
+
color = NUMBER_TO_COLOR_MAP[severity]
|
|
38
|
+
|
|
39
|
+
message = "\n\033[35m#{progname}:\033[0m[\033[#{color}m#{sevstring}\033[0m] #{message.strip}\033\n"
|
|
40
|
+
Rails.logger.add(severity, message, progname)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -7,10 +7,10 @@ module Alondra
|
|
|
7
7
|
include Singleton
|
|
8
8
|
|
|
9
9
|
def start_listening
|
|
10
|
-
|
|
10
|
+
Log.info "Starting message queue"
|
|
11
11
|
|
|
12
12
|
if @connection
|
|
13
|
-
|
|
13
|
+
Log.warn 'Push connection to message queue started twice'
|
|
14
14
|
reset!
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -23,9 +23,9 @@ module Alondra
|
|
|
23
23
|
begin
|
|
24
24
|
parse received.copy_out_string
|
|
25
25
|
rescue Exception => ex
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
Log.error "Error raised while processing message"
|
|
27
|
+
Log.error "#{ex.class}: #{ex.message}"
|
|
28
|
+
Log.error ex.backtrace.join("\n") if ex.respond_to? :backtrace
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
end
|
|
@@ -40,7 +40,7 @@ module Alondra
|
|
|
40
40
|
message = Message.new(received_hash[:message], received_hash[:channel_names])
|
|
41
41
|
message.send_to_channels
|
|
42
42
|
else
|
|
43
|
-
|
|
43
|
+
Log.warn "Unrecognized message type #{received_string}"
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -32,7 +32,7 @@ module Alondra
|
|
|
32
32
|
begin
|
|
33
33
|
push_socket.send_msg(message.to_json)
|
|
34
34
|
rescue Exception => ex
|
|
35
|
-
|
|
35
|
+
Log.error "Exception while sending message to message queue: #{ex.message}"
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
end
|
|
@@ -52,7 +52,7 @@ module Alondra
|
|
|
52
52
|
begin
|
|
53
53
|
push_socket.send_string(message.to_json)
|
|
54
54
|
rescue Exception => ex
|
|
55
|
-
|
|
55
|
+
Log.error "Exception while sending message to message queue: #{ex.message}"
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -6,22 +6,23 @@ module Alondra
|
|
|
6
6
|
include AbstractController::Helpers
|
|
7
7
|
include AbstractController::Translation
|
|
8
8
|
include AbstractController::AssetPaths
|
|
9
|
-
include
|
|
9
|
+
include ActionController::RequestForgeryProtection
|
|
10
10
|
|
|
11
11
|
attr_accessor :channel_names
|
|
12
|
+
attr_accessor :request
|
|
12
13
|
|
|
13
|
-
def initialize(context, to)
|
|
14
|
+
def initialize(context, to, request = nil)
|
|
14
15
|
@channel_names = Channel.names_for(to)
|
|
15
|
-
|
|
16
|
+
@request = request
|
|
17
|
+
|
|
16
18
|
self.class.view_paths = ActionController::Base.view_paths
|
|
17
19
|
copy_instance_variables_from(context)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def render_push(options)
|
|
21
|
-
|
|
22
23
|
if EM.reactor_thread?
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
Log.warn 'You are rendering a view from the Event Machine reactor thread'
|
|
25
|
+
Log.warn 'Rendering a view is a possibly blocking operation, so be careful'
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
message_content = render_to_string(*options)
|
|
@@ -36,7 +37,7 @@ module Alondra
|
|
|
36
37
|
def view_paths
|
|
37
38
|
@view_paths ||= ApplicationController.send '_view_paths'
|
|
38
39
|
end
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
def action_name
|
|
41
42
|
'push'
|
|
42
43
|
end
|
data/lib/alondra/pushing.rb
CHANGED
|
@@ -7,7 +7,12 @@ module Alondra
|
|
|
7
7
|
raise PushingException.new('You need to specify the channel to push') unless args.last[:to].present?
|
|
8
8
|
|
|
9
9
|
to = args.last.delete(:to)
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
# If we are called in the context of a request we save this information
|
|
12
|
+
# so we can create proper routes
|
|
13
|
+
caller_request = self.respond_to?(:request) ? request : nil
|
|
14
|
+
|
|
15
|
+
controller = PushController.new(self, to, caller_request)
|
|
11
16
|
controller.render_push(args)
|
|
12
17
|
end
|
|
13
18
|
end
|
data/lib/alondra/server.rb
CHANGED
|
@@ -5,39 +5,39 @@ module Alondra
|
|
|
5
5
|
extend self
|
|
6
6
|
|
|
7
7
|
def run
|
|
8
|
-
|
|
8
|
+
Log.info "Server starting on port #{Alondra.config.port}"
|
|
9
9
|
|
|
10
10
|
EM::WebSocket.start(:host => '0.0.0.0', :port => Alondra.config.port) do |websocket|
|
|
11
11
|
|
|
12
12
|
websocket.onopen do
|
|
13
13
|
session = SessionParser.parse(websocket)
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
Log.info "client connected."
|
|
16
16
|
Connection.new(websocket, session)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
websocket.onclose do
|
|
20
|
-
|
|
20
|
+
Log.info "Connection closed"
|
|
21
21
|
Connections[websocket].destroy! if Connections[websocket].present?
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
websocket.onerror do |ex|
|
|
25
25
|
puts "Error: #{ex.message}"
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
Log.error "Error: #{ex.message}"
|
|
27
|
+
Log.error ex.backtrace.join("\n")
|
|
28
28
|
Connections[websocket].destroy! if Connections[websocket]
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
websocket.onmessage do |msg|
|
|
32
|
-
|
|
32
|
+
Log.info "received: #{msg}"
|
|
33
33
|
CommandDispatcher.dispatch(msg, Connections[websocket])
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
EM.error_handler do |error|
|
|
38
38
|
puts "Error raised during event loop: #{error.message}"
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
Log.error "Error raised during event loop: #{error.message}"
|
|
40
|
+
Log.error error.backtrace.join("\n")
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
end
|
|
@@ -29,10 +29,10 @@ module Alondra
|
|
|
29
29
|
encoded_session = cookies.detect{|c| c.include?(session_key)}.gsub("#{session_key}=",'').strip
|
|
30
30
|
verifier.verify(CGI.unescape(encoded_session))
|
|
31
31
|
rescue ActiveSupport::MessageVerifier::InvalidSignature => ex
|
|
32
|
-
|
|
32
|
+
Log.error "invalid session cookie: #{cookie}"
|
|
33
33
|
Hash.new
|
|
34
34
|
rescue Exception => ex
|
|
35
|
-
|
|
35
|
+
Log.error "Exception parsing session from cookie: #{ex.message}"
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -41,7 +41,7 @@ module Alondra
|
|
|
41
41
|
decoded_token = verifier.verify(token)
|
|
42
42
|
ActiveSupport::JSON.decode(decoded_token)
|
|
43
43
|
rescue ActiveSupport::MessageVerifier::InvalidSignature => ex
|
|
44
|
-
|
|
44
|
+
Log.error "invalid session token: #{token}"
|
|
45
45
|
Hash.new
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -6,28 +6,25 @@ require 'rubygems'
|
|
|
6
6
|
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
|
7
7
|
require 'daemons'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
log_dir = File.expand_path('../log', File.dirname(__FILE__))
|
|
11
|
-
|
|
12
9
|
options = {
|
|
13
10
|
:app_name => 'alondra',
|
|
14
11
|
:dir_mode => :script,
|
|
15
|
-
:dir => '
|
|
16
|
-
:log_dir => log_dir
|
|
12
|
+
:dir => 'tmp/pids'
|
|
17
13
|
}
|
|
18
14
|
|
|
19
15
|
Daemons.run_proc 'alondra', options do
|
|
20
16
|
|
|
21
17
|
ENV["ALONDRA_SERVER"] = 'true'
|
|
18
|
+
|
|
22
19
|
require_relative File.join('..', 'config', 'environment')
|
|
23
|
-
|
|
24
|
-
log_path = File.join(
|
|
20
|
+
|
|
21
|
+
log_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'log', 'alondra.log'))
|
|
22
|
+
|
|
25
23
|
Rails.logger = ActiveSupport::BufferedLogger.new(log_path)
|
|
26
24
|
|
|
27
|
-
Alondra::Alondra.
|
|
28
|
-
|
|
29
|
-
Rails.logger.info "Started alondra server... #{EM.reactor_running?}"
|
|
25
|
+
Log.info "Started alondra server on port #{Alondra::Alondra.config.port}... #{EM.reactor_running?}"
|
|
30
26
|
|
|
31
27
|
EM.reactor_thread.join
|
|
32
|
-
|
|
28
|
+
|
|
29
|
+
Log.info 'Alondra server terminated'
|
|
33
30
|
end
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<%= javascript_include_tag 'alondra-client' %>
|
|
37
37
|
|
|
38
38
|
<script type="text/javascript">
|
|
39
|
-
var client = new AlondraClient('localhost
|
|
39
|
+
var client = new AlondraClient('localhost:<%= Alondra::Alondra.config.port %>', '<%= chat_path(@path) %>', '<%= encrypted_token %>');
|
|
40
40
|
|
|
41
41
|
$(client).bind('subscribed.Chat', function(event, resource){
|
|
42
42
|
console.log('Received subscribed event!');
|
data/test/models/channel_test.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: alondra
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -10,11 +10,11 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2012-03-27 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: daemons
|
|
17
|
-
requirement:
|
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
|
18
18
|
none: false
|
|
19
19
|
requirements:
|
|
20
20
|
- - ! '>='
|
|
@@ -22,10 +22,15 @@ dependencies:
|
|
|
22
22
|
version: '0'
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
|
-
version_requirements:
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
none: false
|
|
27
|
+
requirements:
|
|
28
|
+
- - ! '>='
|
|
29
|
+
- !ruby/object:Gem::Version
|
|
30
|
+
version: '0'
|
|
26
31
|
- !ruby/object:Gem::Dependency
|
|
27
32
|
name: uuidtools
|
|
28
|
-
requirement:
|
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
34
|
none: false
|
|
30
35
|
requirements:
|
|
31
36
|
- - ! '>='
|
|
@@ -33,10 +38,15 @@ dependencies:
|
|
|
33
38
|
version: '0'
|
|
34
39
|
type: :runtime
|
|
35
40
|
prerelease: false
|
|
36
|
-
version_requirements:
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
none: false
|
|
43
|
+
requirements:
|
|
44
|
+
- - ! '>='
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
37
47
|
- !ruby/object:Gem::Dependency
|
|
38
48
|
name: rails
|
|
39
|
-
requirement:
|
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
|
40
50
|
none: false
|
|
41
51
|
requirements:
|
|
42
52
|
- - ! '>='
|
|
@@ -44,21 +54,15 @@ dependencies:
|
|
|
44
54
|
version: 3.1.0
|
|
45
55
|
type: :runtime
|
|
46
56
|
prerelease: false
|
|
47
|
-
version_requirements:
|
|
48
|
-
- !ruby/object:Gem::Dependency
|
|
49
|
-
name: eventmachine
|
|
50
|
-
requirement: &2152721740 !ruby/object:Gem::Requirement
|
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
58
|
none: false
|
|
52
59
|
requirements:
|
|
53
60
|
- - ! '>='
|
|
54
61
|
- !ruby/object:Gem::Version
|
|
55
|
-
version: 1.0
|
|
56
|
-
type: :runtime
|
|
57
|
-
prerelease: false
|
|
58
|
-
version_requirements: *2152721740
|
|
62
|
+
version: 3.1.0
|
|
59
63
|
- !ruby/object:Gem::Dependency
|
|
60
64
|
name: em-websocket
|
|
61
|
-
requirement:
|
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
|
62
66
|
none: false
|
|
63
67
|
requirements:
|
|
64
68
|
- - ! '>='
|
|
@@ -66,29 +70,28 @@ dependencies:
|
|
|
66
70
|
version: '0'
|
|
67
71
|
type: :runtime
|
|
68
72
|
prerelease: false
|
|
69
|
-
version_requirements:
|
|
70
|
-
- !ruby/object:Gem::Dependency
|
|
71
|
-
name: ffi-rzmq
|
|
72
|
-
requirement: &2152720780 !ruby/object:Gem::Requirement
|
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
74
|
none: false
|
|
74
75
|
requirements:
|
|
75
|
-
- -
|
|
76
|
+
- - ! '>='
|
|
76
77
|
- !ruby/object:Gem::Version
|
|
77
|
-
version: 0
|
|
78
|
-
type: :runtime
|
|
79
|
-
prerelease: false
|
|
80
|
-
version_requirements: *2152720780
|
|
78
|
+
version: '0'
|
|
81
79
|
- !ruby/object:Gem::Dependency
|
|
82
80
|
name: em-zeromq
|
|
83
|
-
requirement:
|
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
|
84
82
|
none: false
|
|
85
83
|
requirements:
|
|
86
|
-
- - =
|
|
84
|
+
- - '='
|
|
87
85
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: 0.2.
|
|
86
|
+
version: 0.2.2
|
|
89
87
|
type: :runtime
|
|
90
88
|
prerelease: false
|
|
91
|
-
version_requirements:
|
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
90
|
+
none: false
|
|
91
|
+
requirements:
|
|
92
|
+
- - '='
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: 0.2.2
|
|
92
95
|
description: Add real time capabilities to your rails app
|
|
93
96
|
email:
|
|
94
97
|
executables: []
|
|
@@ -121,6 +124,7 @@ files:
|
|
|
121
124
|
- lib/alondra/event_listener.rb
|
|
122
125
|
- lib/alondra/event_router.rb
|
|
123
126
|
- lib/alondra/listener_callback.rb
|
|
127
|
+
- lib/alondra/log.rb
|
|
124
128
|
- lib/alondra/message.rb
|
|
125
129
|
- lib/alondra/message_queue.rb
|
|
126
130
|
- lib/alondra/message_queue_client.rb
|
|
@@ -231,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
231
235
|
version: '0'
|
|
232
236
|
requirements: []
|
|
233
237
|
rubyforge_project:
|
|
234
|
-
rubygems_version: 1.8.
|
|
238
|
+
rubygems_version: 1.8.21
|
|
235
239
|
signing_key:
|
|
236
240
|
specification_version: 3
|
|
237
241
|
summary: Add real time capabilities to your rails app
|
|
@@ -314,3 +318,4 @@ test_files:
|
|
|
314
318
|
- test/support/mocks/mock_event_router.rb
|
|
315
319
|
- test/support/mocks/mock_listener.rb
|
|
316
320
|
- test/test_helper.rb
|
|
321
|
+
has_rdoc:
|