message_bus 0.0.2 → 0.9.3
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.
Potentially problematic release.
This version of message_bus might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +18 -0
- data/.travis.yml +6 -0
- data/CHANGELOG +9 -0
- data/Gemfile +15 -0
- data/Guardfile +7 -0
- data/README.md +8 -0
- data/Rakefile +14 -0
- data/assets/application.handlebars +7 -0
- data/assets/application.js +79 -0
- data/assets/ember.js +26839 -0
- data/assets/handlebars.js +2201 -0
- data/assets/index.handlebars +25 -0
- data/assets/jquery-1.8.2.js +9440 -0
- data/assets/message-bus.js +247 -0
- data/examples/bench/ab.sample +1 -0
- data/examples/bench/config.ru +24 -0
- data/examples/bench/payload.post +1 -0
- data/examples/bench/unicorn.conf.rb +4 -0
- data/examples/chat/chat.rb +74 -0
- data/examples/chat/config.ru +2 -0
- data/lib/message_bus.rb +60 -5
- data/lib/message_bus/client.rb +45 -7
- data/lib/message_bus/connection_manager.rb +35 -7
- data/lib/message_bus/em_ext.rb +5 -0
- data/lib/message_bus/rack/middleware.rb +60 -89
- data/lib/message_bus/rack/thin_ext.rb +71 -0
- data/lib/message_bus/rails/railtie.rb +4 -1
- data/lib/message_bus/reliable_pub_sub.rb +22 -4
- data/lib/message_bus/version.rb +1 -1
- data/message_bus.gemspec +20 -0
- data/spec/lib/client_spec.rb +50 -0
- data/spec/lib/connection_manager_spec.rb +83 -0
- data/spec/lib/fake_async_middleware.rb +134 -0
- data/spec/lib/handlers/demo_message_handler.rb +5 -0
- data/spec/lib/message_bus_spec.rb +112 -0
- data/spec/lib/message_handler_spec.rb +39 -0
- data/spec/lib/middleware_spec.rb +306 -0
- data/spec/lib/multi_process_spec.rb +60 -0
- data/spec/lib/reliable_pub_sub_spec.rb +167 -0
- data/spec/spec_helper.rb +19 -0
- data/vendor/assets/javascripts/message-bus.js +247 -0
- metadata +55 -26
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'thin'
|
2
|
+
require 'lib/fake_async_middleware'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.color_enabled = true
|
6
|
+
end
|
7
|
+
|
8
|
+
def wait_for(timeout_milliseconds)
|
9
|
+
timeout = (timeout_milliseconds + 0.0) / 1000
|
10
|
+
finish = Time.now + timeout
|
11
|
+
t = Thread.new do
|
12
|
+
while Time.now < finish && !yield
|
13
|
+
sleep(0.001)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
t.join
|
17
|
+
end
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,247 @@
|
|
1
|
+
/*jshint bitwise: false*/
|
2
|
+
|
3
|
+
/**
|
4
|
+
Message Bus functionality.
|
5
|
+
|
6
|
+
@class MessageBus
|
7
|
+
@namespace Discourse
|
8
|
+
@module Discourse
|
9
|
+
**/
|
10
|
+
window.MessageBus = (function() {
|
11
|
+
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
|
12
|
+
var callbacks, clientId, failCount, interval, shouldLongPoll, queue, responseCallbacks, uniqueId, baseUrl;
|
13
|
+
var me, started, stopped, longPoller, pollTimeout;
|
14
|
+
|
15
|
+
uniqueId = function() {
|
16
|
+
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
17
|
+
var r, v;
|
18
|
+
r = Math.random() * 16 | 0;
|
19
|
+
v = c === 'x' ? r : (r & 0x3 | 0x8);
|
20
|
+
return v.toString(16);
|
21
|
+
});
|
22
|
+
};
|
23
|
+
|
24
|
+
clientId = uniqueId();
|
25
|
+
responseCallbacks = {};
|
26
|
+
callbacks = [];
|
27
|
+
queue = [];
|
28
|
+
interval = null;
|
29
|
+
failCount = 0;
|
30
|
+
baseUrl = "/";
|
31
|
+
|
32
|
+
/* TODO: The plan is to force a long poll as soon as page becomes visible
|
33
|
+
// MIT based off https://github.com/mathiasbynens/jquery-visibility/blob/master/jquery-visibility.js
|
34
|
+
initVisibilityTracking = function(window, document, $, undefined) {
|
35
|
+
var prefix;
|
36
|
+
var property;
|
37
|
+
// In Opera, `'onfocusin' in document == true`, hence the extra `hasFocus` check to detect IE-like behavior
|
38
|
+
var eventName = 'onfocusin' in document && 'hasFocus' in document ? 'focusin focusout' : 'focus blur';
|
39
|
+
var prefixes = ['webkit', 'o', 'ms', 'moz', ''];
|
40
|
+
var $event = $.event;
|
41
|
+
|
42
|
+
while ((prefix = prefixes.pop()) !== undefined) {
|
43
|
+
property = (prefix ? prefix + 'H': 'h') + 'idden';
|
44
|
+
var supportsVisibility = typeof document[property] === 'boolean';
|
45
|
+
if (supportsVisibility) {
|
46
|
+
eventName = prefix + 'visibilitychange';
|
47
|
+
break;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
$(/blur$/.test(eventName) ? window : document).on(eventName, function(event) {
|
52
|
+
var type = event.type;
|
53
|
+
var originalEvent = event.originalEvent;
|
54
|
+
|
55
|
+
// Avoid errors from triggered native events for which `originalEvent` is
|
56
|
+
// not available.
|
57
|
+
if (!originalEvent) {
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
|
61
|
+
var toElement = originalEvent.toElement;
|
62
|
+
|
63
|
+
// If it’s a `{focusin,focusout}` event (IE), `fromElement` and `toElement`
|
64
|
+
// should both be `null` or `undefined`; else, the page visibility hasn’t
|
65
|
+
// changed, but the user just clicked somewhere in the doc. In IE9, we need
|
66
|
+
// to check the `relatedTarget` property instead.
|
67
|
+
if (
|
68
|
+
!/^focus./.test(type) || (
|
69
|
+
toElement === undefined &&
|
70
|
+
originalEvent.fromElement === undefined &&
|
71
|
+
originalEvent.relatedTarget === undefined
|
72
|
+
)
|
73
|
+
) {
|
74
|
+
visibilityChanged(property && document[property] || /^(?:blur|focusout)$/.test(type) ? 'hide' : 'show');
|
75
|
+
}
|
76
|
+
});
|
77
|
+
|
78
|
+
};
|
79
|
+
*/
|
80
|
+
|
81
|
+
var hiddenProperty;
|
82
|
+
|
83
|
+
$.each(["","webkit","ms","moz","ms"], function(index, prefix){
|
84
|
+
var check = prefix + (prefix === "" ? "hidden" : "Hidden");
|
85
|
+
if(document[check] !== undefined ){
|
86
|
+
hiddenProperty = check;
|
87
|
+
}
|
88
|
+
});
|
89
|
+
|
90
|
+
var isHidden = function() {
|
91
|
+
if (hiddenProperty !== undefined){
|
92
|
+
return document[hiddenProperty];
|
93
|
+
} else {
|
94
|
+
return !document.hasFocus;
|
95
|
+
}
|
96
|
+
};
|
97
|
+
|
98
|
+
shouldLongPoll = function() {
|
99
|
+
return me.alwaysLongPoll || !isHidden();
|
100
|
+
};
|
101
|
+
|
102
|
+
longPoller = function(poll,data){
|
103
|
+
var gotData = false;
|
104
|
+
var lastAjax = new Date();
|
105
|
+
|
106
|
+
return $.ajax(baseUrl + "message-bus/" + clientId + "/poll?" + (!shouldLongPoll() || !me.enableLongPolling ? "dlp=t" : ""), {
|
107
|
+
data: data,
|
108
|
+
cache: false,
|
109
|
+
dataType: 'json',
|
110
|
+
type: 'POST',
|
111
|
+
headers: {
|
112
|
+
'X-SILENCE-LOGGER': 'true'
|
113
|
+
},
|
114
|
+
success: function(messages) {
|
115
|
+
failCount = 0;
|
116
|
+
$.each(messages,function(_,message) {
|
117
|
+
gotData = true;
|
118
|
+
$.each(callbacks, function(_,callback) {
|
119
|
+
if (callback.channel === message.channel) {
|
120
|
+
callback.last_id = message.message_id;
|
121
|
+
callback.func(message.data);
|
122
|
+
}
|
123
|
+
if (message.channel === "/__status") {
|
124
|
+
if (message.data[callback.channel] !== undefined) {
|
125
|
+
callback.last_id = message.data[callback.channel];
|
126
|
+
}
|
127
|
+
}
|
128
|
+
});
|
129
|
+
});
|
130
|
+
},
|
131
|
+
error: failCount += 1,
|
132
|
+
complete: function() {
|
133
|
+
if (gotData) {
|
134
|
+
pollTimeout = setTimeout(poll, 100);
|
135
|
+
} else {
|
136
|
+
interval = me.callbackInterval;
|
137
|
+
if (failCount > 2) {
|
138
|
+
interval = interval * failCount;
|
139
|
+
} else if (!shouldLongPoll()) {
|
140
|
+
// slowning down stuff a lot when hidden
|
141
|
+
// we will need to add a lot of fine tuning here
|
142
|
+
interval = interval * 4;
|
143
|
+
}
|
144
|
+
if (interval > me.maxPollInterval) {
|
145
|
+
interval = me.maxPollInterval;
|
146
|
+
}
|
147
|
+
|
148
|
+
interval -= (new Date() - lastAjax);
|
149
|
+
if (interval < 100) {
|
150
|
+
interval = 100;
|
151
|
+
}
|
152
|
+
|
153
|
+
pollTimeout = setTimeout(poll, interval);
|
154
|
+
}
|
155
|
+
me.longPoll = null;
|
156
|
+
}
|
157
|
+
});
|
158
|
+
};
|
159
|
+
|
160
|
+
me = {
|
161
|
+
enableLongPolling: true,
|
162
|
+
callbackInterval: 15000,
|
163
|
+
maxPollInterval: 3 * 60 * 1000,
|
164
|
+
callbacks: callbacks,
|
165
|
+
clientId: clientId,
|
166
|
+
alwaysLongPoll: false,
|
167
|
+
baseUrl: baseUrl,
|
168
|
+
|
169
|
+
stop: function() {
|
170
|
+
stopped = true;
|
171
|
+
started = false;
|
172
|
+
},
|
173
|
+
|
174
|
+
// Start polling
|
175
|
+
start: function(opts) {
|
176
|
+
var poll;
|
177
|
+
|
178
|
+
if (started) return;
|
179
|
+
started = true;
|
180
|
+
stopped = false;
|
181
|
+
|
182
|
+
if (!opts) opts = {};
|
183
|
+
|
184
|
+
poll = function() {
|
185
|
+
var data;
|
186
|
+
|
187
|
+
if(stopped) {
|
188
|
+
return;
|
189
|
+
}
|
190
|
+
|
191
|
+
if (callbacks.length === 0) {
|
192
|
+
setTimeout(poll, 500);
|
193
|
+
return;
|
194
|
+
}
|
195
|
+
|
196
|
+
data = {};
|
197
|
+
$.each(callbacks, function(_,callback) {
|
198
|
+
data[callback.channel] = callback.last_id;
|
199
|
+
});
|
200
|
+
me.longPoll = longPoller(poll,data);
|
201
|
+
};
|
202
|
+
poll();
|
203
|
+
},
|
204
|
+
|
205
|
+
// Subscribe to a channel
|
206
|
+
subscribe: function(channel, func, lastId) {
|
207
|
+
|
208
|
+
if(!started && !stopped){
|
209
|
+
me.start();
|
210
|
+
}
|
211
|
+
|
212
|
+
if (typeof(lastId) !== "number" || lastId < -1){
|
213
|
+
lastId = -1;
|
214
|
+
}
|
215
|
+
callbacks.push({
|
216
|
+
channel: channel,
|
217
|
+
func: func,
|
218
|
+
last_id: lastId
|
219
|
+
});
|
220
|
+
if (me.longPoll) {
|
221
|
+
return me.longPoll.abort();
|
222
|
+
}
|
223
|
+
},
|
224
|
+
|
225
|
+
// Unsubscribe from a channel
|
226
|
+
unsubscribe: function(channel) {
|
227
|
+
// TODO proper globbing
|
228
|
+
var glob;
|
229
|
+
if (channel.indexOf("*", channel.length - 1) !== -1) {
|
230
|
+
channel = channel.substr(0, channel.length - 1);
|
231
|
+
glob = true;
|
232
|
+
}
|
233
|
+
callbacks = $.grep(callbacks,function(callback) {
|
234
|
+
if (glob) {
|
235
|
+
return callback.channel.substr(0, channel.length) !== channel;
|
236
|
+
} else {
|
237
|
+
return callback.channel !== channel;
|
238
|
+
}
|
239
|
+
});
|
240
|
+
if (me.longPoll) {
|
241
|
+
return me.longPoll.abort();
|
242
|
+
}
|
243
|
+
}
|
244
|
+
};
|
245
|
+
|
246
|
+
return me;
|
247
|
+
})();
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: message_bus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.1.3
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: thin
|
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
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: eventmachine
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,26 +52,59 @@ dependencies:
|
|
66
52
|
- - '>='
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
|
-
description: A message bus
|
55
|
+
description: A message bus for rack
|
70
56
|
email:
|
71
57
|
- sam.saffron@gmail.com
|
72
58
|
executables: []
|
73
59
|
extensions: []
|
74
60
|
extra_rdoc_files: []
|
75
61
|
files:
|
76
|
-
-
|
62
|
+
- .gitignore
|
63
|
+
- .travis.yml
|
64
|
+
- CHANGELOG
|
65
|
+
- Gemfile
|
66
|
+
- Guardfile
|
77
67
|
- LICENSE
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- assets/application.handlebars
|
71
|
+
- assets/application.js
|
72
|
+
- assets/ember.js
|
73
|
+
- assets/handlebars.js
|
74
|
+
- assets/index.handlebars
|
75
|
+
- assets/jquery-1.8.2.js
|
76
|
+
- assets/message-bus.js
|
77
|
+
- examples/bench/ab.sample
|
78
|
+
- examples/bench/config.ru
|
79
|
+
- examples/bench/payload.post
|
80
|
+
- examples/bench/unicorn.conf.rb
|
81
|
+
- examples/chat/chat.rb
|
82
|
+
- examples/chat/config.ru
|
78
83
|
- lib/message_bus.rb
|
79
|
-
- lib/message_bus/
|
80
|
-
- lib/message_bus/rack/middleware.rb
|
81
|
-
- lib/message_bus/message.rb
|
84
|
+
- lib/message_bus/client.rb
|
82
85
|
- lib/message_bus/connection_manager.rb
|
86
|
+
- lib/message_bus/diagnostics.rb
|
87
|
+
- lib/message_bus/em_ext.rb
|
88
|
+
- lib/message_bus/message.rb
|
83
89
|
- lib/message_bus/message_handler.rb
|
90
|
+
- lib/message_bus/rack/diagnostics.rb
|
91
|
+
- lib/message_bus/rack/middleware.rb
|
92
|
+
- lib/message_bus/rack/thin_ext.rb
|
84
93
|
- lib/message_bus/rails/railtie.rb
|
85
|
-
- lib/message_bus/version.rb
|
86
|
-
- lib/message_bus/diagnostics.rb
|
87
|
-
- lib/message_bus/client.rb
|
88
94
|
- lib/message_bus/reliable_pub_sub.rb
|
95
|
+
- lib/message_bus/version.rb
|
96
|
+
- message_bus.gemspec
|
97
|
+
- spec/lib/client_spec.rb
|
98
|
+
- spec/lib/connection_manager_spec.rb
|
99
|
+
- spec/lib/fake_async_middleware.rb
|
100
|
+
- spec/lib/handlers/demo_message_handler.rb
|
101
|
+
- spec/lib/message_bus_spec.rb
|
102
|
+
- spec/lib/message_handler_spec.rb
|
103
|
+
- spec/lib/middleware_spec.rb
|
104
|
+
- spec/lib/multi_process_spec.rb
|
105
|
+
- spec/lib/reliable_pub_sub_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
- vendor/assets/javascripts/message-bus.js
|
89
108
|
homepage: ''
|
90
109
|
licenses: []
|
91
110
|
metadata: {}
|
@@ -105,8 +124,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
124
|
version: '0'
|
106
125
|
requirements: []
|
107
126
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.0.
|
127
|
+
rubygems_version: 2.0.3
|
109
128
|
signing_key:
|
110
129
|
specification_version: 4
|
111
130
|
summary: ''
|
112
|
-
test_files:
|
131
|
+
test_files:
|
132
|
+
- spec/lib/client_spec.rb
|
133
|
+
- spec/lib/connection_manager_spec.rb
|
134
|
+
- spec/lib/fake_async_middleware.rb
|
135
|
+
- spec/lib/handlers/demo_message_handler.rb
|
136
|
+
- spec/lib/message_bus_spec.rb
|
137
|
+
- spec/lib/message_handler_spec.rb
|
138
|
+
- spec/lib/middleware_spec.rb
|
139
|
+
- spec/lib/multi_process_spec.rb
|
140
|
+
- spec/lib/reliable_pub_sub_spec.rb
|
141
|
+
- spec/spec_helper.rb
|