Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update searchVector at label identifier update for custom fields #7588

Merged
merged 12 commits into from
Oct 15, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const mapPaginatedObjectMetadataItemsToObjectMetadataItems = ({
pagedObjectMetadataItems?.objects.edges.map((object) => ({
...object.node,
fields: object.node.fields.edges.map((field) => field.node),
indexMetadatas: object.node.indexMetadatas.edges.map((index) => ({
indexMetadatas: object.node.indexMetadatas?.edges.map((index) => ({
...index.node,
indexFieldMetadatas: index.node.indexFieldMetadatas?.edges.map(
(indexField) => indexField.node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DataSeedDemoWorkspaceCommand } from 'src/database/commands/data-seed-de
import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module';
import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command';
import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question';
import { SimplifySearchVectorExpressionCommandModule } from 'src/database/commands/upgrade-version/0-31/0-32/0-32-simplify-search-vector-expression.module';
import { UpgradeTo0_32CommandModule } from 'src/database/commands/upgrade-version/0-32/0-32-upgrade-version.module';
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
Expand Down Expand Up @@ -46,6 +47,7 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp
DataSeedDemoWorkspaceModule,
WorkspaceCacheStorageModule,
WorkspaceMetadataVersionModule,
SimplifySearchVectorExpressionCommandModule,
UpgradeTo0_32CommandModule,
FeatureFlagModule,
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

import { SimplifySearchVectorExpressionCommand } from 'src/database/commands/upgrade-version/0-31/0-32/0-32-simplify-search-vector-expression';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { SearchModule } from 'src/engine/metadata-modules/search/search.module';
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module';

@Module({
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far I did not added this command to an upgrade-0.32 set of command as we would only want to run it twice and not to run it for self hosting

imports: [
TypeOrmModule.forFeature([Workspace], 'core'),
TypeOrmModule.forFeature([FieldMetadataEntity], 'metadata'),
WorkspaceSyncMetadataCommandsModule,
SearchModule,
WorkspaceMigrationRunnerModule,
],
providers: [SimplifySearchVectorExpressionCommand],
})
export class SimplifySearchVectorExpressionCommandModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { InjectRepository } from '@nestjs/typeorm';

import chalk from 'chalk';
import { Command } from 'nest-commander';
import { Repository } from 'typeorm';

import {
ActiveWorkspacesCommandOptions,
ActiveWorkspacesCommandRunner,
} from 'src/database/commands/active-workspaces.command';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import {
FieldMetadataEntity,
FieldMetadataType,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { SearchService } from 'src/engine/metadata-modules/search/search.service';
import { SEARCH_FIELDS_FOR_CUSTOM_OBJECT } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
import {
COMPANY_STANDARD_FIELD_IDS,
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
OPPORTUNITY_STANDARD_FIELD_IDS,
PERSON_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { SEARCH_FIELDS_FOR_COMPANY } from 'src/modules/company/standard-objects/company.workspace-entity';
import { SEARCH_FIELDS_FOR_OPPORTUNITY } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { SEARCH_FIELDS_FOR_PERSON } from 'src/modules/person/standard-objects/person.workspace-entity';

@Command({
name: 'upgrade-0.32:simplify-search-vector-expression',
description: 'Replace searchVector with simpler expression',
})
export class SimplifySearchVectorExpressionCommand extends ActiveWorkspacesCommandRunner {
constructor(
@InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>,
@InjectRepository(FieldMetadataEntity, 'metadata')
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
private readonly searchService: SearchService,
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
) {
super(workspaceRepository);
}

async executeActiveWorkspacesCommand(
_passedParam: string[],
_options: ActiveWorkspacesCommandOptions,
workspaceIds: string[],
): Promise<void> {
this.logger.log('Running command to fix migration');

for (const workspaceId of workspaceIds) {
this.logger.log(`Running command for workspace ${workspaceId}`);

try {
const searchVectorFields = await this.fieldMetadataRepository.findBy({
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Weiko I could add some very specific logic here to filter out fields whose entry in _typeorm_generated_columns_and_materialized_views has a value containing "CASE" (it would imply declaring/creating the repository etc for this entity that we kind of decided to set aside so far). This would make the command idempotent, while it is not completely the case here - if we run the command multiple times the output will be the same but we will have re-created the column and index.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine recreating everything as it will be executed only once. We can even go further and truncate the _typeorm_generated_columns_and_materialized_views table

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, as we just discussed I will do the truncate manually on the db so I can first test on a workspace independently.

workspaceId: workspaceId,
type: FieldMetadataType.TS_VECTOR,
});

for (const searchVectorField of searchVectorFields) {
let fieldsUsedForSearch: FieldTypeAndNameMetadata[] = [];

switch (searchVectorField.standardId) {
case CUSTOM_OBJECT_STANDARD_FIELD_IDS.searchVector: {
fieldsUsedForSearch = SEARCH_FIELDS_FOR_CUSTOM_OBJECT;
break;
}
case PERSON_STANDARD_FIELD_IDS.searchVector: {
fieldsUsedForSearch = SEARCH_FIELDS_FOR_PERSON;
break;
}
case COMPANY_STANDARD_FIELD_IDS.searchVector: {
fieldsUsedForSearch = SEARCH_FIELDS_FOR_COMPANY;
break;
}
case OPPORTUNITY_STANDARD_FIELD_IDS.searchVector: {
fieldsUsedForSearch = SEARCH_FIELDS_FOR_OPPORTUNITY;
break;
}
default: {
throw new Error(
`search vector has unexpected standardId: ${searchVectorField.standardId}`,
);
}
}

await this.searchService.updateSearchVector(
searchVectorField.objectMetadataId,
fieldsUsedForSearch,
workspaceId,
);

await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
workspaceId,
);
}
} catch (error) {
this.logger.log(
chalk.red(
`Running command on workspace ${workspaceId} failed with error: ${error}`,
),
);
continue;
} finally {
this.logger.log(
chalk.green(`Finished running command for workspace ${workspaceId}.`),
);
}

this.logger.log(chalk.green(`Command completed!`));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
import { generateNullable } from 'src/engine/metadata-modules/field-metadata/utils/generate-nullable';
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import {
RelationMetadataEntity,
Expand Down Expand Up @@ -76,7 +75,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(ObjectMetadataEntity, 'metadata')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
private readonly objectMetadataService: ObjectMetadataService,
private readonly workspaceMigrationFactory: WorkspaceMigrationFactory,
private readonly workspaceMigrationService: WorkspaceMigrationService,
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { IndexMetadataModule } from 'src/engine/metadata-modules/index-metadata/index-metadata.module';
import { BeforeUpdateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-update-one-object.hook';
import { ObjectMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/object-metadata/interceptors/object-metadata-graphql-api-exception.interceptor';
import { ObjectMetadataResolver } from 'src/engine/metadata-modules/object-metadata/object-metadata.resolver';
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { RemoteTableRelationsModule } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.module';
import { SearchModule } from 'src/engine/metadata-modules/search/search.module';
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
Expand All @@ -46,8 +46,8 @@ import { UpdateObjectPayload } from './dtos/update-object.input';
WorkspaceMigrationRunnerModule,
WorkspaceMetadataVersionModule,
RemoteTableRelationsModule,
IndexMetadataModule,
FeatureFlagModule,
SearchModule,
],
services: [ObjectMetadataService],
resolvers: [
Expand Down
Loading
Loading