mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-26 18:51:50 +02:00
[web] switch migrations for fixing dates to batchedUpdate (#26582)
* [web] switch migration for fixing confirmedAt dates to batchedUpdate * [web] switch migration for fixing assignedAt dates to batchedUpdate * [web] make eslint happy GitOrigin-RevId: d898d28dc2aa1084e8d3af20b98f49e3fda8a1c6
This commit is contained in:
@@ -1,12 +1,35 @@
|
||||
import updateStringDates from '../scripts/confirmed_at_to_dates.mjs'
|
||||
import { db } from '../app/src/infrastructure/mongodb.js'
|
||||
import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
|
||||
|
||||
const tags = ['saas']
|
||||
|
||||
const migrate = async client => {
|
||||
await updateStringDates()
|
||||
const migrate = async () => {
|
||||
await batchedUpdate(
|
||||
db.users,
|
||||
{ 'emails.confirmedAt': { $type: 'string' } },
|
||||
async function (batch) {
|
||||
for (const user of batch) {
|
||||
for (const email of user.emails) {
|
||||
if (typeof email.confirmedAt === 'string') {
|
||||
await db.users.updateOne(
|
||||
{ _id: user._id, 'emails.email': email.email },
|
||||
{
|
||||
$set: {
|
||||
'emails.$.confirmedAt': new Date(
|
||||
email.confirmedAt.replace(/ UTC$/, '')
|
||||
),
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{ emails: 1 }
|
||||
)
|
||||
}
|
||||
|
||||
const rollback = async client => {
|
||||
const rollback = async () => {
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
import updateStringDates from '../scripts/split_tests_assigned_at_to_dates.mjs'
|
||||
import { db } from '../app/src/infrastructure/mongodb.js'
|
||||
import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
|
||||
|
||||
const tags = ['saas']
|
||||
|
||||
const migrate = async client => {
|
||||
await updateStringDates()
|
||||
const migrate = async () => {
|
||||
await batchedUpdate(
|
||||
db.users,
|
||||
{ splitTests: { $exists: true } },
|
||||
async function (batch) {
|
||||
for (const user of batch) {
|
||||
const splitTests = user.splitTests
|
||||
for (const splitTest of Object.values(user.splitTests)) {
|
||||
for (const variant of splitTest) {
|
||||
variant.assignedAt = new Date(variant.assignedAt)
|
||||
}
|
||||
}
|
||||
|
||||
await db.users.updateOne({ _id: user._id }, { $set: { splitTests } })
|
||||
}
|
||||
},
|
||||
{ splitTests: 1 }
|
||||
)
|
||||
}
|
||||
|
||||
const rollback = async client => {
|
||||
const rollback = async () => {
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import { db } from '../app/src/infrastructure/mongodb.js'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
async function updateStringDates() {
|
||||
const users = await db.users.aggregate([
|
||||
{ $unwind: { path: '$emails' } },
|
||||
{
|
||||
$match: { 'emails.confirmedAt': { $exists: true, $type: 'string' } },
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: 1,
|
||||
'emails.email': 1,
|
||||
'emails.confirmedAt': 1,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
let user
|
||||
let count = 0
|
||||
while ((user = await users.next())) {
|
||||
count += 1
|
||||
if (count % 10000 === 0) {
|
||||
console.log(`processed ${count} users`)
|
||||
}
|
||||
const confirmedAt = user.emails.confirmedAt
|
||||
const dateConfirmedAt = new Date(confirmedAt.replace(/ UTC$/, ''))
|
||||
await db.users.updateOne(
|
||||
{
|
||||
_id: user._id,
|
||||
'emails.email': user.emails.email,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
'emails.$.confirmedAt': dateConfirmedAt,
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
console.log(`Updated ${count} confirmedAt strings to dates!`)
|
||||
}
|
||||
|
||||
if (fileURLToPath(import.meta.url) === process.argv[1]) {
|
||||
try {
|
||||
await updateStringDates()
|
||||
process.exit(0)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
export default updateStringDates
|
||||
@@ -1,46 +0,0 @@
|
||||
import { db } from '../app/src/infrastructure/mongodb.js'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
async function updateStringDates() {
|
||||
const users = db.users.find({
|
||||
splitTests: { $exists: true },
|
||||
})
|
||||
|
||||
let user
|
||||
let count = 0
|
||||
while ((user = await users.next())) {
|
||||
count += 1
|
||||
if (count % 10000 === 0) {
|
||||
console.log(`processed ${count} users...`)
|
||||
}
|
||||
|
||||
const splitTests = user.splitTests
|
||||
for (const splitTestKey of Object.keys(splitTests)) {
|
||||
for (const variantIndex in splitTests[splitTestKey]) {
|
||||
splitTests[splitTestKey][variantIndex].assignedAt = new Date(
|
||||
splitTests[splitTestKey][variantIndex].assignedAt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
await db.users.updateOne(
|
||||
{
|
||||
_id: user._id,
|
||||
},
|
||||
{ $set: { splitTests } }
|
||||
)
|
||||
}
|
||||
console.log(`Updated ${count} assignedAt strings to dates!`)
|
||||
}
|
||||
|
||||
if (fileURLToPath(import.meta.url) === process.argv[1]) {
|
||||
try {
|
||||
await updateStringDates()
|
||||
process.exit(0)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
export default updateStringDates
|
||||
@@ -0,0 +1,69 @@
|
||||
import { expect } from 'chai'
|
||||
import { db } from '../../../app/src/infrastructure/mongodb.js'
|
||||
import { exec } from 'node:child_process'
|
||||
|
||||
describe('ConvertEmailConfirmedAtToDates', function () {
|
||||
beforeEach('insert data', async function () {
|
||||
await db.users.insertMany([
|
||||
{ email: 'foo0@bar.com', emails: [{ email: 'foo0@bar.com' }] },
|
||||
{
|
||||
email: 'foo1@bar.com',
|
||||
emails: [
|
||||
{ email: 'foo1@bar.com', confirmedAt: '2025-06-20 15:53:31 UTC' },
|
||||
],
|
||||
},
|
||||
{
|
||||
email: 'foo2@bar.com',
|
||||
emails: [
|
||||
{ email: 'foo2@bar.com', confirmedAt: '2025-06-20 15:53:32 UTC' },
|
||||
{ email: 'foo3@bar.com', confirmedAt: '2025-06-20 15:53:33 UTC' },
|
||||
{
|
||||
email: 'foo4@bar.com',
|
||||
confirmedAt: new Date('2025-06-20T15:53:31.134Z'),
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
beforeEach('run migration', function (done) {
|
||||
exec(
|
||||
'east migrate -t saas --force 20210726083523_convert_confirmedAt_strings_to_dates',
|
||||
done
|
||||
)
|
||||
})
|
||||
|
||||
it('should update the dates', async function () {
|
||||
expect(
|
||||
await db.users.find({}, { projection: { _id: 0 } }).toArray()
|
||||
).to.deep.equal([
|
||||
{ email: 'foo0@bar.com', emails: [{ email: 'foo0@bar.com' }] },
|
||||
{
|
||||
email: 'foo1@bar.com',
|
||||
emails: [
|
||||
{
|
||||
email: 'foo1@bar.com',
|
||||
confirmedAt: new Date('2025-06-20T15:53:31.000Z'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
email: 'foo2@bar.com',
|
||||
emails: [
|
||||
{
|
||||
email: 'foo2@bar.com',
|
||||
confirmedAt: new Date('2025-06-20T15:53:32.000Z'),
|
||||
},
|
||||
{
|
||||
email: 'foo3@bar.com',
|
||||
confirmedAt: new Date('2025-06-20T15:53:33.000Z'),
|
||||
},
|
||||
{
|
||||
email: 'foo4@bar.com',
|
||||
confirmedAt: new Date('2025-06-20T15:53:31.134Z'),
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,134 @@
|
||||
import { expect } from 'chai'
|
||||
import { db } from '../../../app/src/infrastructure/mongodb.js'
|
||||
import { exec } from 'node:child_process'
|
||||
|
||||
describe('ConvertSplitTestAssignedAtToDates', function () {
|
||||
beforeEach('insert data', async function () {
|
||||
await db.users.insertMany([
|
||||
{
|
||||
email: 'foo0@bar.com',
|
||||
splitTests: {
|
||||
'split-test-1': [
|
||||
{
|
||||
variantName: 'enabled',
|
||||
versionNumber: 4,
|
||||
phase: 'release',
|
||||
assignedAt: '2025-03-18T13:19:46.627Z',
|
||||
},
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 5,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-04-30T08:52:13.783Z'),
|
||||
},
|
||||
],
|
||||
'split-test-2': [
|
||||
{
|
||||
variantName: 'active',
|
||||
versionNumber: 5,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-02-14T09:08:30.190Z'),
|
||||
},
|
||||
{
|
||||
variantName: 'active',
|
||||
versionNumber: 7,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-03-11T11:05:13.640Z'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
email: 'foo1@bar.com',
|
||||
splitTests: {
|
||||
'split-test-3': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: '2025-02-11T14:55:38.470Z',
|
||||
},
|
||||
{
|
||||
variantName: 'enabled',
|
||||
versionNumber: 21,
|
||||
phase: 'release',
|
||||
assignedAt: '2025-03-18T13:19:46.826Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
email: 'foo2@bar.com',
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
beforeEach('run migration', function (done) {
|
||||
exec(
|
||||
'east migrate -t saas --force 20210726083523_convert_split_tests_assigned_at_strings_to_dates',
|
||||
done
|
||||
)
|
||||
})
|
||||
|
||||
it('should update the dates', async function () {
|
||||
expect(
|
||||
await db.users.find({}, { projection: { _id: 0 } }).toArray()
|
||||
).to.deep.equal([
|
||||
{
|
||||
email: 'foo0@bar.com',
|
||||
splitTests: {
|
||||
'split-test-1': [
|
||||
{
|
||||
variantName: 'enabled',
|
||||
versionNumber: 4,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-03-18T13:19:46.627Z'),
|
||||
},
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 5,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-04-30T08:52:13.783Z'),
|
||||
},
|
||||
],
|
||||
'split-test-2': [
|
||||
{
|
||||
variantName: 'active',
|
||||
versionNumber: 5,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-02-14T09:08:30.190Z'),
|
||||
},
|
||||
{
|
||||
variantName: 'active',
|
||||
versionNumber: 7,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-03-11T11:05:13.640Z'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
email: 'foo1@bar.com',
|
||||
splitTests: {
|
||||
'split-test-3': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-02-11T14:55:38.470Z'),
|
||||
},
|
||||
{
|
||||
variantName: 'enabled',
|
||||
versionNumber: 21,
|
||||
phase: 'release',
|
||||
assignedAt: new Date('2025-03-18T13:19:46.826Z'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
email: 'foo2@bar.com',
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user