mirror of
https://github.com/Hopiu/postal.js.git
synced 2026-03-16 22:20:23 +00:00
Set up node and browser build scripts. Node output has NOT been tested. Added unit tests, all kinds of refactoring to core engine.
This commit is contained in:
parent
e860d8700b
commit
8a963ab322
21 changed files with 887 additions and 284 deletions
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
exports.Postal = MessageBroker;
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
src/languageExtensions.js
|
||||
src/CapturedMessageBatch.js
|
||||
src/misc.js
|
||||
src/MessageCaptor.js
|
||||
src/ReplayContext.js
|
||||
src/Postal.js
|
||||
4
build/SourceManifest-node.txt
Normal file
4
build/SourceManifest-node.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
src/misc.js
|
||||
src/MessageCaptor.js
|
||||
src/ReplayContext.js
|
||||
src/Postal.js
|
||||
11
build/boilerplate/browser_footer.txt
Normal file
11
build/boilerplate/browser_footer.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
var postal = global.postal = new Postal();
|
||||
|
||||
postal.DEFAULT_EXCHANGE = DEFAULT_EXCHANGE;
|
||||
postal.SYSTEM_EXCHANGE = SYSTEM_EXCHANGE;
|
||||
postal.NORMAL_MODE = NORMAL_MODE;
|
||||
postal.CAPTURE_MODE = CAPTURE_MODE;
|
||||
postal.REPLAY_MODE = REPLAY_MODE;
|
||||
postal.POSTAL_MSG_STORE_KEY = POSTAL_MSG_STORE_KEY;
|
||||
|
||||
})(window);
|
||||
2
build/boilerplate/browser_header.txt
Normal file
2
build/boilerplate/browser_header.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(function(global, undefined) {
|
||||
|
||||
11
build/boilerplate/node_footer.txt
Normal file
11
build/boilerplate/node_footer.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
var postal = new Postal();
|
||||
|
||||
postal.DEFAULT_EXCHANGE = DEFAULT_EXCHANGE;
|
||||
postal.SYSTEM_EXCHANGE = SYSTEM_EXCHANGE;
|
||||
postal.NORMAL_MODE = NORMAL_MODE;
|
||||
postal.CAPTURE_MODE = CAPTURE_MODE;
|
||||
postal.REPLAY_MODE = REPLAY_MODE;
|
||||
postal.POSTAL_MSG_STORE_KEY = POSTAL_MSG_STORE_KEY;
|
||||
|
||||
exports.postal = postal;
|
||||
4
build/build-all.sh
Executable file
4
build/build-all.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
./linux-build-node.sh
|
||||
./linux-build-browser.sh
|
||||
14
build/linux-build-browser.sh
Executable file
14
build/linux-build-browser.sh
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
|
||||
OutFile='output/browser/postal.js'
|
||||
|
||||
cp version-header.js $OutFile
|
||||
|
||||
cat ./boilerplate/browser_header.txt >> $OutFile
|
||||
|
||||
# Combine the source files
|
||||
while read line; do
|
||||
cat ../$line >> $OutFile
|
||||
done < SourceManifest-browser.txt
|
||||
|
||||
cat ./boilerplate/browser_footer.txt >> $OutFile
|
||||
|
|
@ -7,6 +7,6 @@ cp version-header.js $OutFile
|
|||
# Combine the source files
|
||||
while read line; do
|
||||
cat ../$line >> $OutFile
|
||||
done < SourceManifest.txt
|
||||
done < SourceManifest-node.txt
|
||||
|
||||
cat NodeExports.js >> $OutFile
|
||||
cat ./boilerplate/node_footer.txt >> $OutFile
|
||||
375
build/output/browser/postal.js
Normal file
375
build/output/browser/postal.js
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
postal.js
|
||||
Author: Jim Cowart
|
||||
License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
|
||||
Version 0.0.1
|
||||
*/
|
||||
|
||||
(function(global, undefined) {
|
||||
|
||||
var isArray = function(value) {
|
||||
var s = typeof value;
|
||||
if (s === 'object') {
|
||||
if (value) {
|
||||
if (typeof value.length === 'number' &&
|
||||
!(value.propertyIsEnumerable('length')) &&
|
||||
typeof value.splice === 'function') {
|
||||
s = 'array';
|
||||
}
|
||||
}
|
||||
}
|
||||
return s === 'array';
|
||||
},
|
||||
slice = [].slice,
|
||||
DEFAULT_EXCHANGE = "/",
|
||||
SYSTEM_EXCHANGE = "postal",
|
||||
NORMAL_MODE = "Normal",
|
||||
CAPTURE_MODE = "Capture",
|
||||
REPLAY_MODE = "Replay",
|
||||
POSTAL_MSG_STORE_KEY = "postal.captured",
|
||||
_forEachKeyValue = function(object, callback) {
|
||||
for(var x in object) {
|
||||
if(object.hasOwnProperty(x)) {
|
||||
callback(x, object[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var MessageCaptor = function(plugUp, unPlug) {
|
||||
var _grabMsg = function(data) {
|
||||
// We need to ignore system messages, since they could involve captures, replays, etc.
|
||||
if(data.exchange !== SYSTEM_EXCHANGE) {
|
||||
this.messages.push(data);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
plugUp(_grabMsg);
|
||||
|
||||
this.messages = [];
|
||||
|
||||
this.save = function(batchId, description) {
|
||||
unPlug(_grabMsg);
|
||||
var captureStore = amplify.store(POSTAL_MSG_STORE_KEY);
|
||||
if(!captureStore) {
|
||||
captureStore = {};
|
||||
}
|
||||
captureStore[batchId] = {
|
||||
batchId: batchId,
|
||||
description: description,
|
||||
messages: this.messages
|
||||
};
|
||||
amplify.store(POSTAL_MSG_STORE_KEY, captureStore);
|
||||
};
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "captor.save", function(data) {
|
||||
this.save(data.batchId || new Date().toString(),
|
||||
data.description || "Captured Message Batch");
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
var ReplayContext = function (publish, subscribe) {
|
||||
var _batch,
|
||||
_continue = true,
|
||||
_loadMessages = function(batchId) {
|
||||
var msgStore = amplify.store(POSTAL_MSG_STORE_KEY),
|
||||
targetBatch = msgStore[batchId];
|
||||
if(targetBatch) {
|
||||
targetBatch.messages.forEach(function(msg) {
|
||||
msg.timeStamp = new Date(msg.timeStamp);
|
||||
});
|
||||
_batch = targetBatch;
|
||||
}
|
||||
},
|
||||
_replayImmediate = function() {
|
||||
while(_batch.messages.length > 0) {
|
||||
if(_continue) {
|
||||
_advanceNext();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
_advanceNext = function() {
|
||||
var msg = _batch.messages.shift();
|
||||
publish(msg.exchange, msg.topic, msg.data);
|
||||
},
|
||||
_replayRealTime = function() {
|
||||
if(_continue && _batch.messages.length > 0) {
|
||||
if(_batch.messages.length > 1) {
|
||||
var span = _batch.messages[1].timeStamp - _batch.messages[0].timeStamp;
|
||||
_advanceNext();
|
||||
setTimeout(_replayRealTime, span);
|
||||
}
|
||||
else {
|
||||
_advanceNext();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.load", function(data) {
|
||||
_continue = false;
|
||||
_loadMessages(data);
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.immediate", function() {
|
||||
_continue = true;
|
||||
_replayImmediate();
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.advanceNext", function() {
|
||||
_continue = true;
|
||||
_advanceNext();
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.realTime", function() {
|
||||
_continue = true;
|
||||
_replayRealTime();
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.stop", function() {
|
||||
_continue = false;
|
||||
});
|
||||
};
|
||||
|
||||
var Postal = function() {
|
||||
var _regexify = function(topic) {
|
||||
if(!this.cache[topic]) {
|
||||
this.cache[topic] = topic.replace(".", "\.").replace("*", ".*");
|
||||
}
|
||||
return this.cache[topic];
|
||||
}.bind(this),
|
||||
_isTopicMatch = function(topic, comparison) {
|
||||
if(!this.cache[topic + '_' + comparison]) {
|
||||
this.cache[topic + '_' + comparison] = topic === comparison ||
|
||||
(comparison.indexOf("*") !== -1 && topic.search(_regexify(comparison)) !== -1) ||
|
||||
(topic.indexOf("*") !== -1 && comparison.search(_regexify(topic)) !== -1);
|
||||
}
|
||||
return this.cache[topic + '_' + comparison];
|
||||
}.bind(this),
|
||||
_publish = function(exchange, topic, data) {
|
||||
this.wireTaps.forEach(function(tap) {
|
||||
tap({
|
||||
exchange: exchange,
|
||||
topic: topic,
|
||||
data: data,
|
||||
timeStamp: new Date()
|
||||
});
|
||||
});
|
||||
|
||||
_forEachKeyValue(this.subscriptions[exchange],function(subTpc, subs) {
|
||||
if(_isTopicMatch(topic, subTpc)) {
|
||||
subs.forEach(function(sub) {
|
||||
if(typeof sub.callback === 'function') {
|
||||
sub.callback(data);
|
||||
sub.onFired();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}.bind(this),
|
||||
_mode = NORMAL_MODE,
|
||||
_replayContext,
|
||||
_captor;
|
||||
|
||||
this.cache = {};
|
||||
|
||||
this.getMode = function() { return _mode; };
|
||||
|
||||
this.wireTaps = [];
|
||||
|
||||
this.subscriptions = {};
|
||||
|
||||
this.subscriptions[DEFAULT_EXCHANGE] = {};
|
||||
|
||||
/*
|
||||
options object has the following optional members:
|
||||
{
|
||||
once: {true || false (true indicates a fire-only-once subscription},
|
||||
priority: {integer value - lower value == higher priority},
|
||||
context: {the "this" context for the callback invocation}
|
||||
}
|
||||
*/
|
||||
this.subscribe = function(exchange, topic, callback, options) {
|
||||
var _args = slice.call(arguments, 0),
|
||||
_exchange,
|
||||
_topicList, // we allow multiple topics to be subscribed in one call.,
|
||||
_once = false,
|
||||
_subData = {
|
||||
callback: function() { /* placeholder noop */ },
|
||||
priority: 50,
|
||||
context: null,
|
||||
onFired: function() { /* noop */ }
|
||||
},
|
||||
_idx,
|
||||
_found;
|
||||
|
||||
if(_args.length === 2) { // expecting topic and callback
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_subData.callback = _args[1];
|
||||
}
|
||||
else if(_args.length === 3 && typeof _args[2] === 'function') { // expecting exchange, topic, callback
|
||||
_exchange = exchange;
|
||||
_topicList = _args[1].split(/\s/);
|
||||
_subData.callback = _args[2];
|
||||
}
|
||||
else if(_args.length === 3 && typeof _args[2] === 'object') { // expecting topic, callback and options
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_subData.callback = _args[1];
|
||||
_subData.priority = _args[2].priority ? _args[2].priority : 50;
|
||||
_subData.context = _args[2].context ? _args[2].context : null;
|
||||
_once = _args[2].once ? _args[2].once : false;
|
||||
}
|
||||
else {
|
||||
_exchange = exchange;
|
||||
_topicList = topic.split(/\s/);
|
||||
_subData.callback = callback;
|
||||
_subData.priority = options.priority ? options.priority : 50;
|
||||
_subData.context = options.context ? options.context : null;
|
||||
_once = options.once ? options.once : false;
|
||||
}
|
||||
|
||||
if(_once) {
|
||||
_subData.onFired = function() {
|
||||
this.unsubscribe.apply(this,[_exchange, _topicList.join(' '), _subData.callback]);
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
if(!this.subscriptions[_exchange]) {
|
||||
this.subscriptions[_exchange] = {};
|
||||
}
|
||||
|
||||
_topicList.forEach(function(tpc) {
|
||||
if(!this.subscriptions[_exchange][tpc]) {
|
||||
this.subscriptions[_exchange][tpc] = [_subData];
|
||||
}
|
||||
else {
|
||||
_idx = this.subscriptions[_exchange][tpc].length - 1;
|
||||
if(this.subscriptions[_exchange][tpc].filter(function(sub) { return sub === callback; }).length === 0) {
|
||||
for(; _idx >= 0; _idx--) {
|
||||
if(this.subscriptions[_exchange][tpc][_idx].priority <= _subData.priority) {
|
||||
this.subscriptions[_exchange][tpc].splice(_idx + 1, 0, _subData);
|
||||
_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!_found) {
|
||||
this.subscriptions[_exchange][tpc].unshift(_subData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
// return callback for un-subscribing...
|
||||
return function() {
|
||||
this.unsubscribe(_exchange, _topicList.join(' '), _subData.callback);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
this.unsubscribe = function(exchange, topic, callback) {
|
||||
var _args = slice.call(arguments,0),
|
||||
_exchange,
|
||||
_topicList, // we allow multiple topics to be unsubscribed in one call.
|
||||
_callback;
|
||||
|
||||
if(_args.length === 2) {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_callback = _args[1];
|
||||
}
|
||||
else if(_args.length === 3) {
|
||||
_exchange = exchange;
|
||||
_topicList = topic.split(/\s/);
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
_topicList.forEach(function(tpc) {
|
||||
if(this.subscriptions[_exchange][tpc]) {
|
||||
var _len = this.subscriptions[_exchange][tpc].length,
|
||||
_idx = 0;
|
||||
for ( ; _idx < _len; _idx++ ) {
|
||||
if (this.subscriptions[_exchange][tpc][_idx].callback === callback) {
|
||||
this.subscriptions[_exchange][tpc].splice( _idx, 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},this);
|
||||
};
|
||||
|
||||
this.publish = function(exchange, topic, data) {
|
||||
var _args = slice.call(arguments,0),
|
||||
_exchange,
|
||||
_topicList,
|
||||
_data;
|
||||
if(_args.length === 1) {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_data = {};
|
||||
}
|
||||
else if(_args.length === 2 && typeof _args[1] === 'object') {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_data = _args[1] || {};
|
||||
}
|
||||
else if(_args.length === 2) {
|
||||
_exchange = _args[0];
|
||||
_topicList = _args[1].split(/\s/);
|
||||
_data = {};
|
||||
}
|
||||
else {
|
||||
_exchange = exchange;
|
||||
_topicList = topic.split(/\s/);
|
||||
_data = data || {};
|
||||
}
|
||||
if(_mode !== REPLAY_MODE || (_mode === REPLAY_MODE && _exchange === SYSTEM_EXCHANGE)) {
|
||||
|
||||
_topicList.forEach(function(tpc){
|
||||
_publish(_exchange, tpc, _data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.subscribe(SYSTEM_EXCHANGE, "mode.set", function(data) {
|
||||
if(data.mode) {
|
||||
switch(data.mode) {
|
||||
case REPLAY_MODE:
|
||||
_mode = REPLAY_MODE;
|
||||
_replayContext = new ReplayContext(_publish.bind(this), this.subscribe.bind(this));
|
||||
_captor = undefined;
|
||||
break;
|
||||
case CAPTURE_MODE:
|
||||
_mode = CAPTURE_MODE;
|
||||
_captor = new MessageCaptor(function(callback){
|
||||
this.wireTaps.push(callback);
|
||||
}.bind(this),
|
||||
function(callback) {
|
||||
var idx = this.wireTaps.indexOf(callback);
|
||||
if(idx !== -1) {
|
||||
this.wireTaps.splice(idx,1);
|
||||
}
|
||||
}.bind(this));
|
||||
break;
|
||||
default:
|
||||
_mode = NORMAL_MODE;
|
||||
_replayContext = undefined;
|
||||
_captor = undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
var postal = global.postal = new Postal();
|
||||
|
||||
postal.DEFAULT_EXCHANGE = DEFAULT_EXCHANGE;
|
||||
postal.SYSTEM_EXCHANGE = SYSTEM_EXCHANGE;
|
||||
postal.NORMAL_MODE = NORMAL_MODE;
|
||||
postal.CAPTURE_MODE = CAPTURE_MODE;
|
||||
postal.REPLAY_MODE = REPLAY_MODE;
|
||||
postal.POSTAL_MSG_STORE_KEY = POSTAL_MSG_STORE_KEY;
|
||||
|
||||
})(window);
|
||||
|
|
@ -1,111 +1,373 @@
|
|||
// Postal.js
|
||||
// Author: Jim Cowart
|
||||
// License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
|
||||
// Version 0.0.1
|
||||
/*
|
||||
postal.js
|
||||
Author: Jim Cowart
|
||||
License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
|
||||
Version 0.0.1
|
||||
*/
|
||||
|
||||
if(!Object.prototype.forEach) {
|
||||
Object.prototype.forEach = function (callback) {
|
||||
var self = this;
|
||||
for(var x in self) {
|
||||
if(self.hasOwnProperty(x)) {
|
||||
callback(self[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if(!Object.prototype.forEachKeyValue) {
|
||||
Object.prototype.forEachKeyValue = function (callback) {
|
||||
var self = this;
|
||||
for(var x in self) {
|
||||
if(self.hasOwnProperty(x)) {
|
||||
callback(x, self[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function isArray(value) {
|
||||
var s = typeof value;
|
||||
if (s === 'object') {
|
||||
if (value) {
|
||||
if (typeof value.length === 'number' &&
|
||||
!(value.propertyIsEnumerable('length')) &&
|
||||
typeof value.splice === 'function') {
|
||||
s = 'array';
|
||||
}
|
||||
}
|
||||
}
|
||||
return s === 'array';
|
||||
}
|
||||
|
||||
var slice = [].slice;var MessageBroker = function() {
|
||||
var subscriptions = {},
|
||||
regexify = function(topic) {
|
||||
if(!this[topic]) {
|
||||
this[topic] = topic.replace(".", "\.").replace("*", ".*");
|
||||
}
|
||||
return this[topic];
|
||||
}.bind(this),
|
||||
isTopicMatch = function(topic, comparison) {
|
||||
if(!this[topic + '_' + comparison]) {
|
||||
this[topic + '_' + comparison] = topic === comparison ||
|
||||
(comparison.indexOf("*") !== -1 && topic.search(regexify(comparison)) !== -1) ||
|
||||
(topic.indexOf("*") !== -1 && comparison.search(regexify(topic)) !== -1);
|
||||
}
|
||||
return this[topic + '_' + comparison];
|
||||
}.bind(this);
|
||||
|
||||
this.subscribe = function(topic, callback) {
|
||||
var topicList = topic.split(/\s/), // we allow multiple topics to be subscribed in one call.
|
||||
subIdx = 0,
|
||||
exists;
|
||||
topicList.forEach(function(topic) {
|
||||
exists = false;
|
||||
if(!subscriptions[topic]) {
|
||||
subscriptions[topic] = [callback];
|
||||
}
|
||||
else {
|
||||
subscriptions[topic].forEach(function(sub) {
|
||||
if(subscriptions[topic][subIdx] === callback) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
if(!exists) {
|
||||
subscriptions[topic].push(callback);
|
||||
var isArray = function(value) {
|
||||
var s = typeof value;
|
||||
if (s === 'object') {
|
||||
if (value) {
|
||||
if (typeof value.length === 'number' &&
|
||||
!(value.propertyIsEnumerable('length')) &&
|
||||
typeof value.splice === 'function') {
|
||||
s = 'array';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return s === 'array';
|
||||
},
|
||||
slice = [].slice,
|
||||
DEFAULT_EXCHANGE = "/",
|
||||
SYSTEM_EXCHANGE = "postal",
|
||||
NORMAL_MODE = "Normal",
|
||||
CAPTURE_MODE = "Capture",
|
||||
REPLAY_MODE = "Replay",
|
||||
POSTAL_MSG_STORE_KEY = "postal.captured",
|
||||
_forEachKeyValue = function(object, callback) {
|
||||
for(var x in object) {
|
||||
if(object.hasOwnProperty(x)) {
|
||||
callback(x, object[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var MessageCaptor = function(plugUp, unPlug) {
|
||||
var _grabMsg = function(data) {
|
||||
// We need to ignore system messages, since they could involve captures, replays, etc.
|
||||
if(data.exchange !== SYSTEM_EXCHANGE) {
|
||||
this.messages.push(data);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
plugUp(_grabMsg);
|
||||
|
||||
this.messages = [];
|
||||
|
||||
this.save = function(batchId, description) {
|
||||
unPlug(_grabMsg);
|
||||
var captureStore = amplify.store(POSTAL_MSG_STORE_KEY);
|
||||
if(!captureStore) {
|
||||
captureStore = {};
|
||||
}
|
||||
captureStore[batchId] = {
|
||||
batchId: batchId,
|
||||
description: description,
|
||||
messages: this.messages
|
||||
};
|
||||
amplify.store(POSTAL_MSG_STORE_KEY, captureStore);
|
||||
};
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "captor.save", function(data) {
|
||||
this.save(data.batchId || new Date().toString(),
|
||||
data.description || "Captured Message Batch");
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
var ReplayContext = function (publish, subscribe) {
|
||||
var _batch,
|
||||
_continue = true,
|
||||
_loadMessages = function(batchId) {
|
||||
var msgStore = amplify.store(POSTAL_MSG_STORE_KEY),
|
||||
targetBatch = msgStore[batchId];
|
||||
if(targetBatch) {
|
||||
targetBatch.messages.forEach(function(msg) {
|
||||
msg.timeStamp = new Date(msg.timeStamp);
|
||||
});
|
||||
_batch = targetBatch;
|
||||
}
|
||||
},
|
||||
_replayImmediate = function() {
|
||||
while(_batch.messages.length > 0) {
|
||||
if(_continue) {
|
||||
_advanceNext();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
_advanceNext = function() {
|
||||
var msg = _batch.messages.shift();
|
||||
publish(msg.exchange, msg.topic, msg.data);
|
||||
},
|
||||
_replayRealTime = function() {
|
||||
if(_continue && _batch.messages.length > 0) {
|
||||
if(_batch.messages.length > 1) {
|
||||
var span = _batch.messages[1].timeStamp - _batch.messages[0].timeStamp;
|
||||
_advanceNext();
|
||||
setTimeout(_replayRealTime, span);
|
||||
}
|
||||
else {
|
||||
_advanceNext();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.load", function(data) {
|
||||
_continue = false;
|
||||
_loadMessages(data);
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.immediate", function() {
|
||||
_continue = true;
|
||||
_replayImmediate();
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.advanceNext", function() {
|
||||
_continue = true;
|
||||
_advanceNext();
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.realTime", function() {
|
||||
_continue = true;
|
||||
_replayRealTime();
|
||||
});
|
||||
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.stop", function() {
|
||||
_continue = false;
|
||||
});
|
||||
};
|
||||
|
||||
var Postal = function() {
|
||||
var _regexify = function(topic) {
|
||||
if(!this.cache[topic]) {
|
||||
this.cache[topic] = topic.replace(".", "\.").replace("*", ".*");
|
||||
}
|
||||
return this.cache[topic];
|
||||
}.bind(this),
|
||||
_isTopicMatch = function(topic, comparison) {
|
||||
if(!this.cache[topic + '_' + comparison]) {
|
||||
this.cache[topic + '_' + comparison] = topic === comparison ||
|
||||
(comparison.indexOf("*") !== -1 && topic.search(_regexify(comparison)) !== -1) ||
|
||||
(topic.indexOf("*") !== -1 && comparison.search(_regexify(topic)) !== -1);
|
||||
}
|
||||
return this.cache[topic + '_' + comparison];
|
||||
}.bind(this),
|
||||
_publish = function(exchange, topic, data) {
|
||||
this.wireTaps.forEach(function(tap) {
|
||||
tap({
|
||||
exchange: exchange,
|
||||
topic: topic,
|
||||
data: data,
|
||||
timeStamp: new Date()
|
||||
});
|
||||
});
|
||||
|
||||
_forEachKeyValue(this.subscriptions[exchange],function(subTpc, subs) {
|
||||
if(_isTopicMatch(topic, subTpc)) {
|
||||
subs.forEach(function(sub) {
|
||||
if(typeof sub.callback === 'function') {
|
||||
sub.callback(data);
|
||||
sub.onFired();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}.bind(this),
|
||||
_mode = NORMAL_MODE,
|
||||
_replayContext,
|
||||
_captor;
|
||||
|
||||
this.cache = {};
|
||||
|
||||
this.getMode = function() { return _mode; };
|
||||
|
||||
this.wireTaps = [];
|
||||
|
||||
this.subscriptions = {};
|
||||
|
||||
this.subscriptions[DEFAULT_EXCHANGE] = {};
|
||||
|
||||
/*
|
||||
options object has the following optional members:
|
||||
{
|
||||
once: {true || false (true indicates a fire-only-once subscription},
|
||||
priority: {integer value - lower value == higher priority},
|
||||
context: {the "this" context for the callback invocation}
|
||||
}
|
||||
*/
|
||||
this.subscribe = function(exchange, topic, callback, options) {
|
||||
var _args = slice.call(arguments, 0),
|
||||
_exchange,
|
||||
_topicList, // we allow multiple topics to be subscribed in one call.,
|
||||
_once = false,
|
||||
_subData = {
|
||||
callback: function() { /* placeholder noop */ },
|
||||
priority: 50,
|
||||
context: null,
|
||||
onFired: function() { /* noop */ }
|
||||
},
|
||||
_idx,
|
||||
_found;
|
||||
|
||||
if(_args.length === 2) { // expecting topic and callback
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_subData.callback = _args[1];
|
||||
}
|
||||
else if(_args.length === 3 && typeof _args[2] === 'function') { // expecting exchange, topic, callback
|
||||
_exchange = exchange;
|
||||
_topicList = _args[1].split(/\s/);
|
||||
_subData.callback = _args[2];
|
||||
}
|
||||
else if(_args.length === 3 && typeof _args[2] === 'object') { // expecting topic, callback and options
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_subData.callback = _args[1];
|
||||
_subData.priority = _args[2].priority ? _args[2].priority : 50;
|
||||
_subData.context = _args[2].context ? _args[2].context : null;
|
||||
_once = _args[2].once ? _args[2].once : false;
|
||||
}
|
||||
else {
|
||||
_exchange = exchange;
|
||||
_topicList = topic.split(/\s/);
|
||||
_subData.callback = callback;
|
||||
_subData.priority = options.priority ? options.priority : 50;
|
||||
_subData.context = options.context ? options.context : null;
|
||||
_once = options.once ? options.once : false;
|
||||
}
|
||||
|
||||
if(_once) {
|
||||
_subData.onFired = function() {
|
||||
this.unsubscribe.apply(this,[_exchange, _topicList.join(' '), _subData.callback]);
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
if(!this.subscriptions[_exchange]) {
|
||||
this.subscriptions[_exchange] = {};
|
||||
}
|
||||
|
||||
_topicList.forEach(function(tpc) {
|
||||
if(!this.subscriptions[_exchange][tpc]) {
|
||||
this.subscriptions[_exchange][tpc] = [_subData];
|
||||
}
|
||||
else {
|
||||
_idx = this.subscriptions[_exchange][tpc].length - 1;
|
||||
if(this.subscriptions[_exchange][tpc].filter(function(sub) { return sub === callback; }).length === 0) {
|
||||
for(; _idx >= 0; _idx--) {
|
||||
if(this.subscriptions[_exchange][tpc][_idx].priority <= _subData.priority) {
|
||||
this.subscriptions[_exchange][tpc].splice(_idx + 1, 0, _subData);
|
||||
_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!_found) {
|
||||
this.subscriptions[_exchange][tpc].unshift(_subData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
// return callback for un-subscribing...
|
||||
return function() {
|
||||
this.unsubscribe(topic, callback);
|
||||
this.unsubscribe(_exchange, _topicList.join(' '), _subData.callback);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
this.publish = function(topic, data) {
|
||||
subscriptions.forEachKeyValue(function(subNm, subs) {
|
||||
if(isTopicMatch(topic, subNm)) {
|
||||
subs.forEach(function(callback) {
|
||||
if(typeof callback === 'function') {
|
||||
callback(data);
|
||||
this.unsubscribe = function(exchange, topic, callback) {
|
||||
var _args = slice.call(arguments,0),
|
||||
_exchange,
|
||||
_topicList, // we allow multiple topics to be unsubscribed in one call.
|
||||
_callback;
|
||||
|
||||
if(_args.length === 2) {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_callback = _args[1];
|
||||
}
|
||||
else if(_args.length === 3) {
|
||||
_exchange = exchange;
|
||||
_topicList = topic.split(/\s/);
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
_topicList.forEach(function(tpc) {
|
||||
if(this.subscriptions[_exchange][tpc]) {
|
||||
var _len = this.subscriptions[_exchange][tpc].length,
|
||||
_idx = 0;
|
||||
for ( ; _idx < _len; _idx++ ) {
|
||||
if (this.subscriptions[_exchange][tpc][_idx].callback === callback) {
|
||||
this.subscriptions[_exchange][tpc].splice( _idx, 1 );
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},this);
|
||||
};
|
||||
|
||||
this.unsubscribe = function(topic, callback) {
|
||||
if ( !subscriptions[ topic ] ) {
|
||||
return;
|
||||
this.publish = function(exchange, topic, data) {
|
||||
var _args = slice.call(arguments,0),
|
||||
_exchange,
|
||||
_topicList,
|
||||
_data;
|
||||
if(_args.length === 1) {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_data = {};
|
||||
}
|
||||
var length = subscriptions[ topic ].length,
|
||||
idx = 0;
|
||||
for ( ; idx < length; idx++ ) {
|
||||
if (subscriptions[topic][idx] === callback) {
|
||||
subscriptions[topic].splice( idx, 1 );
|
||||
else if(_args.length === 2 && typeof _args[1] === 'object') {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_data = _args[1] || {};
|
||||
}
|
||||
else if(_args.length === 2) {
|
||||
_exchange = _args[0];
|
||||
_topicList = _args[1].split(/\s/);
|
||||
_data = {};
|
||||
}
|
||||
else {
|
||||
_exchange = exchange;
|
||||
_topicList = topic.split(/\s/);
|
||||
_data = data || {};
|
||||
}
|
||||
if(_mode !== REPLAY_MODE || (_mode === REPLAY_MODE && _exchange === SYSTEM_EXCHANGE)) {
|
||||
|
||||
_topicList.forEach(function(tpc){
|
||||
_publish(_exchange, tpc, _data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.subscribe(SYSTEM_EXCHANGE, "mode.set", function(data) {
|
||||
if(data.mode) {
|
||||
switch(data.mode) {
|
||||
case REPLAY_MODE:
|
||||
_mode = REPLAY_MODE;
|
||||
_replayContext = new ReplayContext(_publish.bind(this), this.subscribe.bind(this));
|
||||
_captor = undefined;
|
||||
break;
|
||||
case CAPTURE_MODE:
|
||||
_mode = CAPTURE_MODE;
|
||||
_captor = new MessageCaptor(function(callback){
|
||||
this.wireTaps.push(callback);
|
||||
}.bind(this),
|
||||
function(callback) {
|
||||
var idx = this.wireTaps.indexOf(callback);
|
||||
if(idx !== -1) {
|
||||
this.wireTaps.splice(idx,1);
|
||||
}
|
||||
}.bind(this));
|
||||
break;
|
||||
default:
|
||||
_mode = NORMAL_MODE;
|
||||
_replayContext = undefined;
|
||||
_captor = undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}.bind(this));
|
||||
};
|
||||
exports.Postal = MessageBroker;
|
||||
|
||||
|
||||
var postal = new Postal();
|
||||
|
||||
postal.DEFAULT_EXCHANGE = DEFAULT_EXCHANGE;
|
||||
postal.SYSTEM_EXCHANGE = SYSTEM_EXCHANGE;
|
||||
postal.NORMAL_MODE = NORMAL_MODE;
|
||||
postal.CAPTURE_MODE = CAPTURE_MODE;
|
||||
postal.REPLAY_MODE = REPLAY_MODE;
|
||||
postal.POSTAL_MSG_STORE_KEY = POSTAL_MSG_STORE_KEY;
|
||||
|
||||
exports.postal = postal;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
simplifyDebugCallback([
|
||||
'src/languageExtensions.js',
|
||||
'src/broker.js',
|
||||
]);
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
// Postal.js
|
||||
// Author: Jim Cowart
|
||||
// License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
|
||||
// Version 0.0.1
|
||||
/*
|
||||
postal.js
|
||||
Author: Jim Cowart
|
||||
License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
|
||||
Version 0.0.1
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -6,16 +6,17 @@
|
|||
<script type="text/javascript" src="../lib/pavlov.js"></script>
|
||||
<script type="text/javascript" src="../lib/amplify.core.js"></script>
|
||||
<script type="text/javascript" src="../lib/amplify.store.js"></script>
|
||||
<script type="text/javascript" src="../src/languageExtensions.js"></script>
|
||||
<script type="text/javascript" src="../src/misc.js"></script>
|
||||
<script type="text/javascript" src="../src/Postal.js"></script>
|
||||
<script type="text/javascript" src="../src/ReplayContext.js"></script>
|
||||
<script type="text/javascript" src="../src/CapturedMessageBatch.js"></script>
|
||||
<script type="text/javascript" src="../src/MessageCaptor.js"></script>
|
||||
<script type="text/javascript">
|
||||
var postal = new Postal();
|
||||
</script>
|
||||
<script type="text/javascript" src="broker.spec.js"></script>
|
||||
<link rel="stylesheet" href="../lib/qunit.css" type="text/css" media="screen" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1 id="qunit-header"></h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
var CapturedMessageBatch = function(batchId, description, messages) {
|
||||
this.batchId = "";
|
||||
this.description = description || "Captured Message Batch";
|
||||
this.messages = messages || [];
|
||||
};
|
||||
|
|
@ -16,7 +16,11 @@ var MessageCaptor = function(plugUp, unPlug) {
|
|||
if(!captureStore) {
|
||||
captureStore = {};
|
||||
}
|
||||
captureStore[batchId] = new CapturedMessageBatch(batchId, description, this.messages);
|
||||
captureStore[batchId] = {
|
||||
batchId: batchId,
|
||||
description: description,
|
||||
messages: this.messages
|
||||
};
|
||||
amplify.store(POSTAL_MSG_STORE_KEY, captureStore);
|
||||
};
|
||||
|
||||
|
|
@ -24,4 +28,5 @@ var MessageCaptor = function(plugUp, unPlug) {
|
|||
this.save(data.batchId || new Date().toString(),
|
||||
data.description || "Captured Message Batch");
|
||||
}.bind(this));
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,45 @@
|
|||
var DEFAULT_EXCHANGE = "/",
|
||||
SYSTEM_EXCHANGE = "postal",
|
||||
NORMAL_MODE = "Normal",
|
||||
CAPTURE_MODE = "Capture",
|
||||
REPLAY_MODE = "Replay",
|
||||
POSTAL_MSG_STORE_KEY = "postal.captured",
|
||||
_forEachKeyValue = function(object, callback) {
|
||||
for(var x in object) {
|
||||
if(object.hasOwnProperty(x)) {
|
||||
callback(x, object[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var Postal = function() {
|
||||
var _regexify = function(topic) {
|
||||
if(!this[topic]) {
|
||||
this[topic] = topic.replace(".", "\.").replace("*", ".*");
|
||||
if(!this.cache[topic]) {
|
||||
this.cache[topic] = topic.replace(".", "\.").replace("*", ".*");
|
||||
}
|
||||
return this[topic];
|
||||
return this.cache[topic];
|
||||
}.bind(this),
|
||||
_isTopicMatch = function(topic, comparison) {
|
||||
if(!this[topic + '_' + comparison]) {
|
||||
this[topic + '_' + comparison] = topic === comparison ||
|
||||
if(!this.cache[topic + '_' + comparison]) {
|
||||
this.cache[topic + '_' + comparison] = topic === comparison ||
|
||||
(comparison.indexOf("*") !== -1 && topic.search(_regexify(comparison)) !== -1) ||
|
||||
(topic.indexOf("*") !== -1 && comparison.search(_regexify(topic)) !== -1);
|
||||
}
|
||||
return this[topic + '_' + comparison];
|
||||
return this.cache[topic + '_' + comparison];
|
||||
}.bind(this),
|
||||
_publish = function(exchange, topic, data) {
|
||||
this.wireTaps.forEach(function(tap) {
|
||||
tap({
|
||||
exchange: exchange,
|
||||
topic: topic,
|
||||
data: data,
|
||||
timeStamp: new Date()
|
||||
});
|
||||
});
|
||||
|
||||
_forEachKeyValue(this.subscriptions[exchange],function(subTpc, subs) {
|
||||
if(_isTopicMatch(topic, subTpc)) {
|
||||
subs.forEach(function(sub) {
|
||||
if(typeof sub.callback === 'function') {
|
||||
sub.callback(data);
|
||||
sub.onFired();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}.bind(this),
|
||||
_mode = NORMAL_MODE,
|
||||
_replayContext,
|
||||
_captor;
|
||||
|
||||
this.cache = {};
|
||||
|
||||
this.getMode = function() { return _mode; };
|
||||
|
||||
this.wireTaps = [];
|
||||
|
|
@ -161,11 +170,21 @@ var Postal = function() {
|
|||
_exchange,
|
||||
_topicList,
|
||||
_data;
|
||||
if(_args.length == 2) {
|
||||
if(_args.length === 1) {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_data = {};
|
||||
}
|
||||
else if(_args.length === 2 && typeof _args[1] === 'object') {
|
||||
_exchange = DEFAULT_EXCHANGE;
|
||||
_topicList = _args[0].split(/\s/);
|
||||
_data = _args[1] || {};
|
||||
}
|
||||
else if(_args.length === 2) {
|
||||
_exchange = _args[0];
|
||||
_topicList = _args[1].split(/\s/);
|
||||
_data = {};
|
||||
}
|
||||
else {
|
||||
_exchange = exchange;
|
||||
_topicList = topic.split(/\s/);
|
||||
|
|
@ -174,26 +193,8 @@ var Postal = function() {
|
|||
if(_mode !== REPLAY_MODE || (_mode === REPLAY_MODE && _exchange === SYSTEM_EXCHANGE)) {
|
||||
|
||||
_topicList.forEach(function(tpc){
|
||||
this.wireTaps.forEach(function(tap) {
|
||||
tap({
|
||||
exchange: _exchange,
|
||||
topic: tpc,
|
||||
data: _data,
|
||||
timeStamp: new Date()
|
||||
});
|
||||
});
|
||||
|
||||
_forEachKeyValue(this.subscriptions[_exchange],function(subTpc, subs) {
|
||||
if(_isTopicMatch(tpc, subTpc)) {
|
||||
subs.map(function(sub) { return sub.callback; })
|
||||
.forEach(function(callback) {
|
||||
if(typeof callback === 'function') {
|
||||
callback(_data);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
_publish(_exchange, tpc, _data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -202,7 +203,7 @@ var Postal = function() {
|
|||
switch(data.mode) {
|
||||
case REPLAY_MODE:
|
||||
_mode = REPLAY_MODE;
|
||||
_replayContext = new ReplayContext(this.publish.bind(this), this.subscribe.bind(this));
|
||||
_replayContext = new ReplayContext(_publish.bind(this), this.subscribe.bind(this));
|
||||
_captor = undefined;
|
||||
break;
|
||||
case CAPTURE_MODE:
|
||||
|
|
@ -227,5 +228,3 @@ var Postal = function() {
|
|||
}.bind(this));
|
||||
};
|
||||
|
||||
var postal = new Postal();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ var ReplayContext = function (publish, subscribe) {
|
|||
var msgStore = amplify.store(POSTAL_MSG_STORE_KEY),
|
||||
targetBatch = msgStore[batchId];
|
||||
if(targetBatch) {
|
||||
targetBatch.messages.forEach(function(msg) {
|
||||
msg.timeStamp = new Date(msg.timeStamp);
|
||||
});
|
||||
_batch = targetBatch;
|
||||
}
|
||||
},
|
||||
|
|
@ -23,39 +26,40 @@ var ReplayContext = function (publish, subscribe) {
|
|||
publish(msg.exchange, msg.topic, msg.data);
|
||||
},
|
||||
_replayRealTime = function() {
|
||||
var lastTime = _batch.messages[0].timeStamp;
|
||||
while(_batch.messages.length > 0) {
|
||||
if(_continue) {
|
||||
_advanceNext();
|
||||
setTimeout(publish(SYSTEM_EXCHANGE, "replay.realTime"), _batch.messages[0].timeStamp - lastTime);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
if(_continue && _batch.messages.length > 0) {
|
||||
if(_batch.messages.length > 1) {
|
||||
var span = _batch.messages[1].timeStamp - _batch.messages[0].timeStamp;
|
||||
_advanceNext();
|
||||
setTimeout(_replayRealTime, span);
|
||||
}
|
||||
else {
|
||||
_advanceNext();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
subscribe(SYSTEM_EXCHANGE, "replay.load", function(data) {
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.load", function(data) {
|
||||
_continue = false;
|
||||
_loadMessages(data);
|
||||
});
|
||||
|
||||
subscribe(SYSTEM_EXCHANGE, "replay.immediate", function() {
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.immediate", function() {
|
||||
_continue = true;
|
||||
_replayImmediate();
|
||||
});
|
||||
|
||||
subscribe(SYSTEM_EXCHANGE, "replay.advanceNext", function() {
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.advanceNext", function() {
|
||||
_continue = true;
|
||||
_advanceNext();
|
||||
});
|
||||
|
||||
subscribe(SYSTEM_EXCHANGE, "replay.realTime", function() {
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.realTime", function() {
|
||||
_continue = true;
|
||||
_replayRealTime();
|
||||
});
|
||||
|
||||
subscribe(SYSTEM_EXCHANGE, "replay.stop", function() {
|
||||
postal.subscribe(SYSTEM_EXCHANGE, "replay.stop", function() {
|
||||
_continue = false;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
var MessageBroker = function() {
|
||||
var subscriptions = {},
|
||||
regexify = function(topic) {
|
||||
if(!this[topic]) {
|
||||
this[topic] = topic.replace(".", "\.").replace("*", ".*");
|
||||
}
|
||||
return this[topic];
|
||||
}.bind(this),
|
||||
isTopicMatch = function(topic, comparison) {
|
||||
if(!this[topic + '_' + comparison]) {
|
||||
this[topic + '_' + comparison] = topic === comparison ||
|
||||
(comparison.indexOf("*") !== -1 && topic.search(regexify(comparison)) !== -1) ||
|
||||
(topic.indexOf("*") !== -1 && comparison.search(regexify(topic)) !== -1);
|
||||
}
|
||||
return this[topic + '_' + comparison];
|
||||
}.bind(this);
|
||||
|
||||
this.subscribe = function(topic, callback) {
|
||||
var topicList = topic.split(/\s/), // we allow multiple topics to be subscribed in one call.
|
||||
subIdx = 0,
|
||||
exists;
|
||||
topicList.forEach(function(topic) {
|
||||
exists = false;
|
||||
if(!subscriptions[topic]) {
|
||||
subscriptions[topic] = [callback];
|
||||
}
|
||||
else {
|
||||
subscriptions[topic].forEach(function(sub) {
|
||||
if(subscriptions[topic][subIdx] === callback) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
if(!exists) {
|
||||
subscriptions[topic].push(callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
// return callback for un-subscribing...
|
||||
return function() {
|
||||
this.unsubscribe(topic, callback);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
this.publish = function(topic, data) {
|
||||
subscriptions.forEachKeyValue(function(subNm, subs) {
|
||||
if(isTopicMatch(topic, subNm)) {
|
||||
subs.forEach(function(callback) {
|
||||
if(typeof callback === 'function') {
|
||||
callback(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.unsubscribe = function(topic, callback) {
|
||||
if ( !subscriptions[ topic ] ) {
|
||||
return;
|
||||
}
|
||||
var length = subscriptions[ topic ].length,
|
||||
idx = 0;
|
||||
for ( ; idx < length; idx++ ) {
|
||||
if (subscriptions[topic][idx] === callback) {
|
||||
subscriptions[topic].splice( idx, 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*if(!Object.prototype.forEach) {
|
||||
Object.prototype.forEach = function (callback) {
|
||||
var self = this;
|
||||
for(var x in self) {
|
||||
if(self.hasOwnProperty(x)) {
|
||||
callback(self[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if(!Object.prototype.forEachKeyValue) {
|
||||
Object.prototype.forEachKeyValue = function (callback) {
|
||||
var self = this;
|
||||
for(var x in self) {
|
||||
if(self.hasOwnProperty(x)) {
|
||||
callback(x, self[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
||||
var isArray = function(value) {
|
||||
var s = typeof value;
|
||||
if (s === 'object') {
|
||||
if (value) {
|
||||
if (typeof value.length === 'number' &&
|
||||
!(value.propertyIsEnumerable('length')) &&
|
||||
typeof value.splice === 'function') {
|
||||
s = 'array';
|
||||
}
|
||||
}
|
||||
}
|
||||
return s === 'array';
|
||||
};
|
||||
|
||||
var slice = [].slice;
|
||||
28
src/misc.js
Normal file
28
src/misc.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
var isArray = function(value) {
|
||||
var s = typeof value;
|
||||
if (s === 'object') {
|
||||
if (value) {
|
||||
if (typeof value.length === 'number' &&
|
||||
!(value.propertyIsEnumerable('length')) &&
|
||||
typeof value.splice === 'function') {
|
||||
s = 'array';
|
||||
}
|
||||
}
|
||||
}
|
||||
return s === 'array';
|
||||
},
|
||||
slice = [].slice,
|
||||
DEFAULT_EXCHANGE = "/",
|
||||
SYSTEM_EXCHANGE = "postal",
|
||||
NORMAL_MODE = "Normal",
|
||||
CAPTURE_MODE = "Capture",
|
||||
REPLAY_MODE = "Replay",
|
||||
POSTAL_MSG_STORE_KEY = "postal.captured",
|
||||
_forEachKeyValue = function(object, callback) {
|
||||
for(var x in object) {
|
||||
if(object.hasOwnProperty(x)) {
|
||||
callback(x, object[x]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
Reference in a new issue