|
|
@@ -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()
|