From 822ee890aff80cd099fc67b778ee02b8e9ef40eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Mon, 21 Nov 2022 12:56:11 +0100 Subject: [PATCH] feat(revisions): add persisting revisions from s3 dump --- packages/revisions/src/Bootstrap/Container.ts | 51 +++++++++++---- packages/revisions/src/Bootstrap/Types.ts | 4 ++ .../Domain/Dump/DumpRepositoryInterface.ts | 6 ++ .../Handler/ItemDumpedEventHandler.spec.ts | 46 ++++++++++++++ .../Domain/Handler/ItemDumpedEventHandler.ts | 24 +++++++ .../src/Domain/Revision/RevisionProps.ts | 5 +- .../Revision/RevisionRepositoryInterface.ts | 2 + .../Infra/MySQL/MySQLRevisionRepository.ts | 14 ++++- .../src/Infra/S3/S3ItemDumpRepository.ts | 39 ++++++++++++ .../src/Infra/TypeORM/TypeORMRevision.ts | 4 +- .../src/Mapping/RevisionItemStringMapper.ts | 43 +++++++++++++ .../src/Mapping/RevisionPersistenceMapper.ts | 62 +++++++++++++++++++ ...isionCreationRequestedEventHandler.spec.ts | 10 +-- ...emRevisionCreationRequestedEventHandler.ts | 4 -- 14 files changed, 283 insertions(+), 31 deletions(-) create mode 100644 packages/revisions/src/Domain/Dump/DumpRepositoryInterface.ts create mode 100644 packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.spec.ts create mode 100644 packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.ts create mode 100644 packages/revisions/src/Infra/S3/S3ItemDumpRepository.ts create mode 100644 packages/revisions/src/Mapping/RevisionItemStringMapper.ts create mode 100644 packages/revisions/src/Mapping/RevisionPersistenceMapper.ts diff --git a/packages/revisions/src/Bootstrap/Container.ts b/packages/revisions/src/Bootstrap/Container.ts index 1ce51a789..4a818583e 100644 --- a/packages/revisions/src/Bootstrap/Container.ts +++ b/packages/revisions/src/Bootstrap/Container.ts @@ -29,6 +29,12 @@ import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository' import { RevisionMetadataPersistenceMapper } from '../Mapping/RevisionMetadataPersistenceMapper' import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision' import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata' +import { Revision } from '../Domain/Revision/Revision' +import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper' +import { RevisionPersistenceMapper } from '../Mapping/RevisionPersistenceMapper' +import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler' +import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface' +import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository' // eslint-disable-next-line @typescript-eslint/no-var-requires const newrelicFormatter = require('@newrelic/winston-enricher') @@ -88,22 +94,18 @@ export class ContainerConfigLoader { container .bind>(TYPES.RevisionMetadataPersistenceMapper) .toConstantValue(new RevisionMetadataPersistenceMapper()) + container + .bind>(TYPES.RevisionPersistenceMapper) + .toConstantValue(new RevisionPersistenceMapper()) + container + .bind>(TYPES.RevisionItemStringMapper) + .toConstantValue(new RevisionItemStringMapper()) // ORM container .bind>(TYPES.ORMRevisionRepository) .toConstantValue(AppDataSource.getRepository(TypeORMRevision)) - // Repositories - container - .bind(TYPES.RevisionRepository) - .toConstantValue( - new MySQLRevisionRepository( - container.get(TYPES.ORMRevisionRepository), - container.get(TYPES.RevisionMetadataPersistenceMapper), - ), - ) - // env vars container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL')) container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL', true)) @@ -114,6 +116,26 @@ export class ContainerConfigLoader { container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true)) container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION')) + // Repositories + container + .bind(TYPES.RevisionRepository) + .toConstantValue( + new MySQLRevisionRepository( + container.get(TYPES.ORMRevisionRepository), + container.get(TYPES.RevisionMetadataPersistenceMapper), + container.get(TYPES.RevisionPersistenceMapper), + ), + ) + container + .bind(TYPES.DumpRepository) + .toConstantValue( + new S3DumpRepository( + container.get(TYPES.S3_BACKUP_BUCKET_NAME), + container.get(TYPES.S3), + container.get(TYPES.RevisionItemStringMapper), + ), + ) + // use cases container .bind(TYPES.GetRevisionsMetada) @@ -125,6 +147,11 @@ export class ContainerConfigLoader { .toConstantValue(new RevisionsController(container.get(TYPES.GetRevisionsMetada), container.get(TYPES.Logger))) // Handlers + container + .bind(TYPES.ItemDumpedEventHandler) + .toConstantValue( + new ItemDumpedEventHandler(container.get(TYPES.DumpRepository), container.get(TYPES.RevisionRepository)), + ) // Services container @@ -136,7 +163,9 @@ export class ContainerConfigLoader { .bind(TYPES.ApiGatewayAuthMiddleware) .to(InversifyExpressApiGatewayAuthMiddleware) - const eventHandlers: Map = new Map([]) + const eventHandlers: Map = new Map([ + ['ITEM_DUMPED', container.get(TYPES.ItemDumpedEventHandler)], + ]) if (env.get('SQS_QUEUE_URL', true)) { container diff --git a/packages/revisions/src/Bootstrap/Types.ts b/packages/revisions/src/Bootstrap/Types.ts index fbcc06388..c10533835 100644 --- a/packages/revisions/src/Bootstrap/Types.ts +++ b/packages/revisions/src/Bootstrap/Types.ts @@ -6,10 +6,13 @@ const TYPES = { S3: Symbol.for('S3'), // Map RevisionMetadataPersistenceMapper: Symbol.for('RevisionMetadataPersistenceMapper'), + RevisionPersistenceMapper: Symbol.for('RevisionPersistenceMapper'), + RevisionItemStringMapper: Symbol.for('RevisionItemStringMapper'), // ORM ORMRevisionRepository: Symbol.for('ORMRevisionRepository'), // Repositories RevisionRepository: Symbol.for('RevisionRepository'), + DumpRepository: Symbol.for('DumpRepository'), // env vars REDIS_URL: Symbol.for('REDIS_URL'), SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'), @@ -25,6 +28,7 @@ const TYPES = { // Controller RevisionsController: Symbol.for('RevisionsController'), // Handlers + ItemDumpedEventHandler: Symbol.for('ItemDumpedEventHandler'), // Services CrossServiceTokenDecoder: Symbol.for('CrossServiceTokenDecoder'), DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'), diff --git a/packages/revisions/src/Domain/Dump/DumpRepositoryInterface.ts b/packages/revisions/src/Domain/Dump/DumpRepositoryInterface.ts new file mode 100644 index 000000000..c91ecda95 --- /dev/null +++ b/packages/revisions/src/Domain/Dump/DumpRepositoryInterface.ts @@ -0,0 +1,6 @@ +import { Revision } from '../Revision/Revision' + +export interface DumpRepositoryInterface { + getRevisionFromDumpPath(path: string): Promise + removeDump(path: string): Promise +} diff --git a/packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.spec.ts b/packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.spec.ts new file mode 100644 index 000000000..1e97eb1c0 --- /dev/null +++ b/packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.spec.ts @@ -0,0 +1,46 @@ +import { ItemDumpedEvent } from '@standardnotes/domain-events' +import { DumpRepositoryInterface } from '../Dump/DumpRepositoryInterface' +import { Revision } from '../Revision/Revision' +import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface' +import { ItemDumpedEventHandler } from './ItemDumpedEventHandler' + +describe('ItemDumpedEventHandler', () => { + let dumpRepository: DumpRepositoryInterface + let revisionRepository: RevisionRepositoryInterface + let revision: Revision + let event: ItemDumpedEvent + + const createHandler = () => new ItemDumpedEventHandler(dumpRepository, revisionRepository) + + beforeEach(() => { + revision = {} as jest.Mocked + + dumpRepository = {} as jest.Mocked + dumpRepository.getRevisionFromDumpPath = jest.fn().mockReturnValue(revision) + dumpRepository.removeDump = jest.fn() + + revisionRepository = {} as jest.Mocked + revisionRepository.save = jest.fn() + + event = {} as jest.Mocked + event.payload = { + fileDumpPath: 'foobar', + } + }) + + it('should save a revision from file dump', async () => { + await createHandler().handle(event) + + expect(revisionRepository.save).toHaveBeenCalled() + expect(dumpRepository.removeDump).toHaveBeenCalled() + }) + + it('should not save a revision if it could not be created from dump', async () => { + dumpRepository.getRevisionFromDumpPath = jest.fn().mockReturnValue(null) + + await createHandler().handle(event) + + expect(revisionRepository.save).not.toHaveBeenCalled() + expect(dumpRepository.removeDump).toHaveBeenCalled() + }) +}) diff --git a/packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.ts b/packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.ts new file mode 100644 index 000000000..8b4994595 --- /dev/null +++ b/packages/revisions/src/Domain/Handler/ItemDumpedEventHandler.ts @@ -0,0 +1,24 @@ +import { DomainEventHandlerInterface, ItemDumpedEvent } from '@standardnotes/domain-events' + +import { DumpRepositoryInterface } from '../Dump/DumpRepositoryInterface' +import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface' + +export class ItemDumpedEventHandler implements DomainEventHandlerInterface { + constructor( + private dumpRepository: DumpRepositoryInterface, + private revisionRepository: RevisionRepositoryInterface, + ) {} + + async handle(event: ItemDumpedEvent): Promise { + const revision = await this.dumpRepository.getRevisionFromDumpPath(event.payload.fileDumpPath) + if (revision === null) { + await this.dumpRepository.removeDump(event.payload.fileDumpPath) + + return + } + + await this.revisionRepository.save(revision) + + await this.dumpRepository.removeDump(event.payload.fileDumpPath) + } +} diff --git a/packages/revisions/src/Domain/Revision/RevisionProps.ts b/packages/revisions/src/Domain/Revision/RevisionProps.ts index e6b4c2c13..38c18302f 100644 --- a/packages/revisions/src/Domain/Revision/RevisionProps.ts +++ b/packages/revisions/src/Domain/Revision/RevisionProps.ts @@ -1,4 +1,4 @@ -import { Uuid } from '@standardnotes/domain-core' +import { Timestamps, Uuid } from '@standardnotes/domain-core' import { ContentType } from './ContentType' @@ -10,6 +10,5 @@ export interface RevisionProps { encItemKey: string | null authHash: string | null creationDate: Date - createdAt: Date - updatedAt: Date + timestamps: Timestamps } diff --git a/packages/revisions/src/Domain/Revision/RevisionRepositoryInterface.ts b/packages/revisions/src/Domain/Revision/RevisionRepositoryInterface.ts index 69262ff76..a1fb826eb 100644 --- a/packages/revisions/src/Domain/Revision/RevisionRepositoryInterface.ts +++ b/packages/revisions/src/Domain/Revision/RevisionRepositoryInterface.ts @@ -1,7 +1,9 @@ import { Uuid } from '@standardnotes/domain-core' +import { Revision } from './Revision' import { RevisionMetadata } from './RevisionMetadata' export interface RevisionRepositoryInterface { findMetadataByItemId(itemUuid: Uuid): Promise> + save(revision: Revision): Promise } diff --git a/packages/revisions/src/Infra/MySQL/MySQLRevisionRepository.ts b/packages/revisions/src/Infra/MySQL/MySQLRevisionRepository.ts index 7e636e00f..e5ebdfff1 100644 --- a/packages/revisions/src/Infra/MySQL/MySQLRevisionRepository.ts +++ b/packages/revisions/src/Infra/MySQL/MySQLRevisionRepository.ts @@ -1,5 +1,6 @@ import { MapperInterface, Uuid } from '@standardnotes/domain-core' import { Repository } from 'typeorm' +import { Revision } from '../../Domain/Revision/Revision' import { RevisionMetadata } from '../../Domain/Revision/RevisionMetadata' import { RevisionRepositoryInterface } from '../../Domain/Revision/RevisionRepositoryInterface' @@ -8,9 +9,18 @@ import { TypeORMRevision } from '../TypeORM/TypeORMRevision' export class MySQLRevisionRepository implements RevisionRepositoryInterface { constructor( private ormRepository: Repository, - private revisionMapper: MapperInterface, + private revisionMetadataMapper: MapperInterface, + private revisionMapper: MapperInterface, ) {} + async save(revision: Revision): Promise { + const typeormRevision = this.revisionMapper.toProjection(revision) + + await this.ormRepository.save(typeormRevision) + + return revision + } + async findMetadataByItemId(itemUuid: Uuid): Promise> { const queryBuilder = this.ormRepository .createQueryBuilder() @@ -27,7 +37,7 @@ export class MySQLRevisionRepository implements RevisionRepositoryInterface { const metadata = [] for (const simplifiedRevision of simplifiedRevisions) { - metadata.push(this.revisionMapper.toDomain(simplifiedRevision)) + metadata.push(this.revisionMetadataMapper.toDomain(simplifiedRevision)) } return metadata diff --git a/packages/revisions/src/Infra/S3/S3ItemDumpRepository.ts b/packages/revisions/src/Infra/S3/S3ItemDumpRepository.ts new file mode 100644 index 000000000..7533d544e --- /dev/null +++ b/packages/revisions/src/Infra/S3/S3ItemDumpRepository.ts @@ -0,0 +1,39 @@ +import { MapperInterface } from '@standardnotes/domain-core' +import { S3 } from 'aws-sdk' + +import { DumpRepositoryInterface } from '../../Domain/Dump/DumpRepositoryInterface' +import { Revision } from '../../Domain/Revision/Revision' + +export class S3DumpRepository implements DumpRepositoryInterface { + constructor( + private dumpBucketName: string, + private s3Client: S3, + private revisionStringItemMapper: MapperInterface, + ) {} + + async getRevisionFromDumpPath(path: string): Promise { + const s3Object = await this.s3Client + .getObject({ + Bucket: this.dumpBucketName, + Key: path, + }) + .promise() + + if (s3Object.Body === undefined) { + return null + } + + const revision = this.revisionStringItemMapper.toDomain(s3Object.Body as string) + + return revision + } + + async removeDump(path: string): Promise { + await this.s3Client + .deleteObject({ + Bucket: this.dumpBucketName, + Key: path, + }) + .promise() + } +} diff --git a/packages/revisions/src/Infra/TypeORM/TypeORMRevision.ts b/packages/revisions/src/Infra/TypeORM/TypeORMRevision.ts index b5711af43..2ac2ee17e 100644 --- a/packages/revisions/src/Infra/TypeORM/TypeORMRevision.ts +++ b/packages/revisions/src/Infra/TypeORM/TypeORMRevision.ts @@ -1,5 +1,3 @@ -import { ContentType } from '@standardnotes/common' - import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm' @Entity({ name: 'revisions' }) @@ -25,7 +23,7 @@ export class TypeORMRevision { length: 255, nullable: true, }) - declare contentType: ContentType | null + declare contentType: string | null @Column({ type: 'varchar', diff --git a/packages/revisions/src/Mapping/RevisionItemStringMapper.ts b/packages/revisions/src/Mapping/RevisionItemStringMapper.ts new file mode 100644 index 000000000..168d0664c --- /dev/null +++ b/packages/revisions/src/Mapping/RevisionItemStringMapper.ts @@ -0,0 +1,43 @@ +import { MapperInterface, Timestamps, Uuid } from '@standardnotes/domain-core' + +import { ContentType } from '../Domain/Revision/ContentType' +import { Revision } from '../Domain/Revision/Revision' + +export class RevisionItemStringMapper implements MapperInterface { + toDomain(projection: string): Revision { + const item = JSON.parse(projection) + + const contentTypeOrError = ContentType.create(item.content_type) + if (contentTypeOrError.isFailed()) { + throw new Error(`Could not map item string to revision: ${contentTypeOrError.getError()}`) + } + const contentType = contentTypeOrError.getValue() + + const itemUuidOrError = Uuid.create(item.uuid) + if (itemUuidOrError.isFailed()) { + throw new Error(`Could not map item string to revision: ${itemUuidOrError.getError()}`) + } + const itemUuid = itemUuidOrError.getValue() + + const revisionOrError = Revision.create({ + itemUuid, + authHash: item.auth_hash, + content: item.content, + contentType, + itemsKeyId: item.items_key_id, + encItemKey: item.enc_item_key, + creationDate: new Date(), + timestamps: Timestamps.create(new Date(), new Date()).getValue(), + }) + + if (revisionOrError.isFailed()) { + throw new Error(`Could not map item string to revision: ${revisionOrError.getError()}`) + } + + return revisionOrError.getValue() + } + + toProjection(domain: Revision): string { + return JSON.stringify(domain) + } +} diff --git a/packages/revisions/src/Mapping/RevisionPersistenceMapper.ts b/packages/revisions/src/Mapping/RevisionPersistenceMapper.ts new file mode 100644 index 000000000..0d0302400 --- /dev/null +++ b/packages/revisions/src/Mapping/RevisionPersistenceMapper.ts @@ -0,0 +1,62 @@ +import { MapperInterface, Timestamps, UniqueEntityId, Uuid } from '@standardnotes/domain-core' +import { ContentType } from '../Domain/Revision/ContentType' +import { Revision } from '../Domain/Revision/Revision' +import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision' + +export class RevisionPersistenceMapper implements MapperInterface { + toDomain(projection: TypeORMRevision): Revision { + const contentTypeOrError = ContentType.create(projection.contentType) + if (contentTypeOrError.isFailed()) { + throw new Error(`Could not map typeorm revision to domain revision: ${contentTypeOrError.getError()}`) + } + const contentType = contentTypeOrError.getValue() + + const timestampsOrError = Timestamps.create(projection.createdAt, projection.updatedAt) + if (timestampsOrError.isFailed()) { + throw new Error(`Could not map typeorm revision to domain revision: ${timestampsOrError.getError()}`) + } + const timestamps = timestampsOrError.getValue() + + const itemUuidOrError = Uuid.create(projection.itemUuid) + if (itemUuidOrError.isFailed()) { + throw new Error(`Could not map typeorm revision to domain revision: ${itemUuidOrError.getError()}`) + } + const itemUuid = itemUuidOrError.getValue() + + const revisionOrError = Revision.create( + { + authHash: projection.authHash, + content: projection.content, + contentType, + creationDate: projection.creationDate, + encItemKey: projection.encItemKey, + itemsKeyId: projection.itemsKeyId, + itemUuid, + timestamps, + }, + new UniqueEntityId(projection.uuid), + ) + if (revisionOrError.isFailed()) { + throw new Error(`Could not map typeorm revision to domain revision: ${revisionOrError.getError()}`) + } + + return revisionOrError.getValue() + } + + toProjection(domain: Revision): TypeORMRevision { + const typeormRevision = new TypeORMRevision() + + typeormRevision.authHash = domain.props.authHash + typeormRevision.content = domain.props.content + typeormRevision.contentType = domain.props.contentType.value + typeormRevision.createdAt = domain.props.timestamps.createdAt + typeormRevision.updatedAt = domain.props.timestamps.updatedAt + typeormRevision.creationDate = domain.props.creationDate + typeormRevision.encItemKey = domain.props.encItemKey + typeormRevision.itemUuid = domain.props.itemUuid.value + typeormRevision.itemsKeyId = domain.props.itemsKeyId + typeormRevision.uuid = domain.id.toString() + + return typeormRevision + } +} diff --git a/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.spec.ts b/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.spec.ts index 89eb67bd3..73e9111ac 100644 --- a/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.spec.ts +++ b/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.spec.ts @@ -5,16 +5,15 @@ import { DomainEventService, ItemRevisionCreationRequestedEvent, } from '@standardnotes/domain-events' + import { Item } from '../Item/Item' import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface' import { ItemRevisionCreationRequestedEventHandler } from './ItemRevisionCreationRequestedEventHandler' -import { RevisionServiceInterface } from '../Revision/RevisionServiceInterface' import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface' import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface' describe('ItemRevisionCreationRequestedEventHandler', () => { let itemRepository: ItemRepositoryInterface - let revisionService: RevisionServiceInterface let event: ItemRevisionCreationRequestedEvent let item: Item let itemBackupService: ItemBackupServiceInterface @@ -24,7 +23,6 @@ describe('ItemRevisionCreationRequestedEventHandler', () => { const createHandler = () => new ItemRevisionCreationRequestedEventHandler( itemRepository, - revisionService, itemBackupService, domainEventFactory, domainEventPublisher, @@ -39,9 +37,6 @@ describe('ItemRevisionCreationRequestedEventHandler', () => { itemRepository = {} as jest.Mocked itemRepository.findByUuid = jest.fn().mockReturnValue(item) - revisionService = {} as jest.Mocked - revisionService.createRevision = jest.fn() - event = {} as jest.Mocked event.createdAt = new Date(1) event.payload = { @@ -68,7 +63,6 @@ describe('ItemRevisionCreationRequestedEventHandler', () => { it('should create a revision for an item', async () => { await createHandler().handle(event) - expect(revisionService.createRevision).toHaveBeenCalled() expect(domainEventPublisher.publish).toHaveBeenCalled() expect(domainEventFactory.createItemDumpedEvent).toHaveBeenCalled() }) @@ -78,7 +72,7 @@ describe('ItemRevisionCreationRequestedEventHandler', () => { await createHandler().handle(event) - expect(revisionService.createRevision).not.toHaveBeenCalled() + expect(domainEventPublisher.publish).not.toHaveBeenCalled() }) it('should not create a revision for an item if the dump was not created', async () => { diff --git a/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.ts b/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.ts index 9a17c1022..468944e40 100644 --- a/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.ts +++ b/packages/syncing-server/src/Domain/Handler/ItemRevisionCreationRequestedEventHandler.ts @@ -9,13 +9,11 @@ import TYPES from '../../Bootstrap/Types' import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface' import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface' import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface' -import { RevisionServiceInterface } from '../Revision/RevisionServiceInterface' @injectable() export class ItemRevisionCreationRequestedEventHandler implements DomainEventHandlerInterface { constructor( @inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface, - @inject(TYPES.RevisionService) private revisionService: RevisionServiceInterface, @inject(TYPES.ItemBackupService) private itemBackupService: ItemBackupServiceInterface, @inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface, @inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface, @@ -33,7 +31,5 @@ export class ItemRevisionCreationRequestedEventHandler implements DomainEventHan this.domainEventFactory.createItemDumpedEvent(fileDumpPath, event.meta.correlation.userIdentifier), ) } - - await this.revisionService.createRevision(item) } }