plezi 0.14.4 → 0.14.5

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.
@@ -1,55 +1,54 @@
1
- require 'securerandom'
2
1
  module Plezi
3
- module Base
4
- module MessageDispatch
5
- module RedisDriver
6
- @redis_locker ||= Mutex.new
7
- @redis = @redis_sub_thread = nil
2
+ module Base
3
+ module MessageDispatch
4
+ module RedisDriver
5
+ @redis_locker ||= Mutex.new
6
+ @redis = @redis_sub_thread = nil
8
7
 
9
- module_function
8
+ module_function
10
9
 
11
- def connect
12
- return false unless ENV['PL_REDIS_URL'] && defined?(::Redis)
13
- return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis
14
- @redis_locker.synchronize do
15
- return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis # repeat the test inside syncing, things change.
16
- @redis.quit if @redis
17
- @redis = ::Redis.new(url: ENV['PL_REDIS_URL'])
18
- raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless @redis
19
- @redis_sub_thread = Thread.new do
20
- begin
21
- ::Redis.new(url: ENV['PL_REDIS_URL']).subscribe(::Plezi.app_name, ::Plezi::Base::MessageDispatch.pid) do |on|
22
- on.message do |_channel, msg|
23
- ::Plezi::Base::MessageDispatch << msg
10
+ def connect
11
+ return false unless ENV['PL_REDIS_URL'] && defined?(::Redis)
12
+ return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis
13
+ @redis_locker.synchronize do
14
+ return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis # repeat the test inside syncing, things change.
15
+ @redis.quit if @redis
16
+ @redis = ::Redis.new(url: ENV['PL_REDIS_URL'])
17
+ raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless @redis
18
+ @redis_sub_thread = Thread.new do
19
+ begin
20
+ ::Redis.new(url: ENV['PL_REDIS_URL']).subscribe(::Plezi.app_name, ::Plezi::Base::MessageDispatch.pid) do |on|
21
+ on.message do |_channel, msg|
22
+ ::Plezi::Base::MessageDispatch << msg
23
+ end
24
+ end
25
+ rescue => e
26
+ puts e.message, e.backtrace
27
+ retry
28
+ end
24
29
  end
25
- end
26
- rescue => e
27
- puts e.message, e.backtrace
28
- retry
29
- end
30
+ @redis
31
+ end
30
32
  end
31
- @redis
32
- end
33
- end
34
33
 
35
- # Get the current redis connection.
36
- def redis
37
- @redis || connect
38
- end
34
+ # Get the current redis connection.
35
+ def redis
36
+ @redis || connect
37
+ end
39
38
 
40
- def push(channel, message)
41
- return unless connect
42
- return if away?(channel)
43
- redis.publish(channel, message)
44
- end
39
+ def push(channel, message)
40
+ return unless connect
41
+ return if away?(channel)
42
+ redis.publish(channel, message)
43
+ end
45
44
 
46
- def away?(server)
47
- return true unless connect
48
- @redis.pubsub('CHANNELS', server).empty?
49
- end
45
+ def away?(server)
46
+ return true unless connect
47
+ @redis.pubsub('CHANNELS', server).empty?
48
+ end
49
+ end
50
50
  end
51
- end
52
- end
51
+ end
53
52
  end
54
53
 
55
54
  ::Plezi::Base::MessageDispatch.drivers << ::Plezi::Base::MessageDispatch::RedisDriver
@@ -27,12 +27,12 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ['lib']
29
29
 
30
- spec.add_dependency 'iodine', '~> 0.2', '>= 0.2.7'
30
+ spec.add_dependency 'iodine', '~> 0.2', '>= 0.2.14'
31
31
  spec.add_dependency 'rack', '>= 2.0.0'
32
- spec.add_dependency 'bundler', '~> 1.13'
32
+ spec.add_dependency 'bundler', '~> 1.14'
33
33
  # spec.add_dependency 'redcarpet', '> 3.3.0'
34
34
  # spec.add_dependency 'slim', '> 3.0.0'
35
35
 
36
- spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'rake', '~> 11.0'
37
37
  spec.add_development_dependency 'minitest', '~> 5.0'
38
38
  end
@@ -7,16 +7,20 @@
7
7
  //
8
8
  // var client = new PleziClient()
9
9
  //
10
- // To open a connection to a different path for the original server (SSL will be preserved when in use), use:
10
+ // To open a connection to a different path for the original server (SSL will be
11
+ // preserved when in use), use:
11
12
  //
