From aa38d9e8434355f880d25abb0b30c5ef789fc58b Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Mon, 31 Dec 2012 13:54:25 -0800 Subject: [PATCH] refactored proposer a bit --- proposer/propose-state.js | 29 +++++++++++++++-------------- proposer/proposer.js | 19 ++++++++++--------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/proposer/propose-state.js b/proposer/propose-state.js index b646403..56e9c6c 100644 --- a/proposer/propose-state.js +++ b/proposer/propose-state.js @@ -1,6 +1,6 @@ module.exports = function (assert, inherits, EventEmitter, Prepare, Proposal) { - function Paxos(proposer, instance, ballot) { + function ProposeState(proposer, instance, ballot) { EventEmitter.call(this) this.proposerId = proposer.id this.instance = instance @@ -8,22 +8,26 @@ module.exports = function (assert, inherits, EventEmitter, Prepare, Proposal) { this.value = null this.valueBallot = 0 - this.timer = null + // TODO: decide where timeouts go. At this point there's arguments for + // here, where they become part of the state, or in the communication + // layer which keeps the state "time free". I think I'd prefer to keep + // knowledge of time out of the state, but it seems easier to implement + // here. So lets try to do it "there" and only come back if its too ugly. this.promises = [] this.majority = proposer.majority } - inherits(Paxos, EventEmitter) + inherits(ProposeState, EventEmitter) - Paxos.create = function (proposer, instance, ballot) { - var state = new Paxos(proposer, instance, ballot) + ProposeState.create = function (proposer, instance, ballot) { + var state = new ProposeState(proposer, instance, ballot) state.on('prepare', proposer.onPrepare) state.on('accept', proposer.onAccept) state.on('propose', proposer.onPropose) return state } - Paxos.prototype.nextBallot = function (previous) { + ProposeState.prototype.nextBallot = function (previous) { var id = previous % 100 var counter = (previous - id) + 100 //here's the increment this.ballot = counter + this.proposerId @@ -31,14 +35,12 @@ module.exports = function (assert, inherits, EventEmitter, Prepare, Proposal) { return this.ballot } - Paxos.prototype.prepare = function (previousBallot) { - clearTimeout(this.timer) + ProposeState.prototype.prepare = function (previousBallot) { this.nextBallot(previousBallot || this.ballot) this.emit('prepare', new Prepare(this.instance, this.ballot)) } - Paxos.prototype.proposal = function () { - clearTimeout(this.timer) + ProposeState.prototype.proposal = function () { var proposal = new Proposal(this.instance, this.ballot, this.value, this.valueBallot) var event = this.value ? 'accept' : 'propose' this.emit(event, proposal) @@ -52,7 +54,7 @@ module.exports = function (assert, inherits, EventEmitter, Prepare, Proposal) { return (a.valueBallot || 0) > (b.valueBallot || 0) ? a : b } - Paxos.prototype.promised = function (proposal) { + ProposeState.prototype.promised = function (proposal) { assert.equal(this.instance, proposal.instance) if (this.ballot < proposal.ballot) { @@ -74,12 +76,11 @@ module.exports = function (assert, inherits, EventEmitter, Prepare, Proposal) { } } - Paxos.prototype.complete = function (proposer) { - clearTimeout(this.timer) + ProposeState.prototype.complete = function (proposer) { this.removeListener('prepare', proposer.onPrepare) this.removeListener('accept', proposer.onAccept) this.removeListener('propose', proposer.onPropose) } - return Paxos + return ProposeState } diff --git a/proposer/proposer.js b/proposer/proposer.js index 1f37d0b..ea4f2e3 100644 --- a/proposer/proposer.js +++ b/proposer/proposer.js @@ -1,4 +1,4 @@ -module.exports = function (assert, inherits, EventEmitter, Paxos) { +module.exports = function (assert, inherits, EventEmitter, ProposeState) { function Proposer(id, majority, learner) { assert(id < 100, "max id is 99") @@ -15,18 +15,19 @@ module.exports = function (assert, inherits, EventEmitter, Paxos) { } inherits(Proposer, EventEmitter) - Proposer.prototype.prepare = function (instanceId) { - instanceId = instanceId || this.instanceCounter++ - var instance = this.instances[instanceId] || Paxos.create(this, instanceId) + Proposer.prototype.instance = function (instanceId, ballot) { + var instance = this.instances[instanceId] || + ProposeState.create(this, instanceId, ballot) this.instances[instanceId] = instance - instance.prepare() + return instance + } + + Proposer.prototype.prepare = function (instanceId) { + this.instance(instanceId || this.instanceCounter++).prepare() } Proposer.prototype.promised = function (proposal) { - var instance = this.instances[proposal.instance] || - Paxos.create(this, proposal.instance, proposal.ballot) - this.instances[proposal.instance] = instance - instance.promised(proposal) + this.instance(proposal.instance, proposal.ballot).promised(proposal) } Proposer.prototype.accept = function (proposal) {