Improve remote.js and test starts.

- Transactions now emit 'pending' and 'lost'
- Remote now supports once().
- Tests now use 'ledger_closed' to know when to start.
- Fix quick close of remote.
This commit is contained in:
Arthur Britto
2012-10-17 18:15:04 -07:00
parent d7ccf1f7a6
commit bacfcff48c
3 changed files with 143 additions and 18 deletions

View File

@@ -26,13 +26,17 @@ var Amount = amount.Amount;
// 'remoteUnexpected'
// 'remoteDisconnected'
var Request = function (remote, command) {
var self = this;
this.message = {
'command' : command,
'id' : undefined,
};
this.remote = remote;
this.on('request', this.request_default);
this.on('request', function () {
self.request_default();
});
};
Request.prototype = new EventEmitter;
@@ -44,6 +48,12 @@ Request.prototype.on = function (e, c) {
return this;
};
Request.prototype.once = function (e, c) {
EventEmitter.prototype.once.call(this, e, c);
return this;
};
// Send the request to a remote.
Request.prototype.request = function (remote) {
this.emit('request', remote);
@@ -103,7 +113,8 @@ Request.prototype.transaction = function (t) {
// 'state':
// - 'online' : connectted and subscribed
// - 'offline' : not subscribed or not connectted.
// 'ledger_closed'
// 'ledger_closed': A good indicate of ready to serve.
// 'subscribed' : This indicates stand-alone is available.
//
// --> trusted: truthy, if remote is trusted
@@ -296,9 +307,10 @@ Remote.prototype._connect_start = function () {
};
if (self.online_target) {
self._server_subscribe(); // Automatically subscribe.
self._set_state('online');
// Note, we could get disconnected before tis go through.
self._server_subscribe(); // Automatically subscribe.
}
else {
self._connect_stop();
@@ -372,7 +384,7 @@ Remote.prototype._connect_message = function (ws, json, flags) {
this.ledger_closed = message.ledger_closed;
this.ledger_current_index = message.ledger_closed_index + 1;
this.emit('ledger_closed', this.ledger_closed, this.ledger_closed_index);
this.emit('ledger_closed', message.ledger_closed, message.ledger_closed_index);
break;
default:
@@ -409,13 +421,20 @@ Remote.prototype._connect_message = function (ws, json, flags) {
// Send a request.
// <-> request: what to send, consumed.
Remote.prototype.request = function (request) {
this.ws.response[request.message.id = this.id] = request;
if (this.ws) {
// Only bother if we are still connected.
this.id += 1; // Advance id.
this.ws.response[request.message.id = this.id] = request;
if (this.trace) console.log("remote: request: %s", JSON.stringify(request.message));
this.id += 1; // Advance id.
this.ws.send(JSON.stringify(request.message));
if (this.trace) console.log("remote: request: %s", JSON.stringify(request.message));
this.ws.send(JSON.stringify(request.message));
}
else {
if (this.trace) console.log("remote: request: DROPPING: %s", JSON.stringify(request.message));
}
};
Remote.prototype.request_ledger_closed = function () {
@@ -480,7 +499,7 @@ Remote.prototype.request_ledger_entry = function (type) {
// This type not cached.
}
this.request_default(remote);
this.request_default();
}
}
});
@@ -668,6 +687,8 @@ Remote.prototype.transaction = function () {
// - The client should only trust this when talking to a trusted server.
// 'final' : Final status of transaction.
// - Only expect a final from honest clients after a tesSUCCESS or ter*.
// 'lost' : Gave up looking for on ledger_closed.
// 'pending' : Transaction was not found on ledger_closed.
// 'state' : Follow the state of a transaction.
// 'clientSubmitted' - Sent to remote
// |- 'remoteError' - Remote rejected transaction.
@@ -802,8 +823,8 @@ Transaction.prototype.submit = function () {
}
}
if (this.listeners('final').length) {
// There are listeners for 'final' arrange to emit it.
if (this.listeners('final').length || this.listeners('lost').length || this.listeners('pending').length) {
// There are listeners for 'final', 'lost', or 'pending' arrange to emit them.
this.submit_index = this.remote.ledger_current_index;
@@ -820,11 +841,16 @@ Transaction.prototype.submit = function () {
if ('remoteError' === message.error
&& 'transactionNotFound' === message.remote.error) {
if (self.submit_index + SUBMIT_LOST < ledger_closed_index) {
self.set_state('clientLost'); // Gave up.
self.set_state('client_lost'); // Gave up.
self.emit('lost');
stop = true;
}
else if (self.submit_index + SUBMIT_MISSING < ledger_closed_index) {
self.set_state('clientMissing'); // We don't know what happened to transaction, still might find.
self.set_state('client_missing'); // We don't know what happened to transaction, still might find.
self.emit('pending');
}
else {
self.emit('pending');
}
}
// XXX Could log other unexpectedness.

View File

@@ -24,7 +24,7 @@ buster.testCase("Remote functions", {
alpha = remote.remoteConfig(config, "alpha");
alpha
.on('connected', done)
.once('ledger_closed', done)
.connect();
});
},

99
test/send-test.js Normal file
View File

@@ -0,0 +1,99 @@
var buster = require("buster");
var config = require("./config.js");
var server = require("./server.js");
var amount = require("../js/amount.js");
var remote = require("../js/remote.js");
var Amount = amount.Amount;
// How long to wait for server to start.
var serverDelay = 1500;
buster.testRunner.timeout = 5000;
buster.testCase("Sending", {
'setUp' :
function (done) {
server.start("alpha",
function (e) {
buster.refute(e);
alpha = remote.remoteConfig(config, "alpha");
alpha
.once('ledger_closed', done)
.connect();
});
},
'tearDown' :
function (done) {
alpha
.on('disconnected', function () {
server.stop("alpha", function (e) {
buster.refute(e);
done();
});
})
.connect(false);
},
"send to non-existant account without create." :
function (done) {
var got_proposed;
var ledgers = 20;
alpha.transaction()
.payment('root', 'alice', Amount.from_json("10000"))
.on('success', function (r) {
// Transaction sent.
console.log("success: %s", JSON.stringify(r));
})
.on('pending', function() {
// Moving ledgers along.
console.log("missing: %d", ledgers);
ledgers -= 1;
if (ledgers) {
alpha.ledger_accept();
}
else {
buster.assert(false, "Final never received.");
done();
}
})
.on('lost', function () {
// Transaction did not make it in.
console.log("lost");
buster.assert(true);
done();
})
.on('proposed', function (m) {
// Transaction got an error.
console.log("proposed: %s", JSON.stringify(m));
buster.assert.equals(m.result, 'terNO_DST');
got_proposed = true;
alpha.ledger_accept(); // Move it along.
})
.on('final', function (m) {
console.log("final: %s", JSON.stringify(m));
buster.assert(false, "Should not have got a final.");
done();
})
.on('error', function(m) {
console.log("error: %s", m);
buster.assert(false);
})
.submit();
},
});
// vim:sw=2:sts=2:ts=8