message_bus 0.0.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of message_bus might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -0
  3. data/.travis.yml +6 -0
  4. data/CHANGELOG +9 -0
  5. data/Gemfile +15 -0
  6. data/Guardfile +7 -0
  7. data/README.md +8 -0
  8. data/Rakefile +14 -0
  9. data/assets/application.handlebars +7 -0
  10. data/assets/application.js +79 -0
  11. data/assets/ember.js +26839 -0
  12. data/assets/handlebars.js +2201 -0
  13. data/assets/index.handlebars +25 -0
  14. data/assets/jquery-1.8.2.js +9440 -0
  15. data/assets/message-bus.js +247 -0
  16. data/examples/bench/ab.sample +1 -0
  17. data/examples/bench/config.ru +24 -0
  18. data/examples/bench/payload.post +1 -0
  19. data/examples/bench/unicorn.conf.rb +4 -0
  20. data/examples/chat/chat.rb +74 -0
  21. data/examples/chat/config.ru +2 -0
  22. data/lib/message_bus.rb +60 -5
  23. data/lib/message_bus/client.rb +45 -7
  24. data/lib/message_bus/connection_manager.rb +35 -7
  25. data/lib/message_bus/em_ext.rb +5 -0
  26. data/lib/message_bus/rack/middleware.rb +60 -89
  27. data/lib/message_bus/rack/thin_ext.rb +71 -0
  28. data/lib/message_bus/rails/railtie.rb +4 -1
  29. data/lib/message_bus/reliable_pub_sub.rb +22 -4
  30. data/lib/message_bus/version.rb +1 -1
  31. data/message_bus.gemspec +20 -0
  32. data/spec/lib/client_spec.rb +50 -0
  33. data/spec/lib/connection_manager_spec.rb +83 -0
  34. data/spec/lib/fake_async_middleware.rb +134 -0
  35. data/spec/lib/handlers/demo_message_handler.rb +5 -0
  36. data/spec/lib/message_bus_spec.rb +112 -0
  37. data/spec/lib/message_handler_spec.rb +39 -0
  38. data/spec/lib/middleware_spec.rb +306 -0
  39. data/spec/lib/multi_process_spec.rb +60 -0
  40. data/spec/lib/reliable_pub_sub_spec.rb +167 -0
  41. data/spec/spec_helper.rb +19 -0
  42. data/vendor/assets/javascripts/message-bus.js +247 -0
  43. metadata +55 -26
@@ -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.0.2
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-05-15 00:00:00.000000000 Z
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 built on websockets
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
- - README.md
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/rack/diagnostics.rb
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.2
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