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