Page MenuHomestyx hydra

No OneTemporary

diff --git a/support/aphlict/client/src/Aphlict.as b/support/aphlict/client/src/Aphlict.as
index d61ad04b0a..592bbd4e54 100644
--- a/support/aphlict/client/src/Aphlict.as
+++ b/support/aphlict/client/src/Aphlict.as
@@ -1,40 +1,44 @@
package {
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.net.LocalConnection;
public class Aphlict extends Sprite {
/**
* A transport channel used to receive data.
*/
protected var recv:LocalConnection;
/**
* A transport channel used to send data.
*/
protected var send:LocalConnection;
public function Aphlict() {
super();
this.recv = new LocalConnection();
this.recv.client = this;
this.send = new LocalConnection();
}
protected function externalInvoke(type:String, object:Object = null):void {
ExternalInterface.call('JX.Aphlict.didReceiveEvent', type, object);
}
+ protected function error(error:Error):void {
+ this.externalInvoke('error', error.toString());
+ }
+
protected function log(message:String):void {
this.externalInvoke('log', message);
}
}
}
diff --git a/support/aphlict/client/src/AphlictMaster.as b/support/aphlict/client/src/AphlictMaster.as
index 1991ab48bd..ee07fe53e6 100644
--- a/support/aphlict/client/src/AphlictMaster.as
+++ b/support/aphlict/client/src/AphlictMaster.as
@@ -1,166 +1,170 @@
package {
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TimerEvent;
import flash.net.Socket;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.utils.Timer;
import vegas.strings.JSON;
public class AphlictMaster extends Aphlict {
/**
* The pool of connected clients.
*/
private var clients:Dictionary;
/**
* A timer used to trigger periodic events.
*/
private var timer:Timer;
/**
* The interval after which clients will be considered dead and removed
* from the pool.
*/
public static const PURGE_INTERVAL:Number = 3 * AphlictClient.INTERVAL;
/**
* The hostname for the Aphlict Server.
*/
private var remoteServer:String;
/**
* The port number for the Aphlict Server.
*/
private var remotePort:Number;
private var socket:Socket;
private var readBuffer:ByteArray;
public function AphlictMaster(server:String, port:Number) {
super();
this.remoteServer = server;
this.remotePort = port;
// Connect to the Aphlict Server.
this.recv.connect('aphlict_master');
this.connectToServer();
this.clients = new Dictionary();
// Start a timer and regularly purge dead clients.
this.timer = new Timer(AphlictMaster.PURGE_INTERVAL);
this.timer.addEventListener(TimerEvent.TIMER, this.purgeClients);
this.timer.start();
}
/**
* Register a @{class:AphlictClient}.
*/
public function register(client:String):void {
if (!this.clients[client]) {
this.log('Registering client: ' + client);
this.clients[client] = new Date().getTime();
}
}
/**
* Purge stale client connections from the client pool.
*/
private function purgeClients(event:TimerEvent):void {
for (var client:String in this.clients) {
var checkin:Number = this.clients[client];
if (new Date().getTime() - checkin > AphlictMaster.PURGE_INTERVAL) {
this.log('Purging client: ' + client);
delete this.clients[client];
}
}
}
/**
* Clients will regularly "ping" the master to let us know that they are
* still alive. We will "pong" them back to let the client know that the
* master is still alive.
*/
public function ping(client:String):void {
this.clients[client] = new Date().getTime();
this.send.send(client, 'pong');
}
private function connectToServer():void {
var socket:Socket = new Socket();
socket.addEventListener(Event.CONNECT, didConnectSocket);
socket.addEventListener(Event.CLOSE, didCloseSocket);
socket.addEventListener(ProgressEvent.SOCKET_DATA, didReceiveSocket);
socket.addEventListener(IOErrorEvent.IO_ERROR, didIOErrorSocket);
socket.addEventListener(
SecurityErrorEvent.SECURITY_ERROR,
didSecurityErrorSocket);
socket.connect(this.remoteServer, this.remotePort);
this.readBuffer = new ByteArray();
this.socket = socket;
}
private function didConnectSocket(event:Event):void {
this.externalInvoke('connected');
}
private function didCloseSocket(event:Event):void {
this.externalInvoke('close');
}
private function didIOErrorSocket(event:IOErrorEvent):void {
this.externalInvoke('error', event.text);
}
private function didSecurityErrorSocket(event:SecurityErrorEvent):void {
this.externalInvoke('error', event.text);
}
private function didReceiveSocket(event:Event):void {
- var b:ByteArray = this.readBuffer;
- this.socket.readBytes(b, b.length);
+ try {
+ var b:ByteArray = this.readBuffer;
+ this.socket.readBytes(b, b.length);
- do {
- b = this.readBuffer;
- b.position = 0;
+ do {
+ b = this.readBuffer;
+ b.position = 0;
- if (b.length <= 8) {
- break;
- }
+ if (b.length <= 8) {
+ break;
+ }
- var msg_len:Number = parseInt(b.readUTFBytes(8), 10);
- if (b.length >= msg_len + 8) {
- var bytes:String = b.readUTFBytes(msg_len);
- var data:Object = vegas.strings.JSON.deserialize(bytes);
- var t:ByteArray = new ByteArray();
- t.writeBytes(b, msg_len + 8);
- this.readBuffer = t;
-
- // Send the message to all clients.
- for (var client:String in this.clients) {
- this.log('Sending message to client: ' + client);
- this.send.send(client, 'receiveMessage', data);
+ var msg_len:Number = parseInt(b.readUTFBytes(8), 10);
+ if (b.length >= msg_len + 8) {
+ var bytes:String = b.readUTFBytes(msg_len);
+ var data:Object = vegas.strings.JSON.deserialize(bytes);
+ var t:ByteArray = new ByteArray();
+ t.writeBytes(b, msg_len + 8);
+ this.readBuffer = t;
+
+ // Send the message to all clients.
+ for (var client:String in this.clients) {
+ this.log('Sending message to client: ' + client);
+ this.send.send(client, 'receiveMessage', data);
+ }
+ } else {
+ break;
}
- } else {
- break;
- }
- } while (true);
+ } while (true);
+ } catch (err:Error) {
+ this.error(err);
+ }
}
}
}
diff --git a/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js b/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js
index 5fc15968d1..0f40d2c13f 100644
--- a/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js
+++ b/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js
@@ -1,94 +1,107 @@
/**
* @provides javelin-behavior-aphlict-listen
* @requires javelin-behavior
* javelin-aphlict
* javelin-stratcom
* javelin-request
* javelin-uri
* javelin-dom
* javelin-json
* javelin-router
* phabricator-notification
*/
JX.behavior('aphlict-listen', function(config) {
var showing_reload = false;
function onready() {
var client = new JX.Aphlict(config.id, config.server, config.port)
.setHandler(onaphlictmessage)
.start();
}
// Respond to a notification from the Aphlict notification server. We send
// a request to Phabricator to get notification details.
function onaphlictmessage(type, message) {
- if (type == 'receive') {
- var routable = new JX.Request('/notification/individual/', onnotification)
- .addData({key: message.key})
- .getRoutable();
+ switch (type) {
+ case 'error':
+ new JX.Notification()
+ .setContent('(Aphlict) ' + message)
+ .alterClassName('jx-notification-error', true)
+ .show();
+ break;
- routable
- .setType('notification')
- .setPriority(250);
+ case 'receive':
+ var routable = new JX.Request(
+ '/notification/individual/',
+ onnotification);
- JX.Router.getInstance().queue(routable);
- } else if (__DEV__) {
- if (config.debug) {
- var details = message ? JX.JSON.stringify(message) : '';
+ routable
+ .addData({key: message.key})
+ .getRoutable();
- new JX.Notification()
- .setContent('(Aphlict) [' + type + '] ' + details)
- .alterClassName('jx-notification-debug', true)
- .show();
- }
+ routable
+ .setType('notification')
+ .setPriority(250);
+
+ JX.Router.getInstance().queue(routable);
+ break;
+
+ default:
+ if (__DEV__ && config.debug) {
+ var details = message ? JX.JSON.stringify(message) : '';
+
+ new JX.Notification()
+ .setContent('(Aphlict) [' + type + '] ' + details)
+ .alterClassName('jx-notification-debug', true)
+ .show();
+ }
}
}
// Respond to a response from Phabricator about a specific notification.
function onnotification(response) {
if (!response.pertinent) {
return;
}
JX.Stratcom.invoke('notification-panel-update', null, {});
// Show the notification itself.
new JX.Notification()
.setContent(JX.$H(response.content))
.show();
// If the notification affected an object on this page, show a
// permanent reload notification if we aren't already.
- if ((response.primaryObjectPHID in config.pageObjects) &&
- !showing_reload) {
+ if ((response.primaryObjectPHID in config.pageObjects) && !showing_reload) {
var reload = new JX.Notification()
.setContent('Page updated, click to reload.')
.alterClassName('jx-notification-alert', true)
.setDuration(0);
reload.listen('activate', function(e) { JX.$U().go(); });
reload.show();
showing_reload = true;
}
}
// Wait for the element to load, and don't do anything if it never loads.
// If we just go crazy and start making calls to it before it loads, its
// interfaces won't be registered yet.
JX.Stratcom.listen('aphlict-component-ready', null, onready);
// Add Flash object to page
JX.$(config.containerID).innerHTML =
'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000">' +
'<param name="movie" value="/rsrc/swf/aphlict.swf" />' +
'<param name="allowScriptAccess" value="always" />' +
'<param name="wmode" value="opaque" />' +
'<embed src="/rsrc/swf/aphlict.swf" wmode="opaque"' +
'width="0" height="0" id="' + config.id + '">' +
'</embed></object>'; //Evan sanctioned
});
diff --git a/webroot/rsrc/swf/aphlict.swf b/webroot/rsrc/swf/aphlict.swf
index cee18c7dc6..c6ffcdbd32 100644
Binary files a/webroot/rsrc/swf/aphlict.swf and b/webroot/rsrc/swf/aphlict.swf differ

File Metadata

Mime Type
text/x-diff
Expires
Fri, Oct 31, 9:34 AM (17 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
312083
Default Alt Text
(11 KB)

Event Timeline