mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 05:37:34 +03:00
Fixed email analytics require error
refs https://github.com/TryGhost/Ghost/pull/12541 refs https://github.com/TryGhost/Ghost/pull/12689 - the analytics job had been switched to create it's own instance of EmailAnalyticsService to avoid requiring logging but the analytics extraction branch was created before this change and wasn't picked up when merging - pulled `queries` option object into a separate file for re-use - updated `fetchLatest` job to conform to extracted library interface
This commit is contained in:
parent
11802ebee0
commit
a06064b115
@ -1,4 +1,3 @@
|
|||||||
const _ = require('lodash');
|
|
||||||
const config = require('../../../shared/config');
|
const config = require('../../../shared/config');
|
||||||
const logging = require('../../../shared/logging');
|
const logging = require('../../../shared/logging');
|
||||||
const db = require('../../data/db');
|
const db = require('../../data/db');
|
||||||
@ -6,9 +5,7 @@ const settings = require('../settings/cache');
|
|||||||
const {EmailAnalyticsService} = require('@tryghost/email-analytics-service');
|
const {EmailAnalyticsService} = require('@tryghost/email-analytics-service');
|
||||||
const EventProcessor = require('./lib/event-processor');
|
const EventProcessor = require('./lib/event-processor');
|
||||||
const MailgunProvider = require('@tryghost/email-analytics-provider-mailgun');
|
const MailgunProvider = require('@tryghost/email-analytics-provider-mailgun');
|
||||||
const debug = require('ghost-ignition').debug('services:email-analytics');
|
const queries = require('../lib/queries');
|
||||||
|
|
||||||
const MIN_EMAIL_COUNT_FOR_OPEN_RATE = 5;
|
|
||||||
|
|
||||||
module.exports = new EmailAnalyticsService({
|
module.exports = new EmailAnalyticsService({
|
||||||
config,
|
config,
|
||||||
@ -18,57 +15,5 @@ module.exports = new EmailAnalyticsService({
|
|||||||
providers: [
|
providers: [
|
||||||
new MailgunProvider({config, settings, logging})
|
new MailgunProvider({config, settings, logging})
|
||||||
],
|
],
|
||||||
queries: {
|
queries
|
||||||
async shouldFetchStats() {
|
|
||||||
// don't fetch stats from Mailgun if we haven't sent any emails
|
|
||||||
const [emailCount] = await db.knex('emails').count('id as count');
|
|
||||||
return emailCount && emailCount.count > 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
async getLastSeenEventTimestamp() {
|
|
||||||
const startDate = new Date();
|
|
||||||
|
|
||||||
// three separate queries is much faster than using max/greatest (with coalesce to handle nulls) across columns
|
|
||||||
const {maxDeliveredAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(delivered_at) as maxDeliveredAt')).first() || {};
|
|
||||||
const {maxOpenedAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(opened_at) as maxOpenedAt')).first() || {};
|
|
||||||
const {maxFailedAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(failed_at) as maxFailedAt')).first() || {};
|
|
||||||
|
|
||||||
const lastSeenEventTimestamp = _.max([maxDeliveredAt, maxOpenedAt, maxFailedAt]);
|
|
||||||
debug(`getLastSeenEventTimestamp: finished in ${Date.now() - startDate}ms`);
|
|
||||||
|
|
||||||
return lastSeenEventTimestamp;
|
|
||||||
},
|
|
||||||
|
|
||||||
async aggregateEmailStats(emailId) {
|
|
||||||
await db.knex('emails').update({
|
|
||||||
delivered_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND delivered_at IS NOT NULL)`, [emailId]),
|
|
||||||
opened_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND opened_at IS NOT NULL)`, [emailId]),
|
|
||||||
failed_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND failed_at IS NOT NULL)`, [emailId])
|
|
||||||
}).where('id', emailId);
|
|
||||||
},
|
|
||||||
|
|
||||||
async aggregateMemberStats(memberId) {
|
|
||||||
const {trackedEmailCount} = await db.knex('email_recipients')
|
|
||||||
.select(db.knex.raw('COUNT(email_recipients.id) as trackedEmailCount'))
|
|
||||||
.leftJoin('emails', 'email_recipients.email_id', 'emails.id')
|
|
||||||
.where('email_recipients.member_id', memberId)
|
|
||||||
.where('emails.track_opens', true)
|
|
||||||
.first() || {};
|
|
||||||
|
|
||||||
const updateQuery = {
|
|
||||||
email_count: db.knex.raw('(SELECT COUNT(id) FROM email_recipients WHERE member_id = ?)', [memberId]),
|
|
||||||
email_opened_count: db.knex.raw('(SELECT COUNT(id) FROM email_recipients WHERE member_id = ? AND opened_at IS NOT NULL)', [memberId])
|
|
||||||
};
|
|
||||||
|
|
||||||
if (trackedEmailCount >= MIN_EMAIL_COUNT_FOR_OPEN_RATE) {
|
|
||||||
updateQuery.email_open_rate = db.knex.raw(`
|
|
||||||
ROUND(((SELECT COUNT(id) FROM email_recipients WHERE member_id = ? AND opened_at IS NOT NULL) * 1.0 / ? * 100), 0)
|
|
||||||
`, [memberId, trackedEmailCount]);
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.knex('members')
|
|
||||||
.update(updateQuery)
|
|
||||||
.where('id', memberId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
@ -56,13 +56,20 @@ if (parentPort) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const EmailAnalyticsService = require('../email-analytics');
|
const {EmailAnalyticsService} = require('@tryghost/email-analytics-service');
|
||||||
|
const EventProcessor = require('../lib/event-processor');
|
||||||
|
const MailgunProvider = require('@tryghost/email-analytics-provider-mailgun');
|
||||||
|
const queries = require('../lib/queries');
|
||||||
|
|
||||||
const emailAnalyticsService = new EmailAnalyticsService({
|
const emailAnalyticsService = new EmailAnalyticsService({
|
||||||
config,
|
config,
|
||||||
db,
|
|
||||||
settings,
|
settings,
|
||||||
logging
|
logging,
|
||||||
|
eventProcessor: new EventProcessor({db, logging}),
|
||||||
|
providers: [
|
||||||
|
new MailgunProvider({config, settings, logging})
|
||||||
|
],
|
||||||
|
queries
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchStartDate = new Date();
|
const fetchStartDate = new Date();
|
||||||
|
59
core/server/services/email-analytics/lib/queries.js
Normal file
59
core/server/services/email-analytics/lib/queries.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
const debug = require('ghost-ignition').debug('services:email-analytics');
|
||||||
|
const db = require('../../../data/db');
|
||||||
|
|
||||||
|
const MIN_EMAIL_COUNT_FOR_OPEN_RATE = 5;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
async shouldFetchStats() {
|
||||||
|
// don't fetch stats from Mailgun if we haven't sent any emails
|
||||||
|
const [emailCount] = await db.knex('emails').count('id as count');
|
||||||
|
return emailCount && emailCount.count > 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
async getLastSeenEventTimestamp() {
|
||||||
|
const startDate = new Date();
|
||||||
|
|
||||||
|
// three separate queries is much faster than using max/greatest (with coalesce to handle nulls) across columns
|
||||||
|
const {maxDeliveredAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(delivered_at) as maxDeliveredAt')).first() || {};
|
||||||
|
const {maxOpenedAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(opened_at) as maxOpenedAt')).first() || {};
|
||||||
|
const {maxFailedAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(failed_at) as maxFailedAt')).first() || {};
|
||||||
|
|
||||||
|
const lastSeenEventTimestamp = _.max([maxDeliveredAt, maxOpenedAt, maxFailedAt]);
|
||||||
|
debug(`getLastSeenEventTimestamp: finished in ${Date.now() - startDate}ms`);
|
||||||
|
|
||||||
|
return lastSeenEventTimestamp;
|
||||||
|
},
|
||||||
|
|
||||||
|
async aggregateEmailStats(emailId) {
|
||||||
|
await db.knex('emails').update({
|
||||||
|
delivered_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND delivered_at IS NOT NULL)`, [emailId]),
|
||||||
|
opened_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND opened_at IS NOT NULL)`, [emailId]),
|
||||||
|
failed_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND failed_at IS NOT NULL)`, [emailId])
|
||||||
|
}).where('id', emailId);
|
||||||
|
},
|
||||||
|
|
||||||
|
async aggregateMemberStats(memberId) {
|
||||||
|
const {trackedEmailCount} = await db.knex('email_recipients')
|
||||||
|
.select(db.knex.raw('COUNT(email_recipients.id) as trackedEmailCount'))
|
||||||
|
.leftJoin('emails', 'email_recipients.email_id', 'emails.id')
|
||||||
|
.where('email_recipients.member_id', memberId)
|
||||||
|
.where('emails.track_opens', true)
|
||||||
|
.first() || {};
|
||||||
|
|
||||||
|
const updateQuery = {
|
||||||
|
email_count: db.knex.raw('(SELECT COUNT(id) FROM email_recipients WHERE member_id = ?)', [memberId]),
|
||||||
|
email_opened_count: db.knex.raw('(SELECT COUNT(id) FROM email_recipients WHERE member_id = ? AND opened_at IS NOT NULL)', [memberId])
|
||||||
|
};
|
||||||
|
|
||||||
|
if (trackedEmailCount >= MIN_EMAIL_COUNT_FOR_OPEN_RATE) {
|
||||||
|
updateQuery.email_open_rate = db.knex.raw(`
|
||||||
|
ROUND(((SELECT COUNT(id) FROM email_recipients WHERE member_id = ? AND opened_at IS NOT NULL) * 1.0 / ? * 100), 0)
|
||||||
|
`, [memberId, trackedEmailCount]);
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.knex('members')
|
||||||
|
.update(updateQuery)
|
||||||
|
.where('id', memberId);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user