This repository has been archived by the owner on Sep 20, 2023. It is now read-only.
/
updateCampaigns.js
120 lines (104 loc) · 3.4 KB
/
updateCampaigns.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Runs periodically and scans active campaigns to update:
// - capUsed: budget used so far.
// - rewardStatus: set to ReadyForCalculation once campaign is over and
// all events during the campaign time window have been verified.
'use strict'
const Logger = require('logplease')
const Sequelize = require('sequelize')
const enums = require('../enums')
const db = require('../models')
const parseArgv = require('../util/args')
Logger.setLogLevel(process.env.LOG_LEVEL || 'INFO')
const logger = Logger.create('verifyEvents', { showTimestamp: false })
class UpdateCampaigns {
constructor(config) {
this.config = config
this.stats = {
numProcessed: 0,
numStatusReady: 0,
numUsedCapUpdated: 0
}
}
// TODO(franck): IMPLEMENT ME
async _updateCapUsed(campaign) {
logger.debug(`Checking capUsed for campaign ${campaign.id}`)
return 0
}
// TODO(franck): Update this logic:
// - The listener logs events for all users, not only enrolled.
// - But the verfifyEvent job only verifies event that belong to enrolled users.
// => The check here should only consider events for enrolled users.
async _allEventsVerified(cutoffDate) {
const events = await db.GrowthEvent.findAll({
where: {
status: enums.GrowthEventStatuses.Logged,
createdAt: { [Sequelize.Op.lt]: cutoffDate }
}
})
return events.length === 0
}
async process() {
const now = new Date()
// Look for campaigns that have started with status NotReady.
const campaigns = await db.GrowthCampaign.findAll({
where: {
rewardStatus: enums.GrowthCampaignRewardStatuses.NotReady,
startDate: { [Sequelize.Op.lt]: now }
}
})
for (const campaign of campaigns) {
// Update cap used.
await this._updateCapUsed(campaign)
// Determine if campaign's status should be set to ReadyForCalculation.
// Conditions:
// a) Campaign over
// b) All events for the campaign's period have been verified.
const readyForCalculation =
campaign.endDate < now &&
(await this._allEventsVerified(campaign.endDate))
if (readyForCalculation) {
if (this.config.persist) {
await campaign.update({
rewardStatus: enums.GrowthCampaignRewardStatuses.ReadyForCalculation
})
} else {
logger.info(
`Would mark campaign ${campaign.id} as ReadyForCalculation`
)
}
this.stats.numStatusReady++
}
this.stats.numProcessed++
}
}
}
module.exports = UpdateCampaigns
/**
* MAIN
*/
if (require.main === module) {
logger.info('Starting campaigns update job.')
const args = parseArgv()
const config = {
// By default run in dry-run mode unless explicitly specified using persist.
persist: args['--persist'] ? args['--persist'] : false
}
logger.info('Config:')
logger.info(config)
const job = new UpdateCampaigns(config)
job
.process()
.then(() => {
logger.info('Campaigns update stats:')
logger.info(' Num processed: ', job.stats.numProcessed)
logger.info(' Num marked as calc. ready:', job.stats.numStatusReady)
logger.info(' Num usedCap updated: ', job.stats.numUsedCapUpdated)
logger.info('Finished')
process.exit()
})
.catch(err => {
logger.error('Job failed: ', err)
logger.error('Exiting')
process.exit(-1)
})
}