mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 20:03:12 +03:00
Added import threshold check to importer
refs https://github.com/TryGhost/Team/issues/912 - We need a way to check if the import threshold has been reached within the members importer. See more deets in refed issue
This commit is contained in:
parent
f90e36b816
commit
a90d996f33
@ -23,8 +23,9 @@ module.exports = class MembersCSVImporter {
|
|||||||
* @param {({name, at, job, data, offloaded}) => void} options.addJob - Method registering an async job
|
* @param {({name, at, job, data, offloaded}) => void} options.addJob - Method registering an async job
|
||||||
* @param {Object} options.knex - An instance of the Ghost Database connection
|
* @param {Object} options.knex - An instance of the Ghost Database connection
|
||||||
* @param {Function} options.urlFor - function generating urls
|
* @param {Function} options.urlFor - function generating urls
|
||||||
|
* @param {number} options.importThreshold - threshold to activate freeze flag if reached
|
||||||
*/
|
*/
|
||||||
constructor({storagePath, getTimezone, getMembersApi, sendEmail, isSet, addJob, knex, urlFor}) {
|
constructor({storagePath, getTimezone, getMembersApi, sendEmail, isSet, addJob, knex, urlFor, importThreshold}) {
|
||||||
this._storagePath = storagePath;
|
this._storagePath = storagePath;
|
||||||
this._getTimezone = getTimezone;
|
this._getTimezone = getTimezone;
|
||||||
this._getMembersApi = getMembersApi;
|
this._getMembersApi = getMembersApi;
|
||||||
@ -33,6 +34,7 @@ module.exports = class MembersCSVImporter {
|
|||||||
this._addJob = addJob;
|
this._addJob = addJob;
|
||||||
this._knex = knex;
|
this._knex = knex;
|
||||||
this._urlFor = urlFor;
|
this._urlFor = urlFor;
|
||||||
|
this._importThreshold = importThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -267,19 +269,27 @@ module.exports = class MembersCSVImporter {
|
|||||||
* @param {Object} config.LabelModel - instance of Ghosts Label model
|
* @param {Object} config.LabelModel - instance of Ghosts Label model
|
||||||
*/
|
*/
|
||||||
async process({pathToCSV, headerMapping, globalLabels, importLabel, user, LabelModel}) {
|
async process({pathToCSV, headerMapping, globalLabels, importLabel, user, LabelModel}) {
|
||||||
|
const meta = {};
|
||||||
const job = await this.prepare(pathToCSV, headerMapping, globalLabels);
|
const job = await this.prepare(pathToCSV, headerMapping, globalLabels);
|
||||||
|
|
||||||
|
if (this._isSet('checkEmailList') && this._importThreshold) {
|
||||||
|
meta.freeze = job.batches > this._importThreshold;
|
||||||
|
} else {
|
||||||
|
meta.freeze = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (job.batches <= 500 && !job.metadata.hasStripeData) {
|
if (job.batches <= 500 && !job.metadata.hasStripeData) {
|
||||||
const result = await this.perform(job.id);
|
const result = await this.perform(job.id);
|
||||||
const importLabelModel = result.imported ? await LabelModel.findOne(importLabel) : null;
|
const importLabelModel = result.imported ? await LabelModel.findOne(importLabel) : null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
meta: {
|
meta: Object.assign(meta, {
|
||||||
stats: {
|
stats: {
|
||||||
imported: result.imported,
|
imported: result.imported,
|
||||||
invalid: result.errors
|
invalid: result.errors
|
||||||
},
|
},
|
||||||
import_label: importLabelModel
|
import_label: importLabelModel
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
const emailRecipient = user.email;
|
const emailRecipient = user.email;
|
||||||
@ -310,7 +320,9 @@ module.exports = class MembersCSVImporter {
|
|||||||
offloaded: false
|
offloaded: false
|
||||||
});
|
});
|
||||||
|
|
||||||
return {};
|
return {
|
||||||
|
meta
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -61,12 +61,16 @@ describe('Importer', function () {
|
|||||||
findOne: sinon.stub().resolves(null)
|
findOne: sinon.stub().resolves(null)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isSetStub = sinon.stub()
|
||||||
|
.withArgs('checkEmailList')
|
||||||
|
.returns('true');
|
||||||
|
|
||||||
const importer = new MembersCSVImporter({
|
const importer = new MembersCSVImporter({
|
||||||
storagePath: csvPath,
|
storagePath: csvPath,
|
||||||
getTimezone: sinon.stub().returns('UTC'),
|
getTimezone: sinon.stub().returns('UTC'),
|
||||||
getMembersApi: () => membersApi,
|
getMembersApi: () => membersApi,
|
||||||
sendEmail: sinon.stub(),
|
sendEmail: sinon.stub(),
|
||||||
isSet: sinon.stub(),
|
isSet: isSetStub,
|
||||||
addJob: sinon.stub(),
|
addJob: sinon.stub(),
|
||||||
knex: knexStub,
|
knex: knexStub,
|
||||||
urlFor: sinon.stub()
|
urlFor: sinon.stub()
|
||||||
@ -92,6 +96,86 @@ describe('Importer', function () {
|
|||||||
should.exist(result.meta.stats.invalid);
|
should.exist(result.meta.stats.invalid);
|
||||||
should.equal(result.meta.import_label, null);
|
should.equal(result.meta.import_label, null);
|
||||||
|
|
||||||
|
// freeze not triggered if it's not provided
|
||||||
|
should.exist(result.meta.freeze);
|
||||||
|
result.meta.freeze.should.be.false();
|
||||||
|
|
||||||
|
fsWriteSpy.calledOnce.should.be.true();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should trigger a freeze when over the freeze threshold', async function () {
|
||||||
|
const defaultProduct = {
|
||||||
|
id: 'default_product_id'
|
||||||
|
};
|
||||||
|
|
||||||
|
const membersApi = {
|
||||||
|
productRepository: {
|
||||||
|
list: async () => {
|
||||||
|
return {
|
||||||
|
data: [defaultProduct]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
members: {
|
||||||
|
get: async () => {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
create: async (row) => {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const knexStub = {
|
||||||
|
transaction: sinon.stub().resolves({
|
||||||
|
rollback: () => {},
|
||||||
|
commit: () => {}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const LabelModelStub = {
|
||||||
|
findOne: sinon.stub().resolves(null)
|
||||||
|
};
|
||||||
|
|
||||||
|
const isSetStub = sinon.stub()
|
||||||
|
.withArgs('checkEmailList')
|
||||||
|
.returns('true');
|
||||||
|
|
||||||
|
const importer = new MembersCSVImporter({
|
||||||
|
storagePath: csvPath,
|
||||||
|
getTimezone: sinon.stub().returns('UTC'),
|
||||||
|
getMembersApi: () => membersApi,
|
||||||
|
sendEmail: sinon.stub(),
|
||||||
|
isSet: isSetStub,
|
||||||
|
addJob: sinon.stub(),
|
||||||
|
knex: knexStub,
|
||||||
|
urlFor: sinon.stub(),
|
||||||
|
importThreshold: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await importer.process({
|
||||||
|
pathToCSV: `${csvPath}/single-column-with-header.csv`,
|
||||||
|
headerMapping: {},
|
||||||
|
importLabel: {
|
||||||
|
name: 'test import'
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
email: 'test@example.com'
|
||||||
|
},
|
||||||
|
LabelModel: LabelModelStub
|
||||||
|
});
|
||||||
|
|
||||||
|
should.exist(result.meta);
|
||||||
|
should.exist(result.meta.stats);
|
||||||
|
should.exist(result.meta.stats.imported);
|
||||||
|
result.meta.stats.imported.should.equal(2);
|
||||||
|
|
||||||
|
should.exist(result.meta.stats.invalid);
|
||||||
|
should.equal(result.meta.import_label, null);
|
||||||
|
|
||||||
|
should.exist(result.meta.freeze);
|
||||||
|
result.meta.freeze.should.be.true();
|
||||||
|
|
||||||
fsWriteSpy.calledOnce.should.be.true();
|
fsWriteSpy.calledOnce.should.be.true();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user