Bring chat example up to date

This commit is contained in:
Tony Garnock-Jones 2014-05-28 19:45:12 -04:00
parent a7212a02af
commit fe2fcdb1c8
3 changed files with 54 additions and 67 deletions

View File

@ -10,6 +10,7 @@
<!-- <script src="../../third-party/bootstrap/js/bootstrap.min.js"></script> -->
<script src="../../third-party/jquery-2.0.3.min.js"></script>
<script src="../../route.js"></script>
<script src="../../marketplace.js"></script>
<script src="../../spy.js"></script>
<script src="../../dom-driver.js"></script>

View File

@ -15,13 +15,12 @@ function outputItem(item) {
return item;
}
function updateNymList(rs) {
function updateNymList(g) {
var statuses = {};
for (var i = 0; i < rs.length; i++) {
var p = rs[i].pattern;
if (p[0] === "broker" && p[1] === 0 && p[2][0] === "chatEvent") {
statuses[chatEventNym(p[2])] = chatEventStatus(p[2]);
}
var nymProj = ["broker", 0, ["chatEvent", _$, _$, __, __]];
var matchedNyms = route.matcherKeys(g.project(route.compileProjection(nymProj), true, 0, 0));
for (var i = 0; i < matchedNyms.length; i++) {
statuses[matchedNyms[i][0]] = matchedNyms[i][1];
}
var nyms = [];
for (var nym in statuses) { nyms.push(nym); }
@ -74,7 +73,10 @@ $(document).ready(function () {
},
handleEvent: function (e) {
if (e.type === "routes") {
var newState = (e.routes.length > 0) ? e.routes[0].pattern[1] : "crashed";
var states =
route.matcherKeys(e.gestalt.project(route.compileProjection([__, _$]),
true, 0, 0));
var newState = states.length > 0 ? states[0][0] : "crashed";
if (this.state != newState) {
outputState(newState);
this.state = newState;
@ -84,8 +86,6 @@ $(document).ready(function () {
});
World.spawn({
// Actual chat functionality
peers: new PresenceDetector(),
peerMap: {},
boot: function () {
World.updateRoutes(this.subscriptions());
},
@ -104,7 +104,7 @@ $(document).ready(function () {
var self = this;
switch (e.type) {
case "routes":
updateNymList(e.routes);
updateNymList(e.gestalt);
break;
case "message":
if (e.message === "wake") {

View File

@ -11,8 +11,8 @@ function WebSocketConnection(label, wsurl, shouldReconnect) {
this.wsurl = wsurl;
this.shouldReconnect = shouldReconnect ? true : false;
this.reconnectDelay = DEFAULT_RECONNECT_DELAY;
this.localRoutes = [];
this.peerRoutes = [];
this.localGestalt = route.emptyGestalt;
this.peerGestalt = route.emptyGestalt;
this.prevPeerRoutesMessage = null;
this.sock = null;
this.deduplicator = new Deduplicator();
@ -43,31 +43,18 @@ WebSocketConnection.prototype.statusRoute = function (status) {
return pub([this.label + "_state", status]);
};
WebSocketConnection.prototype.relayRoutes = function () {
// fresh copy each time, suitable for in-place extension/mutation
return [this.statusRoute(this.isConnected() ? "connected" : "disconnected"),
pub([this.label, __, __], 0, 1000),
sub([this.label, __, __], 0, 1000)];
WebSocketConnection.prototype.relayGestalt = function () {
return this.statusRoute(this.isConnected() ? "connected" : "disconnected")
.union(pub([this.label, __, __], 0, 10))
.union(sub([this.label, __, __], 0, 10));
// TODO: level 10 is ad-hoc; support infinity at some point in future
};
WebSocketConnection.prototype.aggregateRoutes = function () {
var rs = this.relayRoutes();
for (var i = 0; i < this.peerRoutes.length; i++) {
var r = this.peerRoutes[i];
rs.push(new Route(r.isSubscription,
// TODO: This is a horrible syntactic hack
// (in conjunction with the numberness-test
// in handleEvent's routes handler) for
// distinguishing routes published on behalf
// of the remote side from those published
// by the local side. See (**HACK**) mark
// below.
[this.label, __, r.pattern],
r.metaLevel,
r.level));
}
// console.log("WebSocketConnection.aggregateRoutes", this.label, rs);
return rs;
WebSocketConnection.prototype.aggregateGestalt = function () {
var self = this;
return this.peerGestalt.transform(function (m) {
return route.compilePattern(true, [self.label, __, route.embeddedMatcher(m)]);
}).union(this.relayGestalt());
};
WebSocketConnection.prototype.boot = function () {
@ -91,32 +78,39 @@ WebSocketConnection.prototype.safeSend = function (m) {
};
WebSocketConnection.prototype.sendLocalRoutes = function () {
this.safeSend(JSON.stringify(encodeEvent(updateRoutes(this.localRoutes))));
this.safeSend(JSON.stringify(encodeEvent(updateRoutes([this.localGestalt]))));
};
WebSocketConnection.prototype.collectMatchers = function (getAdvertisements, level, g) {
console.log("collectMatchers; getAdvertisements", getAdvertisements, "level", level);
console.log("g", g.pretty());
var extractMetaLevels = route.compileProjection([this.label, _$, __]);
var mls = route.matcherKeys(g.project(extractMetaLevels, getAdvertisements, 0, level));
console.log("got metalevels", JSON.stringify(mls));
for (var i = 0; i < mls.length; i++) {
var metaLevel = mls[i][0]; // only one capture in the projection
var extractMatchers = route.compileProjection([this.label, metaLevel, _$]);
var m = g.project(extractMatchers, getAdvertisements, 0, level);
console.log("matcher at metalevel", metaLevel, "is", route.prettyMatcher(m));
this.localGestalt = this.localGestalt.union(route.simpleGestalt(getAdvertisements,
route.embeddedMatcher(m),
metaLevel,
level));
}
};
WebSocketConnection.prototype.handleEvent = function (e) {
// console.log("WebSocketConnection.handleEvent", e);
switch (e.type) {
case "routes":
this.localRoutes = [];
for (var i = 0; i < e.routes.length; i++) {
var r = e.routes[i];
if (r.pattern.length && r.pattern.length === 3
&& r.pattern[0] === this.label
// TODO: This is a horrible syntactic hack (in
// conjunction with the use of __ in in
// aggregateRoutes) for distinguishing routes
// published on behalf of the remote side from those
// published by the local side. See (**HACK**) mark
// above.
&& typeof(r.pattern[1]) === "number")
{
this.localRoutes.push(new Route(r.isSubscription,
r.pattern[2],
r.pattern[1],
r.level));
}
// TODO: GROSS - erasing by pid!
var g = e.gestalt.erasePath(this.aggregateGestalt().label(World.activePid()));
this.localGestalt = route.emptyGestalt;
for (var level = 0; level < e.gestalt.levelCount(0); level++) {
this.collectMatchers(false, level, g);
this.collectMatchers(true, level, g);
}
this.sendLocalRoutes();
break;
case "message":
@ -178,8 +172,8 @@ WebSocketConnection.prototype.onmessage = function (wse) {
case "routes":
if (this.prevPeerRoutesMessage !== wse.data) {
this.prevPeerRoutesMessage = wse.data;
this.peerRoutes = e.routes;
World.updateRoutes(this.aggregateRoutes());
this.peerGestalt = e.gestalt;
World.updateRoutes([this.aggregateGestalt()]);
}
break;
case "message":
@ -195,7 +189,7 @@ WebSocketConnection.prototype.onclose = function (e) {
console.log("onclose", e);
// Update routes to give clients some indication of the discontinuity
World.updateRoutes(this.aggregateRoutes());
World.updateRoutes([this.aggregateGestalt()]);
if (this.shouldReconnect) {
console.log("reconnecting to " + this.wsurl + " in " + this.reconnectDelay + "ms");
@ -214,11 +208,7 @@ WebSocketConnection.prototype.onclose = function (e) {
function encodeEvent(e) {
switch (e.type) {
case "routes":
var rs = [];
for (var i = 0; i < e.routes.length; i++) {
rs.push(e.routes[i].toJSON());
}
return ["routes", rs];
return ["routes", e.gestalt.serialize(function (v) { return true; })];
case "message":
return ["message", e.message, e.metaLevel, e.isFeedback];
}
@ -227,11 +217,7 @@ function encodeEvent(e) {
function decodeAction(j) {
switch (j[0]) {
case "routes":
var rs = [];
for (var i = 0; i < j[1].length; i++) {
rs.push(Route.fromJSON(j[1][i]));
}
return updateRoutes(rs);
return updateRoutes([route.deserializeGestalt(j[1], function (v) { return true; })]);
case "message":
return sendMessage(j[1], j[2], j[3]);
default: