diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/__tests__/record-position-backfill-service.spec.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/__tests__/record-position-backfill-service.spec.ts deleted file mode 100644 index a6e929240..000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/__tests__/record-position-backfill-service.spec.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { getRepositoryToken } from '@nestjs/typeorm'; - -import { FieldMetadataType } from 'twenty-shared/types'; - -import { RecordPositionBackfillService } from 'src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-service'; -import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; - -describe('RecordPositionBackfillService', () => { - let recordPositionService; - let objectMetadataRepository; - let workspaceDataSourceService; - - let service: RecordPositionBackfillService; - - beforeEach(async () => { - recordPositionService = { - buildRecordPosition: jest.fn().mockResolvedValue([ - { - position: 1, - }, - ]), - }; - - objectMetadataRepository = { - find: jest.fn().mockReturnValue([]), - }; - - workspaceDataSourceService = { - getSchemaName: jest.fn().mockReturnValue('schemaName'), - executeRawQuery: jest.fn().mockResolvedValue([]), - }; - const module: TestingModule = await Test.createTestingModule({ - providers: [ - RecordPositionBackfillService, - { - provide: RecordPositionService, - useValue: recordPositionService, - }, - { - provide: WorkspaceDataSourceService, - useValue: workspaceDataSourceService, - }, - { - provide: getRepositoryToken(ObjectMetadataEntity, 'metadata'), - useValue: objectMetadataRepository, - }, - ], - }).compile(); - - service = module.get( - RecordPositionBackfillService, - ); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); - - it('when no object metadata found, should do nothing', async () => { - await service.backfill('workspaceId', false); - expect(workspaceDataSourceService.executeRawQuery).not.toHaveBeenCalled(); - }); - - it('when objectMetadata without position, should do nothing', async () => { - objectMetadataRepository.find.mockReturnValue([]); - await service.backfill('workspaceId', false); - expect(workspaceDataSourceService.executeRawQuery).not.toHaveBeenCalled(); - }); - - it('when objectMetadata but all record with position, should create and run query once', async () => { - objectMetadataRepository.find.mockReturnValue([ - { - id: '1', - nameSingular: 'company', - fields: [ - { - type: FieldMetadataType.POSITION, - isCustom: true, - nameSingular: 'position', - }, - ], - }, - ]); - await service.backfill('workspaceId', false); - expect(workspaceDataSourceService.executeRawQuery).toHaveBeenCalledTimes(1); - }); - - it('when record without position, should create and run query twice', async () => { - objectMetadataRepository.find.mockReturnValue([ - { - id: '1', - nameSingular: 'company', - fields: [ - { - type: FieldMetadataType.POSITION, - isCustom: true, - nameSingular: 'position', - }, - ], - }, - ]); - workspaceDataSourceService.executeRawQuery.mockResolvedValueOnce([ - { - id: '1', - }, - ]); - await service.backfill('workspaceId', false); - expect(workspaceDataSourceService.executeRawQuery).toHaveBeenCalledTimes(2); - expect(recordPositionService.buildRecordPosition).toHaveBeenCalledTimes(1); - }); - - it('when dryRun is true, should not update position', async () => { - objectMetadataRepository.find.mockReturnValue([ - { - id: '1', - nameSingular: 'company', - fields: [ - { - type: FieldMetadataType.POSITION, - isCustom: true, - nameSingular: 'position', - }, - ], - }, - ]); - workspaceDataSourceService.executeRawQuery.mockResolvedValueOnce([ - { - id: '1', - }, - ]); - await service.backfill('workspaceId', true); - expect(workspaceDataSourceService.executeRawQuery).toHaveBeenCalledTimes(1); - expect(recordPositionService.buildRecordPosition).toHaveBeenCalledTimes(1); - }); -}); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-module.ts deleted file mode 100644 index 08aaa8c6c..000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { RecordPositionBackfillService } from 'src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-service'; -import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; - -@Module({ - imports: [ - WorkspaceDataSourceModule, - TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), - ], - providers: [RecordPositionService, RecordPositionBackfillService], - exports: [RecordPositionBackfillService], -}) -export class RecordPositionBackfillModule {} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-service.ts deleted file mode 100644 index e98b47d27..000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-service.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { isDefined } from 'class-validator'; -import { FieldMetadataType } from 'twenty-shared/types'; -import { Repository } from 'typeorm'; - -import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service'; -import { RecordPositionQueryType } from 'src/engine/core-modules/record-position/types/record-position-query.type'; -import { buildRecordPositionQuery } from 'src/engine/core-modules/record-position/utils/build-record-position-query.util'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; - -@Injectable() -export class RecordPositionBackfillService { - private readonly logger = new Logger(RecordPositionBackfillService.name); - constructor( - @InjectRepository(ObjectMetadataEntity, 'metadata') - private readonly objectMetadataRepository: Repository, - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - private readonly recordPositionService: RecordPositionService, - ) {} - - async backfill(workspaceId: string, dryRun: boolean) { - this.logger.log( - `Starting backfilling record positions for workspace ${workspaceId}`, - ); - - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - const objectMetadataCollection = await this.objectMetadataRepository.find({ - where: { - workspaceId, - fields: { - name: 'position', - type: FieldMetadataType.POSITION, - }, - }, - relations: { - fields: true, - }, - }); - - for (const objectMetadata of objectMetadataCollection) { - const [recordsWithoutPositionQuery, recordsWithoutPositionQueryParams] = - buildRecordPositionQuery( - { - recordPositionQueryType: RecordPositionQueryType.FIND_BY_POSITION, - positionValue: null, - }, - objectMetadata, - dataSourceSchema, - ); - - const recordsWithoutPosition = - await this.workspaceDataSourceService.executeRawQuery( - recordsWithoutPositionQuery, - recordsWithoutPositionQueryParams, - workspaceId, - ); - - if ( - !isDefined(recordsWithoutPosition) || - recordsWithoutPosition?.length === 0 - ) { - this.logger.log( - `No records without position for ${objectMetadata.nameSingular}`, - ); - continue; - } - - const position = await this.recordPositionService.buildRecordPosition({ - objectMetadata: { - isCustom: objectMetadata.isCustom, - nameSingular: objectMetadata.nameSingular, - }, - value: 'last', - workspaceId, - }); - - for ( - let recordIndex = 0; - recordIndex < recordsWithoutPosition.length; - recordIndex++ - ) { - const recordId = recordsWithoutPosition[recordIndex].id; - - if (!recordId) { - this.logger.log( - `Fetched record without id for ${objectMetadata.nameSingular}`, - ); - continue; - } - - const backfilledPosition = position + recordIndex; - - this.logger.log( - `Backfilling position ${backfilledPosition} for ${objectMetadata.nameSingular} ${recordId}`, - ); - - if (dryRun) { - continue; - } - - const [query, params] = buildRecordPositionQuery( - { - recordPositionQueryType: RecordPositionQueryType.UPDATE_POSITION, - recordId: recordsWithoutPosition[recordIndex].id, - positionValue: position + recordIndex, - }, - objectMetadata, - dataSourceSchema, - ); - - await this.workspaceDataSourceService.executeRawQuery( - query, - params, - workspaceId, - ); - } - } - } -}