[fix] Increment cache version after object/field/relation update (#5316)

Fixes #5276.

Updates were not triggering a cache version incrementation because they
do not trigger migrations while that is where the caching version logic
was.
We have decided to move the cache incrementation logic to the services.
This commit is contained in:
Marie
2024-05-07 16:30:25 +02:00
committed by GitHub
parent b0d1cc9dcb
commit 7c3e82870c
22 changed files with 160 additions and 39 deletions

View File

@ -27,7 +27,7 @@ const documents = {
"\n mutation CreateOneFieldMetadataItem($input: CreateOneFieldMetadataInput!) {\n createOneField(input: $input) {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n defaultValue\n options\n }\n }\n": types.CreateOneFieldMetadataItemDocument,
"\n mutation CreateOneRelationMetadata($input: CreateOneRelationInput!) {\n createOneRelation(input: $input) {\n id\n relationType\n fromObjectMetadataId\n toObjectMetadataId\n fromFieldMetadataId\n toFieldMetadataId\n createdAt\n updatedAt\n }\n }\n": types.CreateOneRelationMetadataDocument,
"\n mutation UpdateOneFieldMetadataItem(\n $idToUpdate: UUID!\n $updatePayload: UpdateFieldInput!\n ) {\n updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.UpdateOneFieldMetadataItemDocument,
"\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: UUID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n": types.UpdateOneObjectMetadataItemDocument,
"\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: UUID!\n $updatePayload: UpdateObjectPayload!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n": types.UpdateOneObjectMetadataItemDocument,
"\n mutation DeleteOneObjectMetadataItem($idToDelete: UUID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n": types.DeleteOneObjectMetadataItemDocument,
"\n mutation DeleteOneFieldMetadataItem($idToDelete: UUID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneFieldMetadataItemDocument,
"\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n toFieldMetadataId\n }\n toRelationMetadata {\n id\n relationType\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n fromFieldMetadataId\n }\n defaultValue\n options\n relationDefinition {\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n": types.ObjectMetadataItemsDocument,
@ -106,7 +106,7 @@ export function graphql(source: "\n mutation UpdateOneFieldMetadataItem(\n $
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: UUID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n"): (typeof documents)["\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: UUID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n"];
export function graphql(source: "\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: UUID!\n $updatePayload: UpdateObjectPayload!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n"): (typeof documents)["\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: UUID!\n $updatePayload: UpdateObjectPayload!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/

File diff suppressed because one or more lines are too long

View File

@ -80,7 +80,7 @@ export const UPDATE_ONE_FIELD_METADATA_ITEM = gql`
export const UPDATE_ONE_OBJECT_METADATA_ITEM = gql`
mutation UpdateOneObjectMetadataItem(
$idToUpdate: UUID!
$updatePayload: UpdateObjectInput!
$updatePayload: UpdateObjectPayload!
) {
updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {
id

View File

@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
export const query = gql`
mutation UpdateOneObjectMetadataItem(
$idToUpdate: UUID!
$updatePayload: UpdateObjectInput!
$updatePayload: UpdateObjectPayload!
) {
updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {
id

View File

@ -2,7 +2,7 @@ import { useMutation } from '@apollo/client';
import { getOperationName } from '@apollo/client/utilities';
import {
UpdateObjectInput,
UpdateOneObjectInput,
UpdateOneObjectMetadataItemMutation,
UpdateOneObjectMetadataItemMutationVariables,
} from '~/generated-metadata/graphql';
@ -27,8 +27,8 @@ export const useUpdateOneObjectMetadataItem = () => {
idToUpdate,
updatePayload,
}: {
idToUpdate: UpdateOneObjectMetadataItemMutationVariables['idToUpdate'];
updatePayload: UpdateObjectInput;
idToUpdate: UpdateOneObjectInput['id'];
updatePayload: UpdateOneObjectInput['update'];
}) => {
return await mutate({
variables: {

View File

@ -1,6 +1,6 @@
import { SafeParseSuccess } from 'zod';
import { UpdateObjectInput } from '~/generated-metadata/graphql';
import { UpdateObjectPayload } from '~/generated-metadata/graphql';
import { settingsUpdateObjectInputSchema } from '../settingsUpdateObjectInputSchema';
@ -20,7 +20,7 @@ describe('settingsUpdateObjectInputSchema', () => {
// Then
expect(result.success).toBe(true);
expect((result as SafeParseSuccess<UpdateObjectInput>).data).toEqual({
expect((result as SafeParseSuccess<UpdateObjectPayload>).data).toEqual({
description: validInput.description,
icon: validInput.icon,
labelIdentifierFieldMetadataId: validInput.labelIdentifierFieldMetadataId,

View File

@ -1,5 +1,5 @@
import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema';
import { UpdateObjectInput } from '~/generated-metadata/graphql';
import { UpdateObjectPayload } from '~/generated-metadata/graphql';
import { formatMetadataLabelToMetadataNameOrThrows } from '~/pages/settings/data-model/utils/format-metadata-label-to-name.util';
export const settingsUpdateObjectInputSchema = objectMetadataItemSchema
@ -13,7 +13,7 @@ export const settingsUpdateObjectInputSchema = objectMetadataItemSchema
labelSingular: true,
})
.partial()
.transform<UpdateObjectInput>((value) => ({
.transform<UpdateObjectPayload>((value) => ({
...value,
nameSingular: value.labelSingular
? formatMetadataLabelToMetadataNameOrThrows(value.labelSingular)

View File

@ -17,6 +17,7 @@ import { IsFieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-m
import { FieldMetadataResolver } from 'src/engine/metadata-modules/field-metadata/field-metadata.resolver';
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
import { IsFieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-options.validator';
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
import { FieldMetadataService } from './field-metadata.service';
import { FieldMetadataEntity } from './field-metadata.entity';
@ -31,6 +32,7 @@ import { UpdateFieldInput } from './dtos/update-field.input';
NestjsQueryTypeOrmModule.forFeature([FieldMetadataEntity], 'metadata'),
WorkspaceMigrationModule,
WorkspaceMigrationRunnerModule,
WorkspaceCacheVersionModule,
ObjectMetadataModule,
DataSourceModule,
TypeORMModule,

View File

@ -41,6 +41,7 @@ import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/ut
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { InvalidStringException } from 'src/engine/metadata-modules/errors/InvalidStringException';
import { validateMetadataName } from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
import {
FieldMetadataEntity,
@ -64,6 +65,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
private readonly dataSourceService: DataSourceService,
private readonly typeORMService: TypeORMService,
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
) {
super(fieldMetadataRepository);
}
@ -232,6 +234,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
throw error;
} finally {
await queryRunner.release();
await this.workspaceCacheVersionService.incrementVersion(
fieldMetadataInput.workspaceId,
);
}
}
@ -358,6 +363,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
throw error;
} finally {
await queryRunner.release();
await this.workspaceCacheVersionService.incrementVersion(
fieldMetadataInput.workspaceId,
);
}
}
@ -429,6 +437,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
throw error;
} finally {
await queryRunner.release();
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
}
}
@ -466,6 +475,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
public async deleteFieldsMetadata(workspaceId: string) {
await this.fieldMetadataRepository.delete({ workspaceId });
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
}
private buildUpdatableStandardFieldInput(

View File

@ -1,14 +1,20 @@
import { Field, InputType } from '@nestjs/graphql';
import { BeforeUpdateOne } from '@ptc-org/nestjs-query-graphql';
import { IsBoolean, IsOptional, IsString, IsUUID } from 'class-validator';
import {
IsBoolean,
IsNotEmpty,
IsOptional,
IsString,
IsUUID,
} from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
import { BeforeUpdateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-update-one-object.hook';
@InputType()
@BeforeUpdateOne(BeforeUpdateOneObject)
export class UpdateObjectInput {
export class UpdateObjectPayload {
@IsString()
@IsOptional()
@Field({ nullable: true })
@ -56,3 +62,17 @@ export class UpdateObjectInput {
@Field({ nullable: true })
imageIdentifierFieldMetadataId?: string;
}
@InputType()
@BeforeUpdateOne(BeforeUpdateOneObject)
export class UpdateOneObjectInput {
@Field(() => UpdateObjectPayload)
update: UpdateObjectPayload;
@IsNotEmpty()
@Field(() => UUIDScalarType, {
description: 'The id of the object to update',
})
@IsUUID()
id!: string;
}

View File

@ -12,12 +12,12 @@ import {
import { Equal, In, Repository } from 'typeorm';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { UpdateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
import { UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@Injectable()
export class BeforeUpdateOneObject<T extends UpdateObjectInput>
export class BeforeUpdateOneObject<T extends UpdateObjectPayload>
implements BeforeUpdateOneHook<T, any>
{
constructor(
@ -108,7 +108,7 @@ export class BeforeUpdateOneObject<T extends UpdateObjectInput>
// This is temporary until we properly use the MigrationRunner to update column names
private checkIfFieldIsEditable(
update: UpdateObjectInput,
update: UpdateObjectPayload,
objectMetadata: ObjectMetadataEntity,
) {
if (

View File

@ -18,12 +18,13 @@ import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-met
import { ObjectMetadataResolver } from 'src/engine/metadata-modules/object-metadata/object-metadata.resolver';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
import { ObjectMetadataService } from './object-metadata.service';
import { ObjectMetadataEntity } from './object-metadata.entity';
import { CreateObjectInput } from './dtos/create-object.input';
import { UpdateObjectInput } from './dtos/update-object.input';
import { UpdateObjectPayload } from './dtos/update-object.input';
import { ObjectMetadataDTO } from './dtos/object-metadata.dto';
@Module({
@ -39,6 +40,7 @@ import { ObjectMetadataDTO } from './dtos/object-metadata.dto';
DataSourceModule,
WorkspaceMigrationModule,
WorkspaceMigrationRunnerModule,
WorkspaceCacheVersionModule,
FeatureFlagModule,
],
services: [ObjectMetadataService],
@ -47,7 +49,7 @@ import { ObjectMetadataDTO } from './dtos/object-metadata.dto';
EntityClass: ObjectMetadataEntity,
DTOClass: ObjectMetadataDTO,
CreateDTOClass: CreateObjectInput,
UpdateDTOClass: UpdateObjectInput,
UpdateDTOClass: UpdateObjectPayload,
ServiceClass: ObjectMetadataService,
pagingStrategy: PagingStrategies.CURSOR,
read: {
@ -56,9 +58,7 @@ import { ObjectMetadataDTO } from './dtos/object-metadata.dto';
create: {
many: { disabled: true },
},
update: {
many: { disabled: true },
},
update: { disabled: true },
delete: { disabled: true },
guards: [JwtAuthGuard],
},

View File

@ -7,6 +7,7 @@ import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
import { DeleteOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/delete-object.input';
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
import { UpdateOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
@UseGuards(JwtAuthGuard)
@Resolver(() => ObjectMetadataDTO)
@ -20,4 +21,12 @@ export class ObjectMetadataResolver {
) {
return this.objectMetadataService.deleteOneObject(input, workspaceId);
}
@Mutation(() => ObjectMetadataDTO)
updateOneObject(
@Args('input') input: UpdateOneObjectInput,
@AuthWorkspace() { id: workspaceId }: Workspace,
) {
return this.objectMetadataService.updateOneObject(input, workspaceId);
}
}

View File

@ -60,6 +60,8 @@ import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/ut
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { validateObjectMetadataInput } from 'src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util';
import { mapUdtNameToFieldType } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
import { UpdateOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
import { ObjectMetadataEntity } from './object-metadata.entity';
@ -81,6 +83,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
private readonly typeORMService: TypeORMService,
private readonly workspaceMigrationService: WorkspaceMigrationService,
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
) {
super(objectMetadataRepository);
}
@ -225,6 +228,8 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
workspaceId,
);
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
return objectMetadata;
}
@ -399,9 +404,24 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
);
});
await this.workspaceCacheVersionService.incrementVersion(
objectMetadataInput.workspaceId,
);
return createdObjectMetadata;
}
public async updateOneObject(
input: UpdateOneObjectInput,
workspaceId: string,
): Promise<ObjectMetadataEntity> {
const updatedObject = await super.updateOne(input.id, input.update);
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
return updatedObject;
}
public async findOneWithinWorkspace(
workspaceId: string,
options: FindOneOptions<ObjectMetadataEntity>,
@ -475,6 +495,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
public async deleteObjectsMetadata(workspaceId: string) {
await this.objectMetadataRepository.delete({ workspaceId });
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
}
private async createObjectRelationsMetadataAndMigrations(

View File

@ -2,11 +2,11 @@ import { BadRequestException } from '@nestjs/common';
import { InvalidStringException } from 'src/engine/metadata-modules/errors/InvalidStringException';
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
import { UpdateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
import { UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
import { validateMetadataName } from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
export const validateObjectMetadataInput = <
T extends UpdateObjectInput | CreateObjectInput,
T extends UpdateObjectPayload | CreateObjectInput,
>(
objectMetadataInput: T,
): void => {

View File

@ -0,0 +1,13 @@
import { InputType } from '@nestjs/graphql';
import { IDField } from '@ptc-org/nestjs-query-graphql';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
@InputType()
export class DeleteOneRelationInput {
@IDField(() => UUIDScalarType, {
description: 'The id of the relation to delete.',
})
id!: string;
}

View File

@ -11,6 +11,8 @@ import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.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';
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
import { RelationMetadataResolver } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.resolver';
import { RelationMetadataService } from './relation-metadata.service';
import { RelationMetadataEntity } from './relation-metadata.entity';
@ -30,6 +32,7 @@ import { RelationMetadataDTO } from './dtos/relation-metadata.dto';
FieldMetadataModule,
WorkspaceMigrationRunnerModule,
WorkspaceMigrationModule,
WorkspaceCacheVersionModule,
],
services: [RelationMetadataService],
resolvers: [
@ -41,13 +44,13 @@ import { RelationMetadataDTO } from './dtos/relation-metadata.dto';
pagingStrategy: PagingStrategies.CURSOR,
create: { many: { disabled: true } },
update: { disabled: true },
delete: { many: { disabled: true } },
delete: { disabled: true },
guards: [JwtAuthGuard],
},
],
}),
],
providers: [RelationMetadataService],
providers: [RelationMetadataService, RelationMetadataResolver],
exports: [RelationMetadataService],
})
export class RelationMetadataModule {}

View File

@ -0,0 +1,28 @@
import { UseGuards } from '@nestjs/common';
import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { RelationMetadataService } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.service';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { RelationMetadataDTO } from 'src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto';
import { DeleteOneRelationInput } from 'src/engine/metadata-modules/relation-metadata/dtos/delete-relation.input';
@UseGuards(JwtAuthGuard)
@Resolver()
export class RelationMetadataResolver {
constructor(
private readonly relationMetadataService: RelationMetadataService,
) {}
@Mutation(() => RelationMetadataDTO)
deleteOneRelation(
@Args('input') input: DeleteOneRelationInput,
@AuthWorkspace() { id: workspaceId }: Workspace,
) {
return this.relationMetadataService.deleteOneRelation(
input.id,
workspaceId,
);
}
}

View File

@ -26,6 +26,7 @@ import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
import { InvalidStringException } from 'src/engine/metadata-modules/errors/InvalidStringException';
import { validateMetadataName } from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
import {
RelationMetadataEntity,
@ -42,6 +43,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
private readonly fieldMetadataService: FieldMetadataService,
private readonly workspaceMigrationService: WorkspaceMigrationService,
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
) {
super(relationMetadataRepository);
}
@ -110,6 +112,10 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
relationMetadataInput.workspaceId,
);
await this.workspaceCacheVersionService.incrementVersion(
relationMetadataInput.workspaceId,
);
return createdRelationMetadata;
}
@ -307,7 +313,10 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
});
}
override async deleteOne(id: string): Promise<RelationMetadataEntity> {
public async deleteOneRelation(
id: string,
workspaceId: string,
): Promise<RelationMetadataEntity> {
// TODO: This logic is duplicated with the BeforeDeleteOneRelation hook
const relationMetadata = await this.relationMetadataRepository.findOne({
where: { id },
@ -318,10 +327,10 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
throw new NotFoundException('Relation does not exist');
}
const deletedRelationMetadata = super.deleteOne(id);
await super.deleteOne(id);
// TODO: Move to a cdc scheduler
this.fieldMetadataService.deleteMany({
await this.fieldMetadataService.deleteMany({
id: {
in: [
relationMetadata.fromFieldMetadataId,
@ -330,7 +339,10 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
},
});
return deletedRelationMetadata;
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
// TODO: Return id for delete endpoints
return relationMetadata;
}
async findManyRelationMetadataByFieldMetadataIds(

View File

@ -100,9 +100,6 @@ export class WorkspaceMigrationRunnerService {
);
}
// Increment workspace cache version
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
return flattenedPendingMigrations;
}

View File

@ -15,6 +15,7 @@ import { WorkspaceSyncObjectMetadataService } from 'src/engine/workspace-manager
import { WorkspaceSyncRelationMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-relation-metadata.service';
import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service';
import { WorkspaceMigrationBuilderModule } from 'src/engine/workspace-manager/workspace-migration-builder/workspace-migration-builder.module';
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
@Module({
imports: [
@ -30,6 +31,7 @@ import { WorkspaceMigrationBuilderModule } from 'src/engine/workspace-manager/wo
'metadata',
),
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
WorkspaceCacheVersionModule,
],
providers: [
...workspaceSyncMetadataFactories,

View File

@ -12,6 +12,7 @@ import { WorkspaceSyncRelationMetadataService } from 'src/engine/workspace-manag
import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service';
import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage';
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
interface SynchronizeOptions {
applyChanges?: boolean;
@ -29,6 +30,7 @@ export class WorkspaceSyncMetadataService {
private readonly workspaceSyncObjectMetadataService: WorkspaceSyncObjectMetadataService,
private readonly workspaceSyncRelationMetadataService: WorkspaceSyncRelationMetadataService,
private readonly workspaceSyncFieldMetadataService: WorkspaceSyncFieldMetadataService,
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
) {}
/**
@ -127,6 +129,9 @@ export class WorkspaceSyncMetadataService {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
await this.workspaceCacheVersionService.incrementVersion(
context.workspaceId,
);
}
return {