mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-04 23:27:13 +00:00
Merge pull request #2664 from overleaf/ta-resync-subscriptions
Add Script To Resync Recurly Subscriptions GitOrigin-RevId: 95f1263e5b3b782ec70d3d135f3c1866548a048f
This commit is contained in:
parent
30763043d1
commit
50ccc90815
1 changed files with 164 additions and 0 deletions
164
services/web/scripts/recurly/resync_subscriptions.js
Normal file
164
services/web/scripts/recurly/resync_subscriptions.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
const { Subscription } = require('../../app/src/models/Subscription')
|
||||
const RecurlyWrapper = require('../../app/src/Features/Subscription/RecurlyWrapper')
|
||||
const SubscriptionUpdater = require('../../app/src/Features/Subscription/SubscriptionUpdater')
|
||||
const async = require('async')
|
||||
const minimist = require('minimist')
|
||||
|
||||
const ScriptLogger = {
|
||||
checkedSubscriptionsCount: 0,
|
||||
mismatchSubscriptionsCount: 0,
|
||||
allMismatchReasons: {},
|
||||
|
||||
recordMismatch: (subscription, recurlySubscription) => {
|
||||
const mismatchReasons = {}
|
||||
if (subscription.planCode !== recurlySubscription.plan.plan_code) {
|
||||
mismatchReasons['recurlyPlan'] = recurlySubscription.plan.plan_code
|
||||
mismatchReasons['olPlan'] = subscription.planCode
|
||||
}
|
||||
if (recurlySubscription.state === 'expired') {
|
||||
mismatchReasons['state'] = 'expired'
|
||||
}
|
||||
|
||||
if (!Object.keys(mismatchReasons).length) {
|
||||
return
|
||||
}
|
||||
|
||||
ScriptLogger.mismatchSubscriptionsCount += 1
|
||||
const mismatchReasonsString = JSON.stringify(mismatchReasons)
|
||||
if (ScriptLogger.allMismatchReasons[mismatchReasonsString]) {
|
||||
ScriptLogger.allMismatchReasons[mismatchReasonsString].push(
|
||||
subscription._id
|
||||
)
|
||||
} else {
|
||||
ScriptLogger.allMismatchReasons[mismatchReasonsString] = [
|
||||
subscription._id
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
printProgress: () => {
|
||||
console.warn(
|
||||
`Subscriptions checked: ${
|
||||
ScriptLogger.checkedSubscriptionsCount
|
||||
}. Mismatches: ${ScriptLogger.mismatchSubscriptionsCount}`
|
||||
)
|
||||
},
|
||||
|
||||
printSummary: () => {
|
||||
console.log('All Mismatch Reasons:', ScriptLogger.allMismatchReasons)
|
||||
console.log(
|
||||
'Mismatch Subscriptions Count',
|
||||
ScriptLogger.mismatchSubscriptionsCount
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const slowCallback = callback => setTimeout(callback, 80)
|
||||
|
||||
const handleAPIError = (subscriptionId, error, callback) => {
|
||||
console.warn(`Errors with subscription id=${subscriptionId}:`, error)
|
||||
if (typeof error === 'string' && error.match(/429$/)) {
|
||||
return setTimeout(callback, 1000 * 60 * 5)
|
||||
}
|
||||
slowCallback(callback)
|
||||
}
|
||||
|
||||
const syncSubscription = (subscription, callback) => {
|
||||
RecurlyWrapper.getSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
(error, recurlySubscription) => {
|
||||
if (error) {
|
||||
return handleAPIError(subscription._id, error, callback)
|
||||
}
|
||||
|
||||
ScriptLogger.recordMismatch(subscription, recurlySubscription)
|
||||
|
||||
if (!COMMIT) {
|
||||
return callback()
|
||||
}
|
||||
|
||||
SubscriptionUpdater._updateSubscriptionFromRecurly(
|
||||
recurlySubscription,
|
||||
subscription,
|
||||
{},
|
||||
error => {
|
||||
if (error) {
|
||||
return handleAPIError(subscription._id, error, callback)
|
||||
}
|
||||
slowCallback(callback)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const syncSubscriptions = (subscriptions, callback) => {
|
||||
async.eachLimit(subscriptions, ASYNC_LIMIT, syncSubscription, callback)
|
||||
}
|
||||
|
||||
const loopForSubscriptions = (skip, callback) => {
|
||||
Subscription.find({ recurlySubscription_id: { $exists: true } })
|
||||
.sort('_id')
|
||||
.skip(skip)
|
||||
.limit(FETCH_LIMIT)
|
||||
.exec((error, subscriptions) => {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
if (subscriptions.length === 0) {
|
||||
console.warn('DONE')
|
||||
return callback()
|
||||
}
|
||||
|
||||
syncSubscriptions(subscriptions, error => {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
ScriptLogger.checkedSubscriptionsCount += subscriptions.length
|
||||
retryCounter = 0
|
||||
ScriptLogger.printProgress()
|
||||
ScriptLogger.printSummary()
|
||||
loopForSubscriptions(
|
||||
MONGO_SKIP + ScriptLogger.checkedSubscriptionsCount,
|
||||
callback
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let retryCounter = 0
|
||||
const run = () =>
|
||||
loopForSubscriptions(
|
||||
MONGO_SKIP + ScriptLogger.checkedSubscriptionsCount,
|
||||
error => {
|
||||
if (error) {
|
||||
if (retryCounter < 3) {
|
||||
console.error(error)
|
||||
retryCounter += 1
|
||||
console.warn(`RETRYING IN 60 SECONDS. (${retryCounter}/3)`)
|
||||
return setTimeout(run, 60000)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
process.exit()
|
||||
}
|
||||
)
|
||||
|
||||
let FETCH_LIMIT, ASYNC_LIMIT, COMMIT, MONGO_SKIP
|
||||
const setup = () => {
|
||||
const argv = minimist(process.argv.slice(2))
|
||||
FETCH_LIMIT = argv.fetch ? argv.fetch : 100
|
||||
ASYNC_LIMIT = argv.async ? argv.async : 10
|
||||
MONGO_SKIP = argv.skip ? argv.skip : 0
|
||||
COMMIT = argv.commit !== undefined
|
||||
if (!COMMIT) {
|
||||
console.warn('Doing dry run without --commit')
|
||||
}
|
||||
if (MONGO_SKIP) {
|
||||
console.warn(`Skipping first ${MONGO_SKIP} records`)
|
||||
}
|
||||
}
|
||||
|
||||
setup()
|
||||
run()
|
Loading…
Reference in a new issue