fix: skip removing already existing content in secondary to pick up where the transition left of

This commit is contained in:
Karol Sójko 2023-09-19 14:55:40 +02:00
parent de081fe786
commit 857c6af946
No known key found for this signature in database
GPG key ID: C2F813669419D05F
2 changed files with 79 additions and 41 deletions

View file

@ -31,19 +31,16 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
let newRevisionsInSecondaryCount = 0
let updatedRevisionsInSecondary: string[] = []
let alreadyIdenticalInSecondaryAndPrimary: string[] = []
if (await this.hasAlreadyDataInSecondaryDatabase(userUuid)) {
const { alreadyExistingInPrimary, newRevisionsInSecondary, updatedInSecondary } =
const { alreadyExistingInSecondaryAndPrimary, newRevisionsInSecondary, updatedInSecondary } =
await this.getNewRevisionsCreatedInSecondaryDatabase(userUuid)
this.logger.info(
`[${dto.userUuid}] Removing ${alreadyExistingInPrimary.length} already existing revisions from secondary database`,
`[${dto.userUuid}] ${alreadyExistingInSecondaryAndPrimary.length} already existing identical revisions in primary and secondary.`,
)
for (const existingRevisionUuid of alreadyExistingInPrimary) {
await (this.secondRevisionsRepository as RevisionRepositoryInterface).removeOneByUuid(
Uuid.create(existingRevisionUuid).getValue(),
userUuid,
)
}
alreadyIdenticalInSecondaryAndPrimary = alreadyExistingInSecondaryAndPrimary
if (newRevisionsInSecondary.length > 0) {
this.logger.info(
@ -68,7 +65,11 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
this.logger.info(`[${dto.userUuid}] Migrating revisions`)
const migrationResult = await this.migrateRevisionsForUser(userUuid, updatedRevisionsInSecondary)
const migrationResult = await this.migrateRevisionsForUser(
userUuid,
updatedRevisionsInSecondary,
alreadyIdenticalInSecondaryAndPrimary,
)
if (migrationResult.isFailed()) {
if (newRevisionsInSecondaryCount === 0 && updatedRevisionsInSecondaryCount === 0) {
const cleanupResult = await this.deleteRevisionsForUser(userUuid, this.secondRevisionsRepository)
@ -88,6 +89,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
userUuid,
newRevisionsInSecondaryCount,
updatedRevisionsInSecondary,
alreadyIdenticalInSecondaryAndPrimary,
)
if (integrityCheckResult.isFailed()) {
if (newRevisionsInSecondaryCount === 0 && updatedRevisionsInSecondaryCount === 0) {
@ -119,7 +121,11 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
return Result.ok()
}
private async migrateRevisionsForUser(userUuid: Uuid, updatedRevisionsInSecondary: string[]): Promise<Result<void>> {
private async migrateRevisionsForUser(
userUuid: Uuid,
updatedRevisionsInSecondary: string[],
alreadyExistingInSecondaryAndPrimary: string[],
): Promise<Result<void>> {
try {
const totalRevisionsCountForUser = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
const totalPages = Math.ceil(totalRevisionsCountForUser / this.pageSize)
@ -146,6 +152,14 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
continue
}
if (
alreadyExistingInSecondaryAndPrimary.find(
(alreadyExistingRevisionUuid) => alreadyExistingRevisionUuid === revision.id.toString(),
)
) {
continue
}
const didSave = await (this.secondRevisionsRepository as RevisionRepositoryInterface).insert(revision)
if (!didSave) {
return Result.fail(`Failed to save revision ${revision.id.toString()} to secondary database`)
@ -200,7 +214,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
}
private async getNewRevisionsCreatedInSecondaryDatabase(userUuid: Uuid): Promise<{
alreadyExistingInPrimary: string[]
alreadyExistingInSecondaryAndPrimary: string[]
newRevisionsInSecondary: string[]
updatedInSecondary: string[]
}> {
@ -211,7 +225,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
).countByUserUuid(userUuid)
const totalPages = Math.ceil(totalRevisionsCountForUser / this.pageSize)
const alreadyExistingInPrimary: string[] = []
const alreadyExistingInSecondaryAndPrimary: string[] = []
const newRevisionsInSecondary: string[] = []
const updatedInSecondary: string[] = []
@ -224,17 +238,17 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
const revisions = await (this.secondRevisionsRepository as RevisionRepositoryInterface).findByUserUuid(query)
for (const revision of revisions) {
const { revisionInPrimary, newerRevisionInSecondary } =
const { identicalRevisionInPrimary, newerRevisionInSecondary } =
await this.checkIfRevisionExistsInPrimaryDatabase(revision)
if (revisionInPrimary !== null) {
alreadyExistingInPrimary.push(revision.id.toString())
if (identicalRevisionInPrimary !== null) {
alreadyExistingInSecondaryAndPrimary.push(revision.id.toString())
continue
}
if (newerRevisionInSecondary !== null) {
updatedInSecondary.push(newerRevisionInSecondary.id.toString())
continue
}
if (revisionInPrimary === null && newerRevisionInSecondary === null) {
if (identicalRevisionInPrimary === null && newerRevisionInSecondary === null) {
newRevisionsInSecondary.push(revision.id.toString())
continue
}
@ -242,7 +256,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
}
return {
alreadyExistingInPrimary,
alreadyExistingInSecondaryAndPrimary,
newRevisionsInSecondary,
updatedInSecondary,
}
@ -250,7 +264,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
private async checkIfRevisionExistsInPrimaryDatabase(
revision: Revision,
): Promise<{ revisionInPrimary: Revision | null; newerRevisionInSecondary: Revision | null }> {
): Promise<{ identicalRevisionInPrimary: Revision | null; newerRevisionInSecondary: Revision | null }> {
const revisionInPrimary = await this.primaryRevisionsRepository.findOneByUuid(
Uuid.create(revision.id.toString()).getValue(),
revision.props.userUuid as Uuid,
@ -259,7 +273,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
if (revisionInPrimary === null) {
return {
revisionInPrimary: null,
identicalRevisionInPrimary: null,
newerRevisionInSecondary: null,
}
}
@ -273,14 +287,14 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
)
return {
revisionInPrimary: null,
identicalRevisionInPrimary: null,
newerRevisionInSecondary:
revision.props.dates.updatedAt > revisionInPrimary.props.dates.updatedAt ? revision : null,
}
}
return {
revisionInPrimary: revisionInPrimary,
identicalRevisionInPrimary: revisionInPrimary,
newerRevisionInSecondary: null,
}
}
@ -289,6 +303,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
userUuid: Uuid,
newRevisionsInSecondaryCount: number,
updatedRevisionsInSecondary: string[],
alreadyExistingInSecondaryAndPrimary: string[],
): Promise<Result<boolean>> {
try {
const totalRevisionsCountForUserInPrimary = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
@ -329,6 +344,14 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
continue
}
if (
alreadyExistingInSecondaryAndPrimary.find(
(alreadyExistingRevisionUuid) => alreadyExistingRevisionUuid === revision.id.toString(),
)
) {
continue
}
if (!revision.isIdenticalTo(revisionInSecondary)) {
return Result.fail(
`Revision ${revision.id.toString()} is not identical in primary and secondary database. Revision in primary database: ${JSON.stringify(

View file

@ -32,19 +32,16 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
let newItemsInSecondaryCount = 0
let updatedItemsInSecondary: string[] = []
let alreadyIdenticalInSecondaryAndPrimary: string[] = []
if (await this.hasAlreadyDataInSecondaryDatabase(userUuid)) {
const { alreadyExistingInPrimary, newItemsInSecondary, updatedInSecondary } =
const { alreadyExistingInSecondaryAndPrimary, newItemsInSecondary, updatedInSecondary } =
await this.getNewItemsCreatedInSecondaryDatabase(userUuid)
this.logger.info(
`[${dto.userUuid}] Removing ${alreadyExistingInPrimary.length} already existing items from secondary database.`,
`[${dto.userUuid}] ${alreadyExistingInSecondaryAndPrimary.length} already existing identical items in primary and secondary.`,
)
for (const existingItemUuid of alreadyExistingInPrimary) {
await (this.secondaryItemRepository as ItemRepositoryInterface).removeByUuid(
Uuid.create(existingItemUuid).getValue(),
)
}
alreadyIdenticalInSecondaryAndPrimary = alreadyExistingInSecondaryAndPrimary
if (newItemsInSecondary.length > 0) {
this.logger.info(`[${dto.userUuid}] Found ${newItemsInSecondary.length} new items in secondary database.`)
@ -66,7 +63,11 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
this.logger.info(`[${dto.userUuid}] Migrating items`)
const migrationResult = await this.migrateItemsForUser(userUuid, updatedItemsInSecondary)
const migrationResult = await this.migrateItemsForUser(
userUuid,
updatedItemsInSecondary,
alreadyIdenticalInSecondaryAndPrimary,
)
if (migrationResult.isFailed()) {
if (newItemsInSecondaryCount === 0 && updatedItemsInSecondaryCount === 0) {
const cleanupResult = await this.deleteItemsForUser(userUuid, this.secondaryItemRepository)
@ -86,6 +87,7 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
userUuid,
newItemsInSecondaryCount,
updatedItemsInSecondary,
alreadyIdenticalInSecondaryAndPrimary,
)
if (integrityCheckResult.isFailed()) {
if (newItemsInSecondaryCount === 0 && updatedItemsInSecondaryCount === 0) {
@ -136,13 +138,13 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
}
private async getNewItemsCreatedInSecondaryDatabase(userUuid: Uuid): Promise<{
alreadyExistingInPrimary: string[]
alreadyExistingInSecondaryAndPrimary: string[]
newItemsInSecondary: string[]
updatedInSecondary: string[]
}> {
this.logger.info(`[${userUuid.value}] Checking for new items in secondary database`)
const alreadyExistingInPrimary: string[] = []
const alreadyExistingInSecondaryAndPrimary: string[] = []
const updatedInSecondary: string[] = []
const newItemsInSecondary: string[] = []
@ -161,16 +163,16 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
const items = await (this.secondaryItemRepository as ItemRepositoryInterface).findAll(query)
for (const item of items) {
const { itemInPrimary, newerItemInSecondary } = await this.checkIfItemExistsInPrimaryDatabase(item)
if (itemInPrimary !== null) {
alreadyExistingInPrimary.push(item.id.toString())
const { identicalItemInPrimary, newerItemInSecondary } = await this.checkIfItemExistsInPrimaryDatabase(item)
if (identicalItemInPrimary !== null) {
alreadyExistingInSecondaryAndPrimary.push(item.id.toString())
continue
}
if (newerItemInSecondary !== null) {
updatedInSecondary.push(newerItemInSecondary.id.toString())
continue
}
if (itemInPrimary === null && newerItemInSecondary === null) {
if (identicalItemInPrimary === null && newerItemInSecondary === null) {
newItemsInSecondary.push(item.id.toString())
continue
}
@ -178,7 +180,7 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
}
return {
alreadyExistingInPrimary,
alreadyExistingInSecondaryAndPrimary,
newItemsInSecondary,
updatedInSecondary,
}
@ -186,11 +188,11 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
private async checkIfItemExistsInPrimaryDatabase(
item: Item,
): Promise<{ itemInPrimary: Item | null; newerItemInSecondary: Item | null }> {
): Promise<{ identicalItemInPrimary: Item | null; newerItemInSecondary: Item | null }> {
const itemInPrimary = await this.primaryItemRepository.findByUuid(item.uuid)
if (itemInPrimary === null) {
return { itemInPrimary: null, newerItemInSecondary: null }
return { identicalItemInPrimary: null, newerItemInSecondary: null }
}
if (!item.isIdenticalTo(itemInPrimary)) {
@ -203,15 +205,19 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
)
return {
itemInPrimary: null,
identicalItemInPrimary: null,
newerItemInSecondary: item.props.timestamps.updatedAt > itemInPrimary.props.timestamps.updatedAt ? item : null,
}
}
return { itemInPrimary: itemInPrimary, newerItemInSecondary: null }
return { identicalItemInPrimary: itemInPrimary, newerItemInSecondary: null }
}
private async migrateItemsForUser(userUuid: Uuid, updatedItemsInSecondary: string[]): Promise<Result<void>> {
private async migrateItemsForUser(
userUuid: Uuid,
updatedItemsInSecondary: string[],
alreadyExistingInSecondaryAndPrimary: string[],
): Promise<Result<void>> {
try {
const totalItemsCountForUser = await this.primaryItemRepository.countAll({ userUuid: userUuid.value })
const totalPages = Math.ceil(totalItemsCountForUser / this.pageSize)
@ -234,6 +240,10 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
continue
}
if (alreadyExistingInSecondaryAndPrimary.find((itemUuid) => item.uuid.value === itemUuid)) {
continue
}
await (this.secondaryItemRepository as ItemRepositoryInterface).save(item)
}
}
@ -258,6 +268,7 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
userUuid: Uuid,
newItemsInSecondaryCount: number,
updatedItemsInSecondary: string[],
alreadyExistingInSecondaryAndPrimary: string[],
): Promise<Result<boolean>> {
try {
const totalItemsCountForUserInPrimary = await this.primaryItemRepository.countAll({ userUuid: userUuid.value })
@ -298,6 +309,10 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
continue
}
if (alreadyExistingInSecondaryAndPrimary.find((itemUuid) => item.uuid.value === itemUuid)) {
continue
}
if (!item.isIdenticalTo(itemInSecondary)) {
return Result.fail(
`Item ${