diff --git a/packages/syncing-server/bin/revisions.ts b/packages/syncing-server/bin/revisions.ts index 225385f00..069677989 100644 --- a/packages/syncing-server/bin/revisions.ts +++ b/packages/syncing-server/bin/revisions.ts @@ -14,15 +14,22 @@ import { Stream } from 'stream' import { ContentType } from '@standardnotes/common' const fixRevisionsOwnership = async ( + year: number, + month: number, itemRepository: ItemRepositoryInterface, domainEventFactory: DomainEventFactoryInterface, domainEventPublisher: DomainEventPublisherInterface, logger: Logger, ): Promise => { + const createdAfter = new Date(`${year}-${month}-1`) + const createdBefore = new Date(`${month !== 12 ? year : year + 1}-${month !== 12 ? month + 1 : 1}-1`) + + logger.info(`Processing items between ${createdAfter.toISOString} and ${createdBefore.toISOString}`) + const stream = await itemRepository.streamAll({ - createdBefore: new Date('2022-11-23'), + createdBetween: [createdAfter, createdBefore], selectFields: ['user_uuid', 'uuid'], - contentType: ContentType.Note, + contentType: [ContentType.Note, ContentType.File], }) return new Promise((resolve, reject) => { @@ -48,11 +55,15 @@ const fixRevisionsOwnership = async ( logger.error(`Could not process item ${rawItemData.item_uuid}: ${(error as Error).message}`) } - callback() + return callback() }, }), ) - .on('finish', resolve) + .on('finish', () => { + logger.info(`Finished processing items between ${createdAfter.toISOString} and ${createdBefore.toISOString}`) + + resolve() + }) .on('error', reject) }) } @@ -70,7 +81,16 @@ void container.load().then((container) => { const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory) const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher) - Promise.resolve(fixRevisionsOwnership(itemRepository, domainEventFactory, domainEventPublisher, logger)) + const years = [2016, 2017, 2018, 2019, 2020, 2021, 2022] + + const promises = [] + for (const year of years) { + for (let i = 1; i <= 12; i++) { + promises.push(fixRevisionsOwnership(year, i, itemRepository, domainEventFactory, domainEventPublisher, logger)) + } + } + + Promise.all(promises) .then(() => { logger.info('revisions ownership fix complete.') diff --git a/packages/syncing-server/src/Domain/Item/ItemQuery.ts b/packages/syncing-server/src/Domain/Item/ItemQuery.ts index c97d1f9ee..7ccfcf0f4 100644 --- a/packages/syncing-server/src/Domain/Item/ItemQuery.ts +++ b/packages/syncing-server/src/Domain/Item/ItemQuery.ts @@ -5,10 +5,10 @@ export type ItemQuery = { uuids?: Array lastSyncTime?: number syncTimeComparison?: '>' | '>=' - contentType?: string + contentType?: string | string[] deleted?: boolean offset?: number limit?: number - createdBefore?: Date + createdBetween?: Date[] selectFields?: string[] } diff --git a/packages/syncing-server/src/Infra/MySQL/MySQLItemRepository.ts b/packages/syncing-server/src/Infra/MySQL/MySQLItemRepository.ts index d5749c8ff..155a145a6 100644 --- a/packages/syncing-server/src/Infra/MySQL/MySQLItemRepository.ts +++ b/packages/syncing-server/src/Infra/MySQL/MySQLItemRepository.ts @@ -148,15 +148,22 @@ export class MySQLItemRepository implements ItemRepositoryInterface { queryBuilder.andWhere('item.deleted = :deleted', { deleted: query.deleted }) } if (query.contentType) { - queryBuilder.andWhere('item.content_type = :contentType', { contentType: query.contentType }) + if (Array.isArray(query.contentType)) { + queryBuilder.andWhere('item.content_type IN (:...contentTypes)', { contentTypes: query.contentType }) + } else { + queryBuilder.andWhere('item.content_type = :contentType', { contentType: query.contentType }) + } } if (query.lastSyncTime && query.syncTimeComparison) { queryBuilder.andWhere(`item.updated_at_timestamp ${query.syncTimeComparison} :lastSyncTime`, { lastSyncTime: query.lastSyncTime, }) } - if (query.createdBefore !== undefined) { - queryBuilder.andWhere('item.created_at < :createdAt', { createdAt: query.createdBefore.toISOString() }) + if (query.createdBetween !== undefined) { + queryBuilder.andWhere('item.created_at BETWEEN :createdAfter AND :createdBefore', { + createdAfter: query.createdBetween[0].toISOString(), + createdBefore: query.createdBetween[1].toISOString(), + }) } if (query.offset !== undefined) { queryBuilder.skip(query.offset)