diff --git a/packages/livedata/livedata_server.js b/packages/livedata/livedata_server.js index 09f092bf89..2b568a8238 100644 --- a/packages/livedata/livedata_server.js +++ b/packages/livedata/livedata_server.js @@ -237,6 +237,12 @@ _.extend(Meteor._LivedataSession.prototype, { // done. var fence = new Meteor._WriteFence; fence.onAllCommitted(function () { + // Retire the fence so that future writes are allowed. + // This means that callbacks like timers are free to use + // the fence, and if they fire before it's armed (for + // example, because the method waits for them) their + // writes will be included in the fence. + fence.retire(); self.send({ msg: 'data', methods: [msg.id]}); }); diff --git a/packages/livedata/writefence.js b/packages/livedata/writefence.js index b857cfc9e5..a95aca63fe 100644 --- a/packages/livedata/writefence.js +++ b/packages/livedata/writefence.js @@ -6,6 +6,7 @@ Meteor._WriteFence = function () { self.armed = false; self.fired = false; + self.retired = false; self.outstanding_writes = 0; self.completion_callbacks = []; }; @@ -24,6 +25,9 @@ _.extend(Meteor._WriteFence.prototype, { beginWrite: function () { var self = this; + if (self.retired) + return { committed: function () {} }; + if (self.fired) throw new Error("fence has already activated -- too late to add writes"); @@ -77,5 +81,14 @@ _.extend(Meteor._WriteFence.prototype, { _.each(self.completion_callbacks, function (f) {f(self);}); self.completion_callbacks = []; } + }, + + // Deactivate this fence so that adding more writes has no effect. + // The fence must have already fired. + retire: function () { + var self = this; + if (! self.fired) + throw new Error("Can't retire a fence that hasn't fired."); + self.retired = true; } }); \ No newline at end of file diff --git a/packages/meteor/timers.js b/packages/meteor/timers.js index cb541f8aa2..05443601c5 100644 --- a/packages/meteor/timers.js +++ b/packages/meteor/timers.js @@ -1,8 +1,7 @@ _.extend(Meteor, { // Meteor.setTimeout and Meteor.setInterval callbacks scheduled - // inside a server method are not part of the method invocation, and - // should clear out the CurrentInvocation and CurrentWriteFence - // environment variables. + // inside a server method are not part of the method invocation and + // should clear out the CurrentInvocation environment variable. setTimeout: function (f, duration) { if (Meteor._CurrentInvocation) { @@ -13,11 +12,6 @@ _.extend(Meteor, { f = function () { Meteor._CurrentInvocation.withValue(null, f_with_ci); }; } - if (Meteor._CurrentWriteFence) { - var f_with_cwf = f; - f = function () { Meteor._CurrentWriteFence.withValue(null, f_with_cwf); }; - } - return setTimeout(Meteor.bindEnvironment(f, function (e) { // XXX report nicely (or, should we catch it at all?) Meteor._debug("Exception from setTimeout callback:", e.stack); @@ -33,11 +27,6 @@ _.extend(Meteor, { f = function () { Meteor._CurrentInvocation.withValue(null, f_with_ci); }; } - if (Meteor._CurrentWriteFence) { - var f_with_cwf = f; - f = function () { Meteor._CurrentWriteFence.withValue(null, f_with_cwf); }; - } - return setInterval(Meteor.bindEnvironment(f, function (e) { // XXX report nicely (or, should we catch it at all?) Meteor._debug("Exception from setInterval callback:", e);