| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- const { Subscription } = require('../../app/src/models/Subscription')
- const RecurlyWrapper = require('../../app/src/Features/Subscription/RecurlyWrapper')
- const SubscriptionUpdater = require('../../app/src/Features/Subscription/SubscriptionUpdater')
- const minimist = require('minimist')
- const { setTimeout } = require('node:timers/promises')
- // make sure all `allMismatchReasons` are displayed in the output
- const util = require('util')
- const pLimit = require('p-limit')
- const { waitForDb } = require('../../app/src/infrastructure/mongodb')
- util.inspect.defaultOptions.maxArrayLength = null
- 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({
- id: subscription._id,
- name: subscription.planCode,
- })
- } else {
- ScriptLogger.allMismatchReasons[mismatchReasonsString] = [
- {
- id: subscription._id,
- name: subscription.planCode,
- },
- ]
- }
- },
- 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 handleSyncSubscriptionError = async (subscription, error) => {
- console.warn(`Errors with subscription id=${subscription._id}:`, error)
- if (typeof error === 'string' && error.match(/429$/)) {
- await setTimeout(1000 * 60 * 5)
- return
- }
- if (typeof error === 'string' && error.match(/5\d\d$/)) {
- await setTimeout(1000 * 60)
- await syncSubscription(subscription)
- return
- }
- await setTimeout(80)
- }
- const syncSubscription = async subscription => {
- let recurlySubscription
- try {
- recurlySubscription = await RecurlyWrapper.promises.getSubscription(
- subscription.recurlySubscription_id
- )
- } catch (error) {
- await handleSyncSubscriptionError(subscription, error)
- return
- }
- ScriptLogger.recordMismatch(subscription, recurlySubscription)
- if (!COMMIT) {
- return
- }
- try {
- await SubscriptionUpdater.promises.updateSubscriptionFromRecurly(
- recurlySubscription,
- subscription,
- {}
- )
- } catch (error) {
- await handleSyncSubscriptionError(subscription, error)
- return
- }
- await setTimeout(80)
- }
- const syncSubscriptions = async subscriptions => {
- const limit = pLimit(ASYNC_LIMIT)
- return await Promise.all(
- subscriptions.map(subscription =>
- limit(() => syncSubscription(subscription))
- )
- )
- }
- const loopForSubscriptions = async skipInitial => {
- let skip = skipInitial
- // iterate while there are more subscriptions to fetch
- while (true) {
- const subscriptions = await Subscription.find({
- recurlySubscription_id: { $exists: true, $ne: '' },
- })
- .sort('_id')
- .skip(skip)
- .limit(FETCH_LIMIT)
- .exec()
- if (subscriptions.length === 0) {
- console.warn('DONE')
- return
- }
- await syncSubscriptions(subscriptions)
- ScriptLogger.checkedSubscriptionsCount += subscriptions.length
- retryCounter = 0
- ScriptLogger.printProgress()
- ScriptLogger.printSummary()
- skip += FETCH_LIMIT
- }
- }
- let retryCounter = 0
- const run = async () => {
- await waitForDb()
- while (true) {
- try {
- await loopForSubscriptions(
- MONGO_SKIP + ScriptLogger.checkedSubscriptionsCount
- )
- break
- } catch (error) {
- if (retryCounter < 3) {
- console.error(error)
- retryCounter += 1
- console.warn(`RETRYING IN 60 SECONDS. (${retryCounter}/3)`)
- await setTimeout(60000)
- } else {
- console.error('Failed after 3 retries')
- throw error
- }
- }
- }
- }
- 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().then(() => {
- process.exit()
- })
|