0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-06 22:40:14 -05:00

Added bulkEmail.batchSize option to configure batch size

refs https://github.com/TryGhost/Ghost/issues/15725

This pull request adds a new configuration option for the Mailgun email
provider that allows the user to set the maximum number of recipients
per email batch via a new config option `bulkEmail.batchSize`
This commit is contained in:
Kuba 2023-06-26 12:57:44 +02:00 committed by GitHub
parent 0a6b3d6b99
commit 9601285c3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 22 deletions

View file

@ -228,5 +228,8 @@
"members": [0, 100, 1000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000],
"minDaysSinceImported": 7,
"minDaysSinceLastEmail": 14
}
},
"bulkEmail": {
"batchSize": 1000
}
}

View file

@ -6,7 +6,6 @@ const sinon = require('sinon');
const assert = require('assert/strict');
const jobManager = require('../../../../core/server/services/jobs/job-service');
const _ = require('lodash');
const {MailgunEmailProvider} = require('@tryghost/email-service');
const escapeRegExp = require('lodash/escapeRegExp');
const configUtils = require('../../../utils/configUtils');
const {settingsCache} = require('../../../../core/server/services/settings-helpers');
@ -259,7 +258,7 @@ describe('Batch sending tests', function () {
let ghostServer;
beforeEach(function () {
MailgunEmailProvider.BATCH_SIZE = 100;
configUtils.set('bulkEmail:batchSize', 100);
stubbedSend = sinon.fake.resolves({
id: 'stubbed-email-id'
});
@ -548,7 +547,7 @@ describe('Batch sending tests', function () {
});
it('Splits up in batches according to email provider batch size', async function () {
MailgunEmailProvider.BATCH_SIZE = 1;
configUtils.set('bulkEmail:batchSize', 1);
await testEmailBatches({
mobiledoc: mobileDocExample
}, null, [
@ -561,7 +560,7 @@ describe('Batch sending tests', function () {
});
it('Splits up in batches according to email provider batch size with paid and free segments', async function () {
MailgunEmailProvider.BATCH_SIZE = 1;
configUtils.set('bulkEmail:batchSize', 1);
await testEmailBatches({
mobiledoc: mobileDocWithPaidMemberOnly
}, null, [
@ -577,7 +576,7 @@ describe('Batch sending tests', function () {
});
it('One failed batch marks the email as failed and allows for a retry', async function () {
MailgunEmailProvider.BATCH_SIZE = 1;
configUtils.set('bulkEmail:batchSize', 1);
let counter = 0;
stubbedSend = async function () {
counter += 1;

View file

@ -30,8 +30,6 @@ class MailgunEmailProvider {
#mailgunClient;
#errorHandler;
static BATCH_SIZE = 1000;
/**
* @param {object} dependencies
* @param {import('@tryghost/mailgun-client/lib/MailgunClient')} dependencies.mailgunClient - mailgun client to send emails
@ -172,7 +170,7 @@ class MailgunEmailProvider {
}
getMaximumRecipients() {
return MailgunEmailProvider.BATCH_SIZE;
return this.#mailgunClient.getBatchSize();
}
}

View file

@ -225,8 +225,20 @@ describe('Mailgun Email Provider', function () {
});
describe('getMaximumRecipients', function () {
let mailgunClient;
let getBatchSizeStub;
it('returns 1000', function () {
const provider = new MailgunEmailProvider({});
getBatchSizeStub = sinon.stub().returns(1000);
mailgunClient = {
getBatchSize: getBatchSizeStub
};
const provider = new MailgunEmailProvider({
mailgunClient,
errorHandler: () => {}
});
assert.equal(provider.getMaximumRecipients(), 1000);
});
});

View file

@ -8,7 +8,7 @@ module.exports = class MailgunClient {
#config;
#settings;
static BATCH_SIZE = 1000;
static DEFAULT_BATCH_SIZE = 1000;
constructor({config, settings}) {
this.#config = config;
@ -38,9 +38,10 @@ module.exports = class MailgunClient {
return null;
}
if (Object.keys(recipientData).length > MailgunClient.BATCH_SIZE) {
const batchSize = this.getBatchSize();
if (Object.keys(recipientData).length > batchSize) {
throw new errors.IncorrectUsageError({
message: `Mailgun only supports sending to ${MailgunClient.BATCH_SIZE} recipients at a time`
message: `Mailgun only supports sending to ${batchSize} recipients at a time`
});
}
@ -305,4 +306,13 @@ module.exports = class MailgunClient {
const instance = this.getInstance();
return !!instance;
}
/**
* Returns configured batch size
*
* @returns {number}
*/
getBatchSize() {
return this.#config.get('bulkEmail')?.batchSize ?? this.DEFAULT_BATCH_SIZE;
}
};

View file

@ -43,8 +43,19 @@ describe('MailgunClient', function () {
sinon.restore();
});
it('exports a number for BATCH_SIZE', function () {
assert(typeof MailgunClient.BATCH_SIZE === 'number');
it('exports a number for configurable batch size', function () {
const configStub = sinon.stub(config, 'get');
configStub.withArgs('bulkEmail').returns({
mailgun: {
apiKey: 'apiKey',
domain: 'domain.com',
baseUrl: 'https://api.mailgun.net/v3'
},
batchSize: 1000
});
const mailgunClient = new MailgunClient({config, settings});
assert(typeof mailgunClient.getBatchSize() === 'number');
});
it('can connect via config', function () {
@ -54,7 +65,8 @@ describe('MailgunClient', function () {
apiKey: 'apiKey',
domain: 'domain.com',
baseUrl: 'https://api.mailgun.net/v3'
}
},
batchSize: 1000
});
const mailgunClient = new MailgunClient({config, settings});
@ -116,7 +128,8 @@ describe('MailgunClient', function () {
apiKey: 'apiKey',
domain: 'configdomain.com',
baseUrl: 'https://api.mailgun.net'
}
},
batchSize: 1000
});
const settingsStub = sinon.stub(settings, 'get');
@ -170,7 +183,8 @@ describe('MailgunClient', function () {
apiKey: 'apiKey',
domain: 'domain.com',
baseUrl: 'https://api.mailgun.net/v3'
}
},
batchSize: 1000
});
const firstPageMock = nock('https://api.mailgun.net')
@ -214,7 +228,8 @@ describe('MailgunClient', function () {
apiKey: 'apiKey',
domain: 'domain.com',
baseUrl: 'https://api.mailgun.net/v3'
}
},
batchSize: 1000
});
const firstPageMock = nock('https://api.mailgun.net')
@ -259,7 +274,8 @@ describe('MailgunClient', function () {
apiKey: 'apiKey',
domain: 'domain.com',
baseUrl: 'https://api.mailgun.net/v3'
}
},
batchSize: 1000
});
const firstPageMock = nock('https://api.mailgun.net')
@ -304,7 +320,8 @@ describe('MailgunClient', function () {
apiKey: 'apiKey',
domain: 'domain.com',
baseUrl: 'https://api.mailgun.net/v3'
}
},
batchSize: 1000
});
const firstPageMock = nock('https://api.mailgun.net')
@ -349,7 +366,8 @@ describe('MailgunClient', function () {
apiKey: 'apiKey',
domain: 'domain.com',
baseUrl: 'https://api.eu.mailgun.net/v3'
}
},
batchSize: 1000
});
const firstPageMock = nock('https://api.eu.mailgun.net')