2020-10-07 13:17:49 +00:00
|
|
|
const { db, waitForDb } = require('../app/src/infrastructure/mongodb')
|
2019-12-05 13:57:58 +00:00
|
|
|
const minimist = require('minimist')
|
|
|
|
const _ = require('lodash')
|
|
|
|
const async = require('async')
|
|
|
|
const FeaturesUpdater = require('../app/src/Features/Subscription/FeaturesUpdater')
|
|
|
|
const UserFeaturesUpdater = require('../app/src/Features/Subscription/UserFeaturesUpdater')
|
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
const ScriptLogger = {
|
|
|
|
checkedUsersCount: 0,
|
|
|
|
mismatchUsersCount: 0,
|
|
|
|
allDaysSinceLastLoggedIn: [],
|
|
|
|
allMismatchReasons: {},
|
|
|
|
|
|
|
|
recordMismatch: (user, mismatchReasons) => {
|
|
|
|
const mismatchReasonsString = JSON.stringify(mismatchReasons)
|
|
|
|
if (ScriptLogger.allMismatchReasons[mismatchReasonsString]) {
|
|
|
|
ScriptLogger.allMismatchReasons[mismatchReasonsString].push(user._id)
|
|
|
|
} else {
|
|
|
|
ScriptLogger.allMismatchReasons[mismatchReasonsString] = [user._id]
|
2019-12-16 10:55:10 +00:00
|
|
|
}
|
2019-12-05 13:57:58 +00:00
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
ScriptLogger.mismatchUsersCount += 1
|
2019-12-05 13:57:58 +00:00
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
if (user.lastLoggedIn) {
|
|
|
|
let daysSinceLastLoggedIn =
|
|
|
|
(new Date() - user.lastLoggedIn) / 1000 / 3600 / 24
|
|
|
|
ScriptLogger.allDaysSinceLastLoggedIn.push(daysSinceLastLoggedIn)
|
|
|
|
}
|
|
|
|
},
|
2019-12-05 13:57:58 +00:00
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
printProgress: () => {
|
|
|
|
console.warn(
|
2020-12-15 10:23:54 +00:00
|
|
|
`Users checked: ${ScriptLogger.checkedUsersCount}. Mismatches: ${ScriptLogger.mismatchUsersCount}`
|
2020-01-07 11:03:14 +00:00
|
|
|
)
|
|
|
|
},
|
2019-12-05 13:57:58 +00:00
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
printSummary: () => {
|
|
|
|
console.log('All Mismatch Reasons:', ScriptLogger.allMismatchReasons)
|
|
|
|
console.log('Mismatch Users Count', ScriptLogger.mismatchUsersCount)
|
|
|
|
console.log(
|
|
|
|
'Average Last Logged In (Days):',
|
|
|
|
_.sum(ScriptLogger.allDaysSinceLastLoggedIn) /
|
|
|
|
ScriptLogger.allDaysSinceLastLoggedIn.length
|
|
|
|
)
|
|
|
|
console.log(
|
|
|
|
'Recent Logged In (Last 7 Days):',
|
|
|
|
_.filter(ScriptLogger.allDaysSinceLastLoggedIn, a => a < 7).length
|
|
|
|
)
|
|
|
|
console.log(
|
|
|
|
'Recent Logged In (Last 30 Days):',
|
|
|
|
_.filter(ScriptLogger.allDaysSinceLastLoggedIn, a => a < 30).length
|
|
|
|
)
|
2019-12-05 13:57:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const checkAndUpdateUser = (user, callback) =>
|
|
|
|
FeaturesUpdater._computeFeatures(user._id, (error, freshFeatures) => {
|
|
|
|
if (error) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
let mismatchReasons = FeaturesUpdater.compareFeatures(
|
|
|
|
user.features,
|
|
|
|
freshFeatures
|
|
|
|
)
|
2019-12-10 08:10:14 +00:00
|
|
|
if (Object.keys(mismatchReasons).length === 0) {
|
2019-12-05 13:57:58 +00:00
|
|
|
// features are matching; nothing else to do
|
|
|
|
return callback()
|
|
|
|
}
|
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
ScriptLogger.recordMismatch(user, mismatchReasons)
|
2019-12-05 13:57:58 +00:00
|
|
|
|
|
|
|
if (!COMMIT) {
|
|
|
|
// not saving features; nothing else to do
|
|
|
|
return callback()
|
|
|
|
}
|
|
|
|
|
2019-12-16 10:55:10 +00:00
|
|
|
UserFeaturesUpdater.overrideFeatures(user._id, freshFeatures, callback)
|
2019-12-05 13:57:58 +00:00
|
|
|
})
|
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
const checkAndUpdateUsers = (users, callback) =>
|
|
|
|
async.eachLimit(users, ASYNC_LIMIT, checkAndUpdateUser, callback)
|
2019-12-05 13:57:58 +00:00
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
const loopForUsers = (skip, callback) => {
|
2019-12-05 13:57:58 +00:00
|
|
|
db.users
|
2020-10-07 13:17:49 +00:00
|
|
|
.find({})
|
|
|
|
.project({ features: 1, lastLoggedIn: 1 })
|
2019-12-10 08:10:14 +00:00
|
|
|
.sort('_id')
|
2020-01-07 11:03:14 +00:00
|
|
|
.skip(skip)
|
2020-10-07 13:17:49 +00:00
|
|
|
.limit(FETCH_LIMIT)
|
|
|
|
.toArray((error, users) => {
|
2019-12-05 13:57:58 +00:00
|
|
|
if (error) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (users.length === 0) {
|
2020-01-07 11:03:14 +00:00
|
|
|
console.warn('DONE')
|
2019-12-05 13:57:58 +00:00
|
|
|
return callback()
|
|
|
|
}
|
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
checkAndUpdateUsers(users, error => {
|
2019-12-05 13:57:58 +00:00
|
|
|
if (error) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
2020-01-07 11:03:14 +00:00
|
|
|
ScriptLogger.checkedUsersCount += users.length
|
|
|
|
retryCounter = 0
|
|
|
|
ScriptLogger.printProgress()
|
|
|
|
ScriptLogger.printSummary()
|
|
|
|
loopForUsers(MONGO_SKIP + ScriptLogger.checkedUsersCount, callback)
|
2019-12-05 13:57:58 +00:00
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
let retryCounter = 0
|
2019-12-05 13:57:58 +00:00
|
|
|
const run = () =>
|
2020-01-07 11:03:14 +00:00
|
|
|
loopForUsers(MONGO_SKIP + ScriptLogger.checkedUsersCount, error => {
|
2019-12-05 13:57:58 +00:00
|
|
|
if (error) {
|
2020-01-07 11:03:14 +00:00
|
|
|
if (retryCounter < 3) {
|
|
|
|
console.error(error)
|
|
|
|
retryCounter += 1
|
|
|
|
console.warn(`RETRYING IN 60 SECONDS. (${retryCounter}/3)`)
|
|
|
|
return setTimeout(run, 6000)
|
|
|
|
}
|
2019-12-05 13:57:58 +00:00
|
|
|
throw error
|
|
|
|
}
|
|
|
|
process.exit()
|
|
|
|
})
|
|
|
|
|
2020-01-07 11:03:14 +00:00
|
|
|
let FETCH_LIMIT, ASYNC_LIMIT, COMMIT, MONGO_SKIP
|
2019-12-05 13:57:58 +00:00
|
|
|
const setup = () => {
|
|
|
|
const argv = minimist(process.argv.slice(2))
|
|
|
|
FETCH_LIMIT = argv.fetch ? argv.fetch : 100
|
|
|
|
ASYNC_LIMIT = argv.async ? argv.async : 10
|
2020-01-07 11:03:14 +00:00
|
|
|
MONGO_SKIP = argv.skip ? argv.skip : 0
|
2019-12-05 13:57:58 +00:00
|
|
|
COMMIT = argv.commit !== undefined
|
|
|
|
if (!COMMIT) {
|
2020-01-07 11:03:14 +00:00
|
|
|
console.warn('Doing dry run without --commit')
|
|
|
|
}
|
|
|
|
if (MONGO_SKIP) {
|
|
|
|
console.warn(`Skipping first ${MONGO_SKIP} records`)
|
2019-12-05 13:57:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-07 13:17:49 +00:00
|
|
|
waitForDb().then(() => {
|
|
|
|
setup()
|
|
|
|
run()
|
|
|
|
})
|