mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-30 14:22:07 +03:00
567eb6325f
refs https://github.com/TryGhost/Ghost/issues/12421 requires https://github.com/TryGhost/Ghost/pull/12457 - updates stats aggregator to calculate and store an open rate for each member - uses two queries because I couldn't find a reasonable approach to perform the update in a single query as per the email aggregation - benchmarked locally at <1sec/1000members - will not store an open rate unless the number of tracked emails sent to a member is above a certain threshold (defaults to 5) to avoid new members being heavily weighted - fixes typo in EmailAnalytics that was stopping member stats from being aggregated
74 lines
2.7 KiB
JavaScript
74 lines
2.7 KiB
JavaScript
const logging = require('../../../../shared/logging');
|
|
const {parentPort} = require('bthreads');
|
|
const sentry = require('../../../../shared/sentry');
|
|
const debug = require('ghost-ignition').debug('jobs:email-analytics:fetch-latest');
|
|
|
|
// recurring job to fetch analytics since the most recently seen event timestamp
|
|
|
|
// Exit early when cancelled to prevent stalling shutdown. No cleanup needed when cancelling as everything is idempotent and will pick up
|
|
// where it left off on next run
|
|
function cancel() {
|
|
logging.info('Email analytics fetch-latest job cancelled before completion');
|
|
|
|
if (parentPort) {
|
|
parentPort.postMessage('cancelled');
|
|
} else {
|
|
setTimeout(() => {
|
|
process.exit(0);
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
if (parentPort) {
|
|
parentPort.once('message', (message) => {
|
|
if (message === 'cancel') {
|
|
return cancel();
|
|
}
|
|
});
|
|
}
|
|
|
|
(async () => {
|
|
try {
|
|
const models = require('../../../models');
|
|
const settingsService = require('../../settings');
|
|
|
|
// must be initialized before emailAnalyticsService is required otherwise
|
|
// requires are in the wrong order and settingsCache will always be empty
|
|
await models.init();
|
|
await settingsService.init();
|
|
|
|
const emailAnalyticsService = require('../');
|
|
|
|
const fetchStartDate = new Date();
|
|
debug('Starting email analytics fetch of latest events');
|
|
const eventStats = await emailAnalyticsService.fetchLatest();
|
|
const fetchEndDate = new Date();
|
|
debug(`Finished fetching ${eventStats.totalEvents} analytics events in ${fetchEndDate - fetchStartDate}ms`);
|
|
|
|
const aggregateStartDate = new Date();
|
|
debug(`Starting email analytics aggregation for ${eventStats.emailIds.length} emails`);
|
|
await emailAnalyticsService.aggregateStats(eventStats);
|
|
const aggregateEndDate = new Date();
|
|
debug(`Finished aggregating email analytics in ${aggregateEndDate - aggregateStartDate}ms`);
|
|
|
|
logging.info(`Fetched ${eventStats.totalEvents} events and aggregated stats for ${eventStats.emailIds.length} emails and ${eventStats.memberIds.length} members in ${aggregateEndDate - fetchStartDate}ms`);
|
|
|
|
if (parentPort) {
|
|
parentPort.postMessage('done');
|
|
} else {
|
|
// give the logging pipes time finish writing before exit
|
|
setTimeout(() => {
|
|
process.exit(0);
|
|
}, 1000);
|
|
}
|
|
} catch (error) {
|
|
logging.error(error);
|
|
sentry.captureException(error);
|
|
|
|
// give the logging pipes time finish writing before exit
|
|
setTimeout(() => {
|
|
process.exit(1);
|
|
}, 1000);
|
|
}
|
|
})();
|