diff --git a/lib/core.js b/lib/core.js index b39b2d3..1e0a448 100644 --- a/lib/core.js +++ b/lib/core.js @@ -14,6 +14,7 @@ module.exports.create = function (le) { var utils = require('./utils'); var RSA = PromiseA.promisifyAll(require('rsa-compat').RSA); var log = le.log || _log; // allow custom log + var pendingRegistrations = {}; var core = { // @@ -183,13 +184,45 @@ module.exports.create = function (le) { return PromiseA.reject(err); } + // If a previous request to (re)register a certificate is already underway we need + // to return the same promise created before rather than registering things twice. + // I'm not 100% sure how to properly handle the case where someone registers domain + // lists with some but not all elements common, nor am I sure that's even a case that + // is allowed to happen anyway. But for now we act like the list is completely the + // same if any elements are the same. + var promise; + args.domains.some(function (name) { + if (pendingRegistrations.hasOwnProperty(name)) { + promise = pendingRegistrations[name]; + return true; + } + }); + if (promise) { + return promise; + } + + promise = core.certificates._runRegistration(args); + + // Now that the registration is actually underway we need to make sure any subsequent + // registration attempts return the same promise until it is completed (but not after + // it is completed). + args.domains.forEach(function (name) { + pendingRegistrations[name] = promise; + }); + function clearPending() { + args.domains.forEach(function (name) { + delete pendingRegistrations[name]; + }); + } + promise.then(clearPending, clearPending); + + return promise; + } + , _runRegistration: function (args) { // TODO renewal cb // accountId and or email - return core.accounts.getAsync(copy).then(function (account) { - copy.account = account; - - //var account = args.account; - var keypairOpts = { public: true, pem: true }; + return core.accounts.getAsync(args).then(function (account) { + args.account = account; var promise = le.store.certificates.checkKeypairAsync(args).then(function (keypair) { if (keypair) { @@ -200,6 +233,7 @@ module.exports.create = function (le) { return le.store.certificates.setKeypairAsync(args, RSA.import(args.domainKeypair)); } + var keypairOpts = { public: true, pem: true }; return RSA.generateKeypairAsync(args.rsaKeySize, 65537, keypairOpts).then(function (keypair) { keypair.privateKeyPem = RSA.exportPrivatePem(keypair); keypair.publicKeyPem = RSA.exportPublicPem(keypair);