12
13
  // var client = new PleziClient(PleziClient.origin + "/path")
13
14
  //
14
- // To automatically renew the connection when disconnections are reported by the browser, use:
15
+ // To automatically renew the connection when disconnections are reported by the
16
+ // browser, use:
15
17
  //
16
18
  // client.autoreconnect = true
17
- // client.reconnect_interval = 250 // sets how long to wait before reconnection attempts. default is 250 ms.
19
+ // client.reconnect_interval = 250 // sets how long to wait before
20
+ // reconnection attempts. default is 250 ms.
18
21
  //
19
- // To set up event handling, directly set an `<event name>` callback. i.e., for an event called `chat`:
22
+ // To set up event handling, directly set an `<event name>` callback. i.e., for
23
+ // an event called `chat`:
20
24
  //
21
25
  // client.chat = function(event) { "..." }
22
26
  //
@@ -25,229 +29,250 @@
25
29
  // client.emit({event: "chat", data: "the message"})
26
30
  //
27
31
  function PleziClient(url, autoreconnect) {
28
- // Set URL
29
- if (url) {
30
- this.url = url;
31
- } else {
32
- this.url = PleziClient.origin + self.location.pathname;
33
- }
34
- // Connect Websocket
35
- this.reconnect();
36
- // Setup AJAJ
37
- this.ajaj = {};
38
- this.ajaj.client = this;
39
- this.ajaj.url = this.url.replace(/^ws:\/\//i, "http://").replace(/^wss:\/\//i, "https://");
40
- this.ajaj.add = {};
41
- this.ajaj.emit = this.___ajaj__emit;
42
- this.ajaj.auto = false;
43
- // auto-reconnection
44
- this.autoreconnect = false;
45
- this.reconnect_interval = 200;
46
- // dump data to console?
47
- this.log_events = false;
48
- // the timeout for a message ack receipt
49
- this.emit_timeout = false;
50
- // Set the autoreconnect property
51
- if (autoreconnect) {
52
- this.autoreconnect = true;
53
- }
32
+ // Set URL
33
+ if (url) {
34
+ this.url = url;
35
+ } else {
36
+ this.url = PleziClient.origin + self.location.pathname;
37
+ }
38
+ // Connect Websocket
39
+ this.reconnect();
40
+ // Setup AJAJ
41
+ this.ajaj = {};
42
+ this.ajaj.client = this;
43
+ this.ajaj.url = this.url.replace(/^ws:\/\//i, "http://")
44
+ .replace(/^wss:\/\//i, "https://");
45
+ this.ajaj.add = {};
46
+ this.ajaj.emit = this.___ajaj__emit;
47
+ this.ajaj.auto = false;
48
+ // auto-reconnection
49
+ this.autoreconnect = false;
50
+ this.reconnect_interval = 200;
51
+ // dump data to console?
52
+ this.log_events = false;
53
+ // the timeout for a message ack receipt
54
+ this.emit_timeout = false;
55
+ // Set the autoreconnect property
56
+ if (autoreconnect) {
57
+ this.autoreconnect = true;
58
+ }
54
59
  }
55
60
  // The Websocket onopen callback
56
- PleziClient.prototype.___on_open = function(e) {
57
- this.owner.connected = true;
58
- if (this.owner.onopen) {
59
- this.owner.onopen(e);
60
- }
61
- }
61
+ PleziClient.prototype.___on_open =
62
+ function(e) {
63
+ this.owner.connected = true;
64
+ if (this.owner.onopen) {
65
+ this.owner.onopen(e);
66
+ }
67
+ }
62
68
  // The Websocket onclose callback
63
- PleziClient.prototype.___on_close = function(e) {
64
- this.owner.connected = false;
65
- if (this.owner.onclose) {
66
- this.owner.onclose(e);
67
- }
68
- if (this.owner.autoreconnect) {
69
- setTimeout(function(obj) {
70
- obj.reconnect();
71
- }, this.owner.reconnect_interval, this.owner);
72
- }
73
- }
74
- // The Websocket onerror callback
75
- PleziClient.prototype.___on_error = function(e) {
76
- if (this.owner.onerror) {
77
- this.owner.onerror(e);
78
- }
69
+ PleziClient.prototype.___on_close =
70
+ function(e) {
71
+ this.owner.connected = false;
72
+ if (this.owner.onclose) {
73
+ this.owner.onclose(e);
74
+ }
75
+ if (this.owner.autoreconnect) {
76
+ setTimeout(function(obj) { obj.reconnect(); },
77
+ this.owner.reconnect_interval, this.owner);
78
+ }
79
+ }
80
+ // The Websocket onerror callback
81
+ PleziClient.prototype.___on_error =
82
+ function(e) {
83
+ if (this.owner.onerror) {
84
+ this.owner.onerror(e);
85
+ }
86
+ }
87
+ // The Websocket onmessage callback
88
+ PleziClient.prototype.___on_message = function(e) {
89
+ try {
90
+ var msg = JSON.parse(e.data);
91
+ this.owner.___dispatch(msg);
92
+ } catch (err) {
93
+ console.error(
94
+ "PleziClient experienced an error parsing the following data (not JSON):",
95
+ err, e);
96
+ }
97
+ };
98
+
99
+ PleziClient.prototype.___dispatch =
100
+ function(msg) {
101
+ try {
102
+ if (this.log_events) {
103
+ console.log(msg);
79
104
  }
80
- // The Websocket onmessage callback
81
- PleziClient.prototype.___on_message = function(e) {
82
- try {
83
- var msg = JSON.parse(e.data);
84
- this.owner.___dispatch(msg);
85
- } catch (err) {
86
- console.error("PleziClient experienced an error parsing the following data (not JSON):",
87
- err, e);
105
+ if (msg.event == '_ack_') {
106
+ clearTimeout(msg._EID_);
107
+ if (this[msg._EID_] && this[msg._EID_].callback) {
108
+ this[msg._EID_].callback(this[msg._EID_].event, this);
109
+ }
110
+ delete this[msg._EID_];
88
111
  }
89
- }
90
- PleziClient.prototype.___dispatch = function(msg) {
91
- try {
92
- if (this.log_events) {
93
- console.log(msg);
94
- }
95
- if (msg.event == '_ack_') {
96
- clearTimeout(msg._EID_);
97
- if (this[msg._EID_] && this[msg._EID_].callback) {
98
- this[msg._EID_].callback(this[msg._EID_].event, this);
99
- }
100
- delete this[msg._EID_];
101
- }
102
- if ((msg.event) && (this[msg.event])) {
103
- this[msg.event](msg);
104
- } else if ((msg.event) && (this['on' + msg.event])) {
105
- console.warn('PleziClient: use a callback called "' + msg.event +
106
- '" instead of of "on' + msg.event + '"');
107
- this['on' + msg.event](msg);
108
- } else {
109
- if (this['unknown'] && (msg.event != '_ack_')) {
110
- this['unknown'](msg);
111
- };
112
- }
113
- } catch (err) {
114
- console.error("PleziClient experienced an error while responding to the following onmessage event",
115
- err, msg);
112
+ if ((msg.event) && (this[msg.event])) {
113
+ this[msg.event](msg);
114
+ } else if ((msg.event) && (this['on' + msg.event])) {
115
+ console.warn('PleziClient: use a callback called "' + msg.event +
116
+ '" instead of of "on' + msg.event + '"');
117
+ this['on' + msg.event](msg);
118
+ } else {
119
+ if (this['unknown'] && (msg.event != '_ack_')) {
120
+ this['unknown'](msg);
121
+ };
116
122
  }
123
+ } catch (err) {
124
+ console.error(
125
+ "PleziClient experienced an error while responding to the following onmessage event",
126
+ err, msg);
127
+ }
117
128
  }
118
129
 
119
- // Clears meta timeout data
120
- PleziClient.prototype.___perform_timeout_callback = function(event, pl_client, callback) {
121
- delete pl_client[event._EID_];
122
- callback(event, pl_client);
130
+ // Clears meta timeout data
131
+ PleziClient.prototype.___perform_timeout_callback =
132
+ function(event, pl_client, callback) {
133
+ delete pl_client[event._EID_];
134
+ callback(event, pl_client);
123
135
  }
124
136
 
125
- // Sets a timeout for the websocket message
126
- PleziClient.prototype.___set_failed_timeout = function(event, callback, timeout) {
127
- if (event._EID_) {
128
- return event;
129
- };
130
- if (!timeout) {
131
- timeout = this.emit_timeout;
132
- };
133
- if (!callback) {
134
- callback = this.___on_timeout;
135
- };
136
- if (!timeout) {
137
- return event;
138
- };
139
- event._EID_ = setTimeout(this.___perform_timeout_callback, timeout, event, this, callback);
140
- return event;
141
- }
142
- // Removes the _client_ property from the event and calls
143
- // the ontimeout callback within the correct scope
144
- PleziClient.prototype.___on_timeout = function(event, client) {
145
- if (client.ajaj.auto) {
146
- if (client.log_events) {
147
- console.log("falling back on AJAJ for the event:", event);
148
- }
149
- client.ajaj.emit(event, client.ontimeout);
150
- } else {
151
- client.ontimeout(event);
152
- }
137
+ // Sets a timeout for the websocket message
138
+ PleziClient.prototype.___set_failed_timeout =
139
+ function(event, callback, timeout) {
140
+ if (event._EID_) {
141
+ return event;
142
+ };
143
+ if (!timeout) {
144
+ timeout = this.emit_timeout;
145
+ };
146
+ if (!callback) {
147
+ callback = this.___on_timeout;
148
+ };
149
+ if (!timeout) {
150
+ return event;
151
+ };
152
+ event._EID_ = setTimeout(this.___perform_timeout_callback, timeout, event,
153
+ this, callback);
154
+ return event;
155
+ }
156
+ // Removes the _client_ property from the event and
157
+ // calls
158
+ // the ontimeout callback within the correct scope
159
+ PleziClient.prototype.___on_timeout =
160
+ function(event, client) {
161
+ if (client.ajaj.auto) {
162
+ if (client.log_events) {
163
+ console.log("falling back on AJAJ for the event:", event);
153
164
  }
154
- // The timeout callback
155
- PleziClient.prototype.ontimeout = function(event) {
156
- console.warn("Timeout reached - it's assumed the connection was lost " +
157
- "and the following event was ignored by the server:", event);
158
- console.log(this);
165
+ client.ajaj.emit(event, client.ontimeout);
166
+ } else {
167
+ client.ontimeout(event);
168
+ }
159
169
  }
160
-
161
- PleziClient.prototype.reconnect = function() {
162
- this.connected = NaN;
163
- this.ws = new WebSocket(this.url);
164
- // lets us access the client from the callbacks
165
- this.ws.owner = this;
166
- // The Websocket onopen callback
167
- this.ws.onopen = this.___on_open;
168
- // The Websocket onclose callback
169
- this.ws.onclose = this.___on_close;
170
- // The Websocket onerror callback
171
- this.ws.onerror = this.___on_error;
172
- // The Websocket onmessage callback
173
- this.ws.onmessage = this.___on_message;
170
+ // The timeout callback
171
+ PleziClient.prototype.ontimeout =
172
+ function(event) {
173
+ console.warn("Timeout reached - it's assumed the connection was lost " +
174
+ "and the following event was ignored by the server:",
175
+ event);
176
+ console.log(this);
174
177
  }
175
178
 
176
- PleziClient.prototype.close = function() {
177
- this.autoreconnect = false;
178
- this.ws.close();
179
+ PleziClient.prototype.reconnect =
180
+ function() {
181
+ this.connected = NaN;
182
+ this.ws = new WebSocket(this.url);
183
+ // lets us access the client from the callbacks
184
+ this.ws.owner = this;
185
+ // The Websocket onopen callback
186
+ this.ws.onopen = this.___on_open;
187
+ // The Websocket onclose callback
188
+ this.ws.onclose = this.___on_close;
189
+ // The Websocket onerror callback
190
+ this.ws.onerror = this.___on_error;
191
+ // The Websocket onmessage callback
192
+ this.ws.onmessage = this.___on_message;
179
193
  }
180
194
 
181
- PleziClient.origin = (self.location.protocol.match(/https/) ? 'wws' : 'ws') + '://' + self.location.hostname + (self.location.port == '' ? '' : (':' + self.location.port));
182
-
183
- PleziClient.prototype.sendraw = function(data) {
184
- if (this.ws.readyState != 1) {
185
- return false;
186
- }
187
- this.ws.send(data);
188
- if (this.ws.readyState != 1) {
189
- return false;
190
- }
191
- return true;
195
+ PleziClient.prototype.close =
196
+ function() {
197
+ this.autoreconnect = false;
198
+ this.ws.close();
192
199
  }
193
200
 
194
- PleziClient.prototype.emit = function(event, callback, timeout_callback, timeout) {
195
- if (!timeout && callback && !this.emit_timeout)
196
- timeout = 10;
197
- this.___set_failed_timeout(event, timeout_callback, timeout)
198
- if (callback) {
199
- this[event._EID_] = {
200
- callback: callback,
201
- event: event
202
- };
203
- }
204
- return this.sendraw(JSON.stringify(event));
201
+ PleziClient.origin =
202
+ (self.location.protocol.match(/https/) ? 'wws'
203
+ : 'ws') +
204
+ '://' + self.location.hostname +
205
+ (self.location.port == ''
206
+ ? ''
207
+ : (':' + self.location.port));
208
+
209
+ PleziClient.prototype.sendraw =
210
+ function(data) {
211
+ if (this.ws.readyState != 1) {
212
+ return false;
213
+ }
214
+ this.ws.send(data);
215
+ if (this.ws.readyState != 1) {
216
+ return false;
217
+ }
218
+ return true;
205
219
  }
206
220
 
207
- PleziClient.prototype.readyState = function() {
208
- return this.ws.readyState;
221
+ PleziClient.prototype.emit =
222
+ function(event, callback, timeout_callback, timeout) {
223
+ if (!timeout && callback && !this.emit_timeout)
224
+ timeout = 10;
225
+ this.___set_failed_timeout(event, timeout_callback, timeout);
226
+ if (callback) {
227
+ this[event._EID_] = {callback : callback, event : event};
228
+ }
229
+ return this.sendraw(JSON.stringify(event));
209
230
  }
210
231
 
211
- PleziClient.prototype.___ajaj__emit = function(event, callback) {
212
- var combined = {}
213
- for (var k in this.add) {
214
- combined[k] = this.add[k];
215
- };
216
- for (var k in event) {
217
- combined[k] = event[k];
218
- };
219
- if (!combined.id) {
220
- combined.id = event.event;
221
- };
222
- var req = new XMLHttpRequest();
223
- req.client = this.client;
224
- req.json = combined;
225
- req.callback = callback;
226
- // if(!req.callback) req.callback = this.failed
227
- req.onreadystatechange = function() {
228
- if (this.readyState != 4) {
229
- return;
230
- }
231
- if (this.status == 200) {
232
- try {
233
- var res = JSON.parse(this.responseText);
234
- this.client.___dispatch(res);
235
- } catch (err) {
236
- console.error("PleziClient experienced an error parsing the following data (not JSON):",
237
- err, this.responseText);
238
- }
232
+ PleziClient.prototype.readyState =
233
+ function() { return this.ws.readyState; }
239
234
 
240
- } else {
241
- if (this.callback) {
242
- this.callback(this.json);
243
- }
244
- }
235
+ PleziClient.prototype.___ajaj__emit = function(event, callback) {
236
+ var combined = {};
237
+ for (var k in this.add) {
238
+ combined[k] = this.add[k];
239
+ };
240
+ for (var k in event) {
241
+ combined[k] = event[k];
242
+ };
243
+ if (!combined.id) {
244
+ combined.id = event.event;
245
+ };
246
+ var req = new XMLHttpRequest();
247
+ req.client = this.client;
248
+ req.json = combined;
249
+ req.callback = callback;
250
+ // if(!req.callback) req.callback = this.failed
251
+ req.onreadystatechange = function() {
252
+ if (this.readyState != 4) {
253
+ return;
245
254
  }
246
- req.open("POST", this.url, true);
247
- req.setRequestHeader("Content-type", "application/json");
248
- try {
249
- req.send(JSON.stringify(combined));
250
- } catch (err) {
251
- callback(event);
255
+ if (this.status == 200) {
256
+ try {
257
+ var res = JSON.parse(this.responseText);
258
+ this.client.___dispatch(res);
259
+ } catch (err) {
260
+ console.error(
261
+ "PleziClient experienced an error parsing the following data (not JSON):",
262
+ err, this.responseText);
263
+ }
264
+
265
+ } else {
266
+ if (this.callback) {
267
+ this.callback(this.json);
268
+ }
252
269
  }
270
+ };
271
+ req.open("POST", this.url, true);
272
+ req.setRequestHeader("Content-type", "application/json");
273
+ try {
274
+ req.send(JSON.stringify(combined));
275
+ } catch (err) {
276
+ callback(event);
277
+ }
253
278
  }