ソースを参照

fix: transitionining revisions (#801)

Karol Sójko 1 年間 前
コミット
596a0f1a02

+ 1 - 0
packages/revisions/src/Domain/UseCase/Transition/TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser/TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser.spec.ts

@@ -109,6 +109,7 @@ describe('TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser', () => {
     logger.info = jest.fn()
 
     timer = {} as jest.Mocked<TimerInterface>
+    timer.sleep = jest.fn()
     timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(123)
     timer.convertMicrosecondsToTimeStructure = jest.fn().mockReturnValue({
       days: 0,

+ 15 - 0
packages/revisions/src/Domain/UseCase/Transition/TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser/TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser.ts

@@ -38,6 +38,8 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
       return Result.fail(migrationResult.getError())
     }
 
+    await this.allowForSecondaryDatabaseToCatchUp()
+
     const integrityCheckResult = await this.checkIntegrityBetweenPrimaryAndSecondaryDatabase(userUuid)
     if (integrityCheckResult.isFailed()) {
       const cleanupResult = await this.deleteRevisionsForUser(userUuid, this.secondRevisionsRepository)
@@ -72,9 +74,15 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
   private async migrateRevisionsForUser(userUuid: Uuid): Promise<Result<void>> {
     try {
       const totalRevisionsCountForUser = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
+      this.logger.info(`Total revisions count for user ${userUuid.value} is ${totalRevisionsCountForUser}`)
+
       const pageSize = 1
       const totalPages = Math.ceil(totalRevisionsCountForUser / pageSize)
+      this.logger.info(`Total pages to migrate for user ${userUuid.value} is ${totalPages}`)
+
       for (let currentPage = 1; currentPage <= totalPages; currentPage++) {
+        this.logger.info(`Migrating page ${currentPage} of ${totalPages} for user ${userUuid.value}`)
+
         const query = {
           userUuid: userUuid,
           offset: (currentPage - 1) * pageSize,
@@ -83,6 +91,8 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
 
         const revisions = await this.primaryRevisionsRepository.findByUserUuid(query)
 
+        this.logger.info(`Migrating ${revisions.length} revisions for user ${userUuid.value}`)
+
         for (const revision of revisions) {
           await (this.secondRevisionsRepository as RevisionRepositoryInterface).save(revision)
         }
@@ -107,6 +117,11 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
     }
   }
 
+  private async allowForSecondaryDatabaseToCatchUp(): Promise<void> {
+    const twoSecondsInMilliseconds = 2_000
+    await this.timer.sleep(twoSecondsInMilliseconds)
+  }
+
   private async checkIntegrityBetweenPrimaryAndSecondaryDatabase(userUuid: Uuid): Promise<Result<boolean>> {
     try {
       const totalRevisionsCountForUserInPrimary = await this.primaryRevisionsRepository.countByUserUuid(userUuid)

+ 2 - 6
packages/revisions/src/Infra/TypeORM/MongoDB/MongoDBRevisionRepository.ts

@@ -44,12 +44,8 @@ export class MongoDBRevisionRepository implements RevisionRepositoryInterface {
 
   async removeOneByUuid(revisionUuid: Uuid, userUuid: Uuid): Promise<void> {
     await this.mongoRepository.deleteOne({
-      where: {
-        $and: [
-          { _id: { $eq: BSON.UUID.createFromHexString(revisionUuid.value) } },
-          { userUuid: { $eq: userUuid.value } },
-        ],
-      },
+      _id: { $eq: BSON.UUID.createFromHexString(revisionUuid.value) },
+      userUuid: { $eq: userUuid.value },
     })
   }
 

+ 1 - 0
packages/syncing-server/src/Domain/UseCase/Transition/TransitionItemsFromPrimaryToSecondaryDatabaseForUser/TransitionItemsFromPrimaryToSecondaryDatabaseForUser.spec.ts

@@ -117,6 +117,7 @@ describe('TransitionItemsFromPrimaryToSecondaryDatabaseForUser', () => {
     logger.info = jest.fn()
 
     timer = {} as jest.Mocked<TimerInterface>
+    timer.sleep = jest.fn()
     timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(123)
     timer.convertMicrosecondsToTimeStructure = jest.fn().mockReturnValue({
       days: 0,

+ 7 - 0
packages/syncing-server/src/Domain/UseCase/Transition/TransitionItemsFromPrimaryToSecondaryDatabaseForUser/TransitionItemsFromPrimaryToSecondaryDatabaseForUser.ts

@@ -39,6 +39,8 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
       return Result.fail(migrationResult.getError())
     }
 
+    await this.allowForSecondaryDatabaseToCatchUp()
+
     const integrityCheckResult = await this.checkIntegrityBetweenPrimaryAndSecondaryDatabase(userUuid)
     if (integrityCheckResult.isFailed()) {
       const cleanupResult = await this.deleteItemsForUser(userUuid, this.secondaryItemRepository)
@@ -70,6 +72,11 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
     return Result.ok()
   }
 
+  private async allowForSecondaryDatabaseToCatchUp(): Promise<void> {
+    const twoSecondsInMilliseconds = 2_000
+    await this.timer.sleep(twoSecondsInMilliseconds)
+  }
+
   private async migrateItemsForUser(userUuid: Uuid): Promise<Result<void>> {
     try {
       const totalItemsCountForUser = await this.primaryItemRepository.countAll({ userUuid: userUuid.value })

+ 1 - 1
packages/syncing-server/src/Infra/TypeORM/MongoDBItemRepository.ts

@@ -136,7 +136,7 @@ export class MongoDBItemRepository implements ItemRepositoryInterface {
   }
 
   async remove(item: Item): Promise<void> {
-    await this.mongoRepository.deleteOne({ where: { _id: { $eq: BSON.UUID.createFromHexString(item.uuid.value) } } })
+    await this.mongoRepository.deleteOne({ _id: { $eq: BSON.UUID.createFromHexString(item.uuid.value) } })
   }
 
   async save(item: Item): Promise<void> {

+ 5 - 0
packages/time/src/Domain/Time/Timer.ts

@@ -10,6 +10,11 @@ export class Timer implements TimerInterface {
     dayjs.extend(utc)
   }
 
+  /* istanbul ignore next */
+  async sleep(milliseconds: number): Promise<void> {
+    return new Promise((resolve) => setTimeout(resolve, milliseconds))
+  }
+
   getUTCDateNSecondsAhead(n: number): Date {
     return dayjs.utc().add(n, 'second').toDate()
   }

+ 1 - 0
packages/time/src/Domain/Time/TimerInterface.ts

@@ -23,4 +23,5 @@ export interface TimerInterface {
   convertMicrosecondsToTimeStructure(microseconds: number): TimeStructure
   formatDate(date: Date, format: string): string
   dateWasNDaysAgo(date: Date): number
+  sleep(milliseconds: number): Promise<void>
 }