forked from TryGhost/Ghost
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Removed duplicate stripe customers&subscriptions
refs TryGhost#12100 We want to add unique constraints to the subscription_id and customer_id fields in the members_stripe_customers_subscriptions and members_stripe_customers tables respectively. In order to do this safely we must first ensure that no duplicate entries exist.
- Loading branch information
Showing
2 changed files
with
90 additions
and
0 deletions.
There are no files selected for viewing
45 changes: 45 additions & 0 deletions
45
core/server/data/migrations/versions/3.28/01-remove-duplicate-subscriptions.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const logging = require('../../../../../shared/logging'); | ||
|
||
module.exports = { | ||
config: { | ||
transaction: true | ||
}, | ||
|
||
async up({transacting: knex}) { | ||
const duplicates = await knex('members_stripe_customers_subscriptions') | ||
.select('subscription_id') | ||
.count('subscription_id as count') | ||
.groupBy('subscription_id') | ||
.having('count', '>', 1); | ||
|
||
if (!duplicates.length) { | ||
logging.info('No duplicate subscriptions found'); | ||
return; | ||
} | ||
|
||
logging.info(`Found ${duplicates.length} duplicate stripe subscriptions`); | ||
for (const duplicate of duplicates) { | ||
const subscriptions = await knex('members_stripe_customers_subscriptions') | ||
.select() | ||
.where('subscription_id', duplicate.subscription_id); | ||
|
||
const orderedSubscriptions = subscriptions.sort((subA, subB) => { | ||
return subB.updated_at - subA.updated_at; | ||
}); | ||
|
||
const [newestSubscription, ...olderSubscriptions] = orderedSubscriptions; | ||
|
||
logging.info(`Keeping newest subscription ${newestSubscription.id} - ${newestSubscription.subscription_id}, last updated at ${newestSubscription.updated_at}`); | ||
|
||
for (const subscriptionToDelete of olderSubscriptions) { | ||
logging.info(`Deleting duplicate subscription ${subscriptionToDelete.id} - ${subscriptionToDelete.subscription_id}, last updated at ${subscriptionToDelete.updated_at}`); | ||
await knex('members_stripe_customers_subscriptions') | ||
.where({id: subscriptionToDelete.id}) | ||
.del(); | ||
} | ||
} | ||
}, | ||
|
||
// noop for down | ||
async down() {} | ||
}; |
45 changes: 45 additions & 0 deletions
45
core/server/data/migrations/versions/3.28/02-remove-duplicate-customers.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const logging = require('../../../../../shared/logging'); | ||
|
||
module.exports = { | ||
config: { | ||
transaction: true | ||
}, | ||
|
||
async up({transacting: knex}) { | ||
const duplicates = await knex('members_stripe_customers') | ||
.select('customer_id') | ||
.count('customer_id as count') | ||
.groupBy('customer_id') | ||
.having('count', '>', 1); | ||
|
||
if (!duplicates.length) { | ||
logging.info('No duplicate customers found'); | ||
return; | ||
} | ||
|
||
logging.info(`Found ${duplicates.length} duplicate stripe customers`); | ||
for (const duplicate of duplicates) { | ||
const customers = await knex('members_stripe_customers') | ||
.select() | ||
.where('customer_id', duplicate.customer_id); | ||
|
||
const orderedCustomers = customers.sort((subA, subB) => { | ||
return subB.updated_at - subA.updated_at; | ||
}); | ||
|
||
const [newestCustomer, ...olderCustomers] = orderedCustomers; | ||
|
||
logging.info(`Keeping newest customer ${newestCustomer.id} - ${newestCustomer.customer_id}, last updated at ${newestCustomer.updated_at}`); | ||
|
||
for (const customerToDelete of olderCustomers) { | ||
logging.info(`Deleting duplicate customer ${customerToDelete.id} - ${customerToDelete.customer_id}, last updated at ${customerToDelete.updated_at}`); | ||
await knex('members_stripe_customers') | ||
.where({id: customerToDelete.id}) | ||
.del(); | ||
} | ||
} | ||
}, | ||
|
||
// noop for down | ||
async down() {} | ||
}; |