mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 21:40:55 +01:00
Modify the Aphlict server to transmit messages instead of broadcasting them.
Summary: Ref T4324. Ref T5284. This adds server-side support for keeping track of a set of PHIDs that the Aphlict clients have subscribed to. Instead of broadcasting a notification to all clients (after which the clients can poll `/notification/individual` in order to determine whether or not they are interested in the notification), transmit notifications only to clients that have subscribed to a PHID that is relevant to the notification. Test Plan: I opened up two clients on the same host (incognito tabs in Chrome). Here is the output from the server: ``` > sudo ./bin/aphlict debug Starting Aphlict server in foreground... Launching server: $ 'nodejs' '/usr/src/phabricator/src/applications/aphlict/management/../../../../support/aphlict/server/aphlict_server.js' --port='22280' --admin='22281' --host='localhost' --user='aphlict' [Wed Jun 11 2014 19:10:27 GMT+0000 (UTC)] Started Server (PID 4546) [Wed Jun 11 2014 19:10:36 GMT+0000 (UTC)] <FlashPolicy> Policy Request From ::ffff:192.168.1.1 [Wed Jun 11 2014 19:10:37 GMT+0000 (UTC)] <Listener/1> Connected from ::ffff:192.168.1.1 [Wed Jun 11 2014 19:10:37 GMT+0000 (UTC)] <Listener/1> Received data: {"command":"subscribe","data":["PHID-USER-cb5af6p4oepy5tlgqypi"]} [Wed Jun 11 2014 19:10:37 GMT+0000 (UTC)] <Listener/1> Subscribed to: ["PHID-USER-cb5af6p4oepy5tlgqypi"] [Wed Jun 11 2014 19:10:39 GMT+0000 (UTC)] <Listener/1> Received data: {"command":"subscribe","data":["PHID-USER-kfohe3ca5oe6ygykmioq"]} [Wed Jun 11 2014 19:10:39 GMT+0000 (UTC)] <Listener/1> Subscribed to: ["PHID-USER-kfohe3ca5oe6ygykmioq"] [Wed Jun 11 2014 19:10:42 GMT+0000 (UTC)] notification: {"key":"6023751084283587681","type":"notification","subscribers":["PHID-USER-cb5af6p4oepy5tlgqypi"]} [Wed Jun 11 2014 19:10:42 GMT+0000 (UTC)] <Listener/1> Wrote Message ``` I verified (using the "Network" tab in Chrome) that an AJAX request to `/notification/individual/` was only made in the tab belonging to the user that triggered the test notification. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: epriestley, Korvin Maniphest Tasks: T5284, T4324 Differential Revision: https://secure.phabricator.com/D9458
This commit is contained in:
parent
82f889c421
commit
84d259cea2
10 changed files with 257 additions and 45 deletions
|
@ -8,7 +8,7 @@ return array(
|
||||||
'names' =>
|
'names' =>
|
||||||
array(
|
array(
|
||||||
'core.pkg.css' => 'd82d2f53',
|
'core.pkg.css' => 'd82d2f53',
|
||||||
'core.pkg.js' => '88ca2043',
|
'core.pkg.js' => '4af4aa9d',
|
||||||
'darkconsole.pkg.js' => 'ca8671ce',
|
'darkconsole.pkg.js' => 'ca8671ce',
|
||||||
'differential.pkg.css' => '4a93db37',
|
'differential.pkg.css' => '4a93db37',
|
||||||
'differential.pkg.js' => 'eca39a2c',
|
'differential.pkg.js' => 'eca39a2c',
|
||||||
|
@ -334,9 +334,9 @@ return array(
|
||||||
'rsrc/image/texture/table_header.png' => '5c433037',
|
'rsrc/image/texture/table_header.png' => '5c433037',
|
||||||
'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
|
'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
|
||||||
'rsrc/image/texture/table_header_tall.png' => 'd56b434f',
|
'rsrc/image/texture/table_header_tall.png' => 'd56b434f',
|
||||||
'rsrc/js/application/aphlict/Aphlict.js' => '493665ee',
|
'rsrc/js/application/aphlict/Aphlict.js' => '08be8878',
|
||||||
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '2a2dba85',
|
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '2a2dba85',
|
||||||
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => '027c888a',
|
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'acda9f51',
|
||||||
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
||||||
'rsrc/js/application/config/behavior-reorder-fields.js' => '938aed89',
|
'rsrc/js/application/config/behavior-reorder-fields.js' => '938aed89',
|
||||||
'rsrc/js/application/conpherence/behavior-menu.js' => '7ee23816',
|
'rsrc/js/application/conpherence/behavior-menu.js' => '7ee23816',
|
||||||
|
@ -477,7 +477,7 @@ return array(
|
||||||
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
|
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
|
||||||
'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4',
|
'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4',
|
||||||
'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca',
|
'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca',
|
||||||
'rsrc/swf/aphlict.swf' => 'f45c3edc',
|
'rsrc/swf/aphlict.swf' => 'd9bca85d',
|
||||||
),
|
),
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
array(
|
array(
|
||||||
|
@ -525,10 +525,10 @@ return array(
|
||||||
'herald-rule-editor' => '22d2966a',
|
'herald-rule-editor' => '22d2966a',
|
||||||
'herald-test-css' => '778b008e',
|
'herald-test-css' => '778b008e',
|
||||||
'inline-comment-summary-css' => '8cfd34e8',
|
'inline-comment-summary-css' => '8cfd34e8',
|
||||||
'javelin-aphlict' => '493665ee',
|
'javelin-aphlict' => '08be8878',
|
||||||
'javelin-behavior' => '8a3ed18b',
|
'javelin-behavior' => '8a3ed18b',
|
||||||
'javelin-behavior-aphlict-dropdown' => '2a2dba85',
|
'javelin-behavior-aphlict-dropdown' => '2a2dba85',
|
||||||
'javelin-behavior-aphlict-listen' => '027c888a',
|
'javelin-behavior-aphlict-listen' => 'acda9f51',
|
||||||
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
|
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
|
||||||
'javelin-behavior-aphront-crop' => 'b98fc918',
|
'javelin-behavior-aphront-crop' => 'b98fc918',
|
||||||
'javelin-behavior-aphront-drag-and-drop-textarea' => '4a11ea9c',
|
'javelin-behavior-aphront-drag-and-drop-textarea' => '4a11ea9c',
|
||||||
|
@ -819,18 +819,6 @@ return array(
|
||||||
4 => 'javelin-vector',
|
4 => 'javelin-vector',
|
||||||
5 => 'differential-inline-comment-editor',
|
5 => 'differential-inline-comment-editor',
|
||||||
),
|
),
|
||||||
'027c888a' =>
|
|
||||||
array(
|
|
||||||
0 => 'javelin-behavior',
|
|
||||||
1 => 'javelin-aphlict',
|
|
||||||
2 => 'javelin-stratcom',
|
|
||||||
3 => 'javelin-request',
|
|
||||||
4 => 'javelin-uri',
|
|
||||||
5 => 'javelin-dom',
|
|
||||||
6 => 'javelin-json',
|
|
||||||
7 => 'javelin-router',
|
|
||||||
8 => 'phabricator-notification',
|
|
||||||
),
|
|
||||||
'029a133d' =>
|
'029a133d' =>
|
||||||
array(
|
array(
|
||||||
0 => 'aphront-dialog-view-css',
|
0 => 'aphront-dialog-view-css',
|
||||||
|
@ -865,6 +853,11 @@ return array(
|
||||||
3 => 'javelin-vector',
|
3 => 'javelin-vector',
|
||||||
4 => 'javelin-stratcom',
|
4 => 'javelin-stratcom',
|
||||||
),
|
),
|
||||||
|
'08be8878' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-install',
|
||||||
|
1 => 'javelin-util',
|
||||||
|
),
|
||||||
'08e56a4e' =>
|
'08e56a4e' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-install',
|
0 => 'javelin-install',
|
||||||
|
@ -1153,11 +1146,6 @@ return array(
|
||||||
2 => 'javelin-stratcom',
|
2 => 'javelin-stratcom',
|
||||||
3 => 'phabricator-tooltip',
|
3 => 'phabricator-tooltip',
|
||||||
),
|
),
|
||||||
'493665ee' =>
|
|
||||||
array(
|
|
||||||
0 => 'javelin-install',
|
|
||||||
1 => 'javelin-util',
|
|
||||||
),
|
|
||||||
'4a11ea9c' =>
|
'4a11ea9c' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-behavior',
|
0 => 'javelin-behavior',
|
||||||
|
@ -1620,6 +1608,18 @@ return array(
|
||||||
1 => 'javelin-dom',
|
1 => 'javelin-dom',
|
||||||
2 => 'javelin-stratcom',
|
2 => 'javelin-stratcom',
|
||||||
),
|
),
|
||||||
|
'acda9f51' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-aphlict',
|
||||||
|
2 => 'javelin-stratcom',
|
||||||
|
3 => 'javelin-request',
|
||||||
|
4 => 'javelin-uri',
|
||||||
|
5 => 'javelin-dom',
|
||||||
|
6 => 'javelin-json',
|
||||||
|
7 => 'javelin-router',
|
||||||
|
8 => 'phabricator-notification',
|
||||||
|
),
|
||||||
'ad7a69ca' =>
|
'ad7a69ca' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-install',
|
0 => 'javelin-install',
|
||||||
|
|
|
@ -376,6 +376,12 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView {
|
||||||
$swf_uri = $response->getURI($map, 'rsrc/swf/aphlict.swf');
|
$swf_uri = $response->getURI($map, 'rsrc/swf/aphlict.swf');
|
||||||
|
|
||||||
$enable_debug = PhabricatorEnv::getEnvConfig('notification.debug');
|
$enable_debug = PhabricatorEnv::getEnvConfig('notification.debug');
|
||||||
|
|
||||||
|
$subscriptions = $this->pageObjects;
|
||||||
|
if ($user) {
|
||||||
|
$subscriptions[] = $user->getPHID();
|
||||||
|
}
|
||||||
|
|
||||||
Javelin::initBehavior(
|
Javelin::initBehavior(
|
||||||
'aphlict-listen',
|
'aphlict-listen',
|
||||||
array(
|
array(
|
||||||
|
@ -386,6 +392,7 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView {
|
||||||
'debug' => $enable_debug,
|
'debug' => $enable_debug,
|
||||||
'swfURI' => $swf_uri,
|
'swfURI' => $swf_uri,
|
||||||
'pageObjects' => array_fill_keys($this->pageObjects, true),
|
'pageObjects' => array_fill_keys($this->pageObjects, true),
|
||||||
|
'subscriptions' => $subscriptions,
|
||||||
));
|
));
|
||||||
|
|
||||||
$tail[] = phutil_tag(
|
$tail[] = phutil_tag(
|
||||||
|
|
|
@ -2,6 +2,7 @@ package {
|
||||||
|
|
||||||
import flash.events.TimerEvent;
|
import flash.events.TimerEvent;
|
||||||
import flash.external.ExternalInterface;
|
import flash.external.ExternalInterface;
|
||||||
|
import flash.utils.Dictionary;
|
||||||
import flash.utils.Timer;
|
import flash.utils.Timer;
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +44,11 @@ package {
|
||||||
{});
|
{});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function externalConnect(server:String, port:Number):void {
|
public function externalConnect(
|
||||||
|
server:String,
|
||||||
|
port:Number,
|
||||||
|
subscriptions:Array):void {
|
||||||
|
|
||||||
this.externalInvoke('connect');
|
this.externalInvoke('connect');
|
||||||
|
|
||||||
this.remoteServer = server;
|
this.remoteServer = server;
|
||||||
|
@ -56,6 +61,10 @@ package {
|
||||||
this.timer.addEventListener(TimerEvent.TIMER, this.keepalive);
|
this.timer.addEventListener(TimerEvent.TIMER, this.keepalive);
|
||||||
|
|
||||||
this.connectToMaster();
|
this.connectToMaster();
|
||||||
|
|
||||||
|
// Send subscriptions to master.
|
||||||
|
this.log('Sending subscriptions to master.');
|
||||||
|
this.send.send('aphlict_master', 'subscribe', this.client, subscriptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,6 +40,11 @@ package {
|
||||||
*/
|
*/
|
||||||
private var remotePort:Number;
|
private var remotePort:Number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dictionary mapping PHID to subscribed clients.
|
||||||
|
*/
|
||||||
|
private var subscriptions:Dictionary;
|
||||||
|
|
||||||
private var socket:Socket;
|
private var socket:Socket;
|
||||||
private var readBuffer:ByteArray;
|
private var readBuffer:ByteArray;
|
||||||
|
|
||||||
|
@ -50,12 +55,13 @@ package {
|
||||||
this.remoteServer = server;
|
this.remoteServer = server;
|
||||||
this.remotePort = port;
|
this.remotePort = port;
|
||||||
|
|
||||||
|
this.clients = new Dictionary();
|
||||||
|
this.subscriptions = new Dictionary();
|
||||||
|
|
||||||
// Connect to the Aphlict Server.
|
// Connect to the Aphlict Server.
|
||||||
this.recv.connect('aphlict_master');
|
this.recv.connect('aphlict_master');
|
||||||
this.connectToServer();
|
this.connectToServer();
|
||||||
|
|
||||||
this.clients = new Dictionary();
|
|
||||||
|
|
||||||
// Start a timer and regularly purge dead clients.
|
// Start a timer and regularly purge dead clients.
|
||||||
this.timer = new Timer(AphlictMaster.PURGE_INTERVAL);
|
this.timer = new Timer(AphlictMaster.PURGE_INTERVAL);
|
||||||
this.timer.addEventListener(TimerEvent.TIMER, this.purgeClients);
|
this.timer.addEventListener(TimerEvent.TIMER, this.purgeClients);
|
||||||
|
@ -116,6 +122,16 @@ package {
|
||||||
|
|
||||||
private function didConnectSocket(event:Event):void {
|
private function didConnectSocket(event:Event):void {
|
||||||
this.externalInvoke('connected');
|
this.externalInvoke('connected');
|
||||||
|
|
||||||
|
// Send subscriptions
|
||||||
|
var phids = new Array();
|
||||||
|
for (var phid:String in this.subscriptions) {
|
||||||
|
phids.push(phid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phids.length) {
|
||||||
|
this.sendSubscribeCommand(phids);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function didCloseSocket(event:Event):void {
|
private function didCloseSocket(event:Event):void {
|
||||||
|
@ -130,6 +146,69 @@ package {
|
||||||
this.externalInvoke('error', event.text);
|
this.externalInvoke('error', event.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function subscribe(client:String, phids:Array):void {
|
||||||
|
var newPHIDs = new Array();
|
||||||
|
|
||||||
|
for (var i:String in phids) {
|
||||||
|
var phid = phids[i];
|
||||||
|
if (!this.subscriptions[phid]) {
|
||||||
|
this.subscriptions[phid] = new Dictionary();
|
||||||
|
newPHIDs.push(phid);
|
||||||
|
}
|
||||||
|
this.subscriptions[phid][client] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPHIDs.length) {
|
||||||
|
this.sendSubscribeCommand(newPHIDs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unsubscribe(client:String, phids:Array):void {
|
||||||
|
var oldPHIDs = new Array();
|
||||||
|
|
||||||
|
for (var phid:String in phids) {
|
||||||
|
if (!this.subscriptions[phid]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete this.subscriptions[phid][client];
|
||||||
|
|
||||||
|
var empty = true;
|
||||||
|
for (var key:String in this.subscriptions[phid]) {
|
||||||
|
empty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
delete this.subscriptions[phid];
|
||||||
|
oldPHIDs.push(phid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldPHIDs.length) {
|
||||||
|
this.sendUnsubscribeCommand(oldPHIDs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendSubscribeCommand(phids:Array):void {
|
||||||
|
var msg:Dictionary = new Dictionary();
|
||||||
|
msg['command'] = 'subscribe';
|
||||||
|
msg['data'] = phids;
|
||||||
|
|
||||||
|
this.log('Sending subscribe command to server.');
|
||||||
|
this.socket.writeUTF(vegas.strings.JSON.serialize(msg));
|
||||||
|
this.socket.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendUnsubscribeCommand(phids:Array):void {
|
||||||
|
var msg:Dictionary = new Dictionary();
|
||||||
|
msg['command'] = 'unsubscribe';
|
||||||
|
msg['data'] = phids;
|
||||||
|
|
||||||
|
this.log('Sending subscribe command to server.');
|
||||||
|
this.socket.writeUTF(vegas.strings.JSON.serialize(msg));
|
||||||
|
this.socket.flush();
|
||||||
|
}
|
||||||
|
|
||||||
private function didReceiveSocket(event:Event):void {
|
private function didReceiveSocket(event:Event):void {
|
||||||
try {
|
try {
|
||||||
var b:ByteArray = this.readBuffer;
|
var b:ByteArray = this.readBuffer;
|
||||||
|
@ -153,9 +232,23 @@ package {
|
||||||
|
|
||||||
// Send the message to all clients.
|
// Send the message to all clients.
|
||||||
for (var client:String in this.clients) {
|
for (var client:String in this.clients) {
|
||||||
|
var subscribed = false;
|
||||||
|
|
||||||
|
for (var i:String in data.subscribers) {
|
||||||
|
var phid = data.subscribers[i];
|
||||||
|
|
||||||
|
if (this.subscriptions[phid] &&
|
||||||
|
this.subscriptions[phid][client]) {
|
||||||
|
subscribed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subscribed) {
|
||||||
this.log('Sending message to client: ' + client);
|
this.log('Sending message to client: ' + client);
|
||||||
this.send.send(client, 'receiveMessage', data);
|
this.send.send(client, 'receiveMessage', data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,61 @@ var send_server = net.createServer(function(socket) {
|
||||||
listener.getDescription(),
|
listener.getDescription(),
|
||||||
socket.remoteAddress);
|
socket.remoteAddress);
|
||||||
|
|
||||||
|
var buffer = new Buffer([]);
|
||||||
|
var length = 0;
|
||||||
|
|
||||||
|
socket.on('data', function(data) {
|
||||||
|
buffer = Buffer.concat([buffer, new Buffer(data)]);
|
||||||
|
|
||||||
|
while (buffer.length) {
|
||||||
|
if (!length) {
|
||||||
|
length = buffer.readUInt16BE(0);
|
||||||
|
buffer = buffer.slice(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer.length < length) {
|
||||||
|
// We need to wait for the rest of the data.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var message;
|
||||||
|
try {
|
||||||
|
message = JSON.parse(buffer.toString('utf8', 0, length));
|
||||||
|
} catch (err) {
|
||||||
|
debug.log('<%s> Received invalid data.', listener.getDescription());
|
||||||
|
continue;
|
||||||
|
} finally {
|
||||||
|
buffer = buffer.slice(length);
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.log('<%s> Received data: %s',
|
||||||
|
listener.getDescription(),
|
||||||
|
JSON.stringify(message));
|
||||||
|
|
||||||
|
switch (message.command) {
|
||||||
|
case 'subscribe':
|
||||||
|
debug.log(
|
||||||
|
'<%s> Subscribed to: %s',
|
||||||
|
listener.getDescription(),
|
||||||
|
JSON.stringify(message.data));
|
||||||
|
listener.subscribe(message.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'unsubscribe':
|
||||||
|
debug.log(
|
||||||
|
'<%s> Unsubscribed from: %s',
|
||||||
|
listener.getDescription(),
|
||||||
|
JSON.stringify(message.data));
|
||||||
|
listener.unsubscribe(message.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
debug.log('<s> Unrecognized command.', listener.getDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('close', function() {
|
socket.on('close', function() {
|
||||||
clients.removeListener(listener);
|
clients.removeListener(listener);
|
||||||
debug.log('<%s> Disconnected', listener.getDescription());
|
debug.log('<%s> Disconnected', listener.getDescription());
|
||||||
|
@ -122,7 +177,7 @@ var receive_server = http.createServer(function(request, response) {
|
||||||
|
|
||||||
debug.log('notification: ' + JSON.stringify(msg));
|
debug.log('notification: ' + JSON.stringify(msg));
|
||||||
++messages_in;
|
++messages_in;
|
||||||
broadcast(msg);
|
transmit(msg);
|
||||||
|
|
||||||
response.writeHead(200, {'Content-Type': 'text/plain'});
|
response.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -161,12 +216,16 @@ var receive_server = http.createServer(function(request, response) {
|
||||||
|
|
||||||
}).listen(config.admin, config.host);
|
}).listen(config.admin, config.host);
|
||||||
|
|
||||||
function broadcast(data) {
|
function transmit(msg) {
|
||||||
var listeners = clients.getListeners();
|
var listeners = clients.getListeners().filter(function(client) {
|
||||||
for (var id in listeners) {
|
return client.isSubscribedToAny(msg.subscribers);
|
||||||
var listener = listeners[id];
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < listeners.length; i++) {
|
||||||
|
var listener = listeners[i];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
listener.writeMessage(data);
|
listener.writeMessage(msg);
|
||||||
|
|
||||||
++messages_out;
|
++messages_out;
|
||||||
debug.log('<%s> Wrote Message', listener.getDescription());
|
debug.log('<%s> Wrote Message', listener.getDescription());
|
||||||
|
|
|
@ -9,11 +9,37 @@ JX.install('AphlictListener', {
|
||||||
members: {
|
members: {
|
||||||
_id: null,
|
_id: null,
|
||||||
_socket: null,
|
_socket: null,
|
||||||
|
_subscriptions: {},
|
||||||
|
|
||||||
getID: function() {
|
getID: function() {
|
||||||
return this._id;
|
return this._id;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
subscribe: function(phids) {
|
||||||
|
for (var i = 0; i < phids.length; i++) {
|
||||||
|
var phid = phids[i];
|
||||||
|
this._subscriptions[phid] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
unsubscribe: function(phids) {
|
||||||
|
for (var i = 0; i < phids.length; i++) {
|
||||||
|
var phid = phids[i];
|
||||||
|
delete this._subscriptions[phid];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
isSubscribedToAny: function(phids) {
|
||||||
|
var intersection = phids.filter(function(phid) {
|
||||||
|
return phid in this._subscriptions;
|
||||||
|
}, this);
|
||||||
|
return intersection.length > 0;
|
||||||
|
},
|
||||||
|
|
||||||
getSocket: function() {
|
getSocket: function() {
|
||||||
return this._socket;
|
return this._socket;
|
||||||
},
|
},
|
||||||
|
|
|
@ -31,7 +31,14 @@ JX.install('AphlictListenerList', {
|
||||||
},
|
},
|
||||||
|
|
||||||
getListeners: function() {
|
getListeners: function() {
|
||||||
return this._listeners;
|
var keys = Object.keys(this._listeners);
|
||||||
|
var listeners = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
listeners.push(this._listeners[keys[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return listeners;
|
||||||
},
|
},
|
||||||
|
|
||||||
getActiveListenerCount: function() {
|
getActiveListenerCount: function() {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
*/
|
*/
|
||||||
JX.install('Aphlict', {
|
JX.install('Aphlict', {
|
||||||
|
|
||||||
construct : function(id, server, port) {
|
construct : function(id, server, port, subscriptions) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (JX.Aphlict._instance) {
|
if (JX.Aphlict._instance) {
|
||||||
JX.$E('Aphlict object is sort of a singleton..!');
|
JX.$E('Aphlict object is sort of a singleton..!');
|
||||||
|
@ -36,6 +36,7 @@ JX.install('Aphlict', {
|
||||||
|
|
||||||
this._server = server;
|
this._server = server;
|
||||||
this._port = port;
|
this._port = port;
|
||||||
|
this._subscriptions = subscriptions;
|
||||||
|
|
||||||
// Flash puts its "objects" into global scope in an inconsistent way,
|
// Flash puts its "objects" into global scope in an inconsistent way,
|
||||||
// because it was written in like 1816 when globals were awesome and IE4
|
// because it was written in like 1816 when globals were awesome and IE4
|
||||||
|
@ -48,8 +49,12 @@ JX.install('Aphlict', {
|
||||||
members : {
|
members : {
|
||||||
_server : null,
|
_server : null,
|
||||||
_port : null,
|
_port : null,
|
||||||
|
_subscriptions : null,
|
||||||
start : function() {
|
start : function() {
|
||||||
this._flashContainer.connect(this._server, this._port);
|
this._flashContainer.connect(
|
||||||
|
this._server,
|
||||||
|
this._port,
|
||||||
|
this._subscriptions);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,13 @@ JX.behavior('aphlict-listen', function(config) {
|
||||||
var showing_reload = false;
|
var showing_reload = false;
|
||||||
|
|
||||||
function onready() {
|
function onready() {
|
||||||
var client = new JX.Aphlict(config.id, config.server, config.port)
|
var client = new JX.Aphlict(
|
||||||
|
config.id,
|
||||||
|
config.server,
|
||||||
|
config.port,
|
||||||
|
config.subscriptions);
|
||||||
|
|
||||||
|
client
|
||||||
.setHandler(onaphlictmessage)
|
.setHandler(onaphlictmessage)
|
||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue