mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-09-11 12:55:37 +03:00
Extracted batchDelay into configuration
This commit is contained in:
parent
f15d4c122f
commit
7393f5857f
@ -357,6 +357,8 @@ class BatchSendingService {
|
||||
async sendBatches({email, batches, post, newsletter}) {
|
||||
logging.info(`Sending ${batches.length} batches for email ${email.id}`);
|
||||
|
||||
const BATCH_DELAY = this.#sendingService.getBatchDelay(); // delay between batches in milliseconds
|
||||
|
||||
// Reuse same HTML body if we send an email to the same segment
|
||||
const emailBodyCache = new EmailBodyCache();
|
||||
|
||||
@ -370,9 +372,12 @@ class BatchSendingService {
|
||||
runNext = async () => {
|
||||
const batch = queue.shift();
|
||||
if (batch) {
|
||||
const index = batches.indexOf(batch);
|
||||
const deliveryDelay = Math.abs(index * 5000);
|
||||
const deliveryTime = new Date(startTime.getTime() + deliveryDelay);
|
||||
let deliveryTime = undefined;
|
||||
if (BATCH_DELAY > 0) {
|
||||
const index = batches.indexOf(batch);
|
||||
const deliveryDelay = Math.abs(index * BATCH_DELAY);
|
||||
deliveryTime = new Date(startTime.getTime() + deliveryDelay);
|
||||
}
|
||||
if (await this.sendBatch({email, batch, post, newsletter, emailBodyCache, deliveryTime})) {
|
||||
succeededCount += 1;
|
||||
}
|
||||
@ -442,11 +447,11 @@ class BatchSendingService {
|
||||
post,
|
||||
newsletter,
|
||||
segment: batch.get('member_segment'),
|
||||
members,
|
||||
deliveryTime
|
||||
members
|
||||
}, {
|
||||
openTrackingEnabled: !!email.get('track_opens'),
|
||||
clickTrackingEnabled: !!email.get('track_clicks'),
|
||||
deliveryTime,
|
||||
emailBodyCache
|
||||
});
|
||||
}, {...this.#MAILGUN_API_RETRY_CONFIG, description: `Sending email batch ${originalBatch.id}`});
|
||||
|
@ -177,6 +177,15 @@ class MailgunEmailProvider {
|
||||
getMaximumRecipients() {
|
||||
return this.#mailgunClient.getBatchSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured delay between batches in milliseconds
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
getBatchDelay() {
|
||||
return this.#mailgunClient.getBatchDelay();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MailgunEmailProvider;
|
||||
|
@ -76,6 +76,15 @@ class SendingService {
|
||||
return this.#emailProvider.getMaximumRecipients();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured delay between batches in milliseconds
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
getBatchDelay() {
|
||||
return this.#emailProvider.getBatchDelay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a given post, rendered for a given newsletter and segment to the members provided in the list
|
||||
* @param {object} data
|
||||
|
@ -681,7 +681,13 @@ describe('Batch Sending Service', function () {
|
||||
|
||||
describe('sendBatches', function () {
|
||||
it('Works for a single batch', async function () {
|
||||
const service = new BatchSendingService({});
|
||||
const service = new BatchSendingService({
|
||||
sendingService: {
|
||||
getBatchDelay() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
const sendBatch = sinon.stub(service, 'sendBatch').callsFake(() => {
|
||||
return Promise.resolve(true);
|
||||
});
|
||||
@ -700,7 +706,13 @@ describe('Batch Sending Service', function () {
|
||||
});
|
||||
|
||||
it('Works for more than 2 batches', async function () {
|
||||
const service = new BatchSendingService({});
|
||||
const service = new BatchSendingService({
|
||||
sendingService: {
|
||||
getBatchDelay() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
let runningCount = 0;
|
||||
let maxRunningCount = 0;
|
||||
const sendBatch = sinon.stub(service, 'sendBatch').callsFake(async () => {
|
||||
@ -723,8 +735,51 @@ describe('Batch Sending Service', function () {
|
||||
assert.equal(maxRunningCount, 2);
|
||||
});
|
||||
|
||||
it('Works with a batchDelay > 0', async function () {
|
||||
const service = new BatchSendingService({
|
||||
sendingService: {
|
||||
getBatchDelay() {
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
});
|
||||
let runningCount = 0;
|
||||
let maxRunningCount = 0;
|
||||
const sendBatch = sinon.stub(service, 'sendBatch').callsFake(async () => {
|
||||
runningCount += 1;
|
||||
maxRunningCount = Math.max(maxRunningCount, runningCount);
|
||||
await sleep(5);
|
||||
runningCount -= 1;
|
||||
return Promise.resolve(true);
|
||||
});
|
||||
const batches = new Array(101).fill(0).map(() => createModel({}));
|
||||
await service.sendBatches({
|
||||
email: createModel({}),
|
||||
batches,
|
||||
post: createModel({}),
|
||||
newsletter: createModel({})
|
||||
});
|
||||
sinon.assert.callCount(sendBatch, 101);
|
||||
const sendBatches = sendBatch.getCalls().map(call => call.args[0].batch);
|
||||
const deliveryTimes = sendBatch.getCalls().map(call => call.args[0].deliveryTime);
|
||||
deliveryTimes.forEach((time, i) => {
|
||||
assert(time instanceof Date);
|
||||
if (i > 0) {
|
||||
assert(time - deliveryTimes[i - 1] >= 1000);
|
||||
}
|
||||
});
|
||||
assert.deepEqual(sendBatches, batches);
|
||||
assert.equal(maxRunningCount, 2);
|
||||
});
|
||||
|
||||
it('Throws error if all batches fail', async function () {
|
||||
const service = new BatchSendingService({});
|
||||
const service = new BatchSendingService({
|
||||
sendingService: {
|
||||
getBatchDelay() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
let runningCount = 0;
|
||||
let maxRunningCount = 0;
|
||||
const sendBatch = sinon.stub(service, 'sendBatch').callsFake(async () => {
|
||||
@ -748,7 +803,13 @@ describe('Batch Sending Service', function () {
|
||||
});
|
||||
|
||||
it('Throws error if a single batch fails', async function () {
|
||||
const service = new BatchSendingService({});
|
||||
const service = new BatchSendingService({
|
||||
sendingService: {
|
||||
getBatchDelay() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
let runningCount = 0;
|
||||
let maxRunningCount = 0;
|
||||
let callCount = 0;
|
||||
|
@ -246,4 +246,23 @@ describe('Mailgun Email Provider', function () {
|
||||
assert.equal(provider.getMaximumRecipients(), 1000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBatchDelay', function () {
|
||||
let mailgunClient;
|
||||
let getBatchDelayStub;
|
||||
|
||||
it('returns 1000', function () {
|
||||
getBatchDelayStub = sinon.stub().returns(0);
|
||||
|
||||
mailgunClient = {
|
||||
getBatchDelay: getBatchDelayStub
|
||||
};
|
||||
|
||||
const provider = new MailgunEmailProvider({
|
||||
mailgunClient,
|
||||
errorHandler: () => {}
|
||||
});
|
||||
assert.equal(provider.getBatchDelay(), 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -391,4 +391,17 @@ describe('Sending service', function () {
|
||||
sinon.assert.calledOnce(emailProvider.getMaximumRecipients);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBatchDelay', function () {
|
||||
it('returns the batch delay of the email provider', function () {
|
||||
const emailProvider = {
|
||||
getBatchDelay: sinon.stub().returns(0)
|
||||
};
|
||||
const sendingService = new SendingService({
|
||||
emailProvider
|
||||
});
|
||||
assert.equal(sendingService.getBatchDelay(), 0);
|
||||
sinon.assert.calledOnce(emailProvider.getBatchDelay);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -327,4 +327,15 @@ module.exports = class MailgunClient {
|
||||
getBatchSize() {
|
||||
return this.#config.get('bulkEmail')?.batchSize ?? this.DEFAULT_BATCH_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configurated delay between batches in milliseconds
|
||||
*
|
||||
* Defaults to 0 (no delay) if not set
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
getBatchDelay() {
|
||||
return this.#config.get('bulkEmail')?.batchDelay ?? 0;
|
||||
}
|
||||
};
|
||||
|
@ -58,6 +58,22 @@ describe('MailgunClient', function () {
|
||||
assert(typeof mailgunClient.getBatchSize() === 'number');
|
||||
});
|
||||
|
||||
it('exports a number for configurable batch delay', 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,
|
||||
batchDelay: 1000
|
||||
});
|
||||
|
||||
const mailgunClient = new MailgunClient({config, settings});
|
||||
assert(typeof mailgunClient.getBatchDelay() === 'number');
|
||||
});
|
||||
|
||||
it('can connect via config', function () {
|
||||
const configStub = sinon.stub(config, 'get');
|
||||
configStub.withArgs('bulkEmail').returns({
|
||||
|
Loading…
Reference in New Issue
Block a user