diff --git a/apps/platform/src/campaigns/CampaignInteractJob.ts b/apps/platform/src/campaigns/CampaignInteractJob.ts index 1608ec9b..53f56546 100644 --- a/apps/platform/src/campaigns/CampaignInteractJob.ts +++ b/apps/platform/src/campaigns/CampaignInteractJob.ts @@ -1,7 +1,8 @@ +import App from '../app' import { Job } from '../queue' import { unsubscribe } from '../subscriptions/SubscriptionService' import { CampaignSend } from './Campaign' -import { getCampaignSend, updateCampaignSend } from './CampaignService' +import { CacheKeys, getCampaignSend, updateCampaignSend } from './CampaignService' interface CampaignIteraction { user_id: number @@ -25,6 +26,7 @@ export default class CampaignInteractJob extends Job { if (type === 'opened' && !send.opened_at) { await updateCampaignSend(send.id, { opened_at: new Date() }) + await App.main.redis.sadd(CacheKeys.pendingStats, campaign_id) } if (type === 'clicked') { diff --git a/apps/platform/src/campaigns/CampaignService.ts b/apps/platform/src/campaigns/CampaignService.ts index 0cca7bce..ed1c31bf 100644 --- a/apps/platform/src/campaigns/CampaignService.ts +++ b/apps/platform/src/campaigns/CampaignService.ts @@ -23,6 +23,10 @@ import Template from '../render/Template' import { differenceInDays, subDays } from 'date-fns' import { raw } from '../core/Model' +export const CacheKeys = { + pendingStats: 'campaigns:pending_stats', +} + export const pagedCampaigns = async (params: PageParams, projectId: number) => { const result = await Campaign.search( { ...params, fields: ['name'] }, diff --git a/apps/platform/src/campaigns/CampaignStateJob.ts b/apps/platform/src/campaigns/CampaignStateJob.ts index 929f30b8..3d14ddd6 100644 --- a/apps/platform/src/campaigns/CampaignStateJob.ts +++ b/apps/platform/src/campaigns/CampaignStateJob.ts @@ -1,7 +1,8 @@ import { subDays } from 'date-fns' import { Job } from '../queue' import Campaign from './Campaign' -import { updateCampaignProgress } from './CampaignService' +import { CacheKeys, updateCampaignProgress } from './CampaignService' +import App from '../app' export default class CampaignStateJob extends Job { static $name = 'campaign_state_job' @@ -9,16 +10,20 @@ export default class CampaignStateJob extends Job { static async handler() { // Fetch anything that is currently running or has finished - // within the last two days + // within the last two days or has activity + const openedCampaignIds = await App.main.redis.smembers(CacheKeys.pendingStats) const campaigns = await Campaign.query() .whereIn('state', ['scheduled', 'running']) .orWhere(function(qb) { qb.where('state', 'finished') .where('send_at', '>', subDays(Date.now(), 2)) }) + .orWhereIn('id', openedCampaignIds.map(id => parseInt(id, 10))) as Campaign[] for (const campaign of campaigns) { await updateCampaignProgress(campaign) } + + await App.main.redis.srem(CacheKeys.pendingStats, ...campaigns.map(c => c.id)) } }