fix: nlp sample inconsistency when language is deleted

This commit is contained in:
Mohamed Marrouchi
2024-09-24 16:21:00 +01:00
parent 82dd888f2f
commit 6652629995
8 changed files with 78 additions and 17 deletions

View File

@@ -9,6 +9,7 @@
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { MongooseModule } from '@nestjs/mongoose';
import { Test } from '@nestjs/testing';
@@ -63,6 +64,7 @@ describe('LanguageController', () => {
},
},
LoggerService,
EventEmitter2,
],
}).compile();
languageService = module.get<LanguageService>(LanguageService);

View File

@@ -8,16 +8,46 @@
*/
import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Document, Model, Query, TFilterQuery } from 'mongoose';
import { BaseRepository } from '@/utils/generics/base-repository';
import { BaseRepository, DeleteResult } from '@/utils/generics/base-repository';
import { Language } from '../schemas/language.schema';
@Injectable()
export class LanguageRepository extends BaseRepository<Language> {
constructor(@InjectModel(Language.name) readonly model: Model<Language>) {
constructor(
@InjectModel(Language.name) readonly model: Model<Language>,
private readonly eventEmitter: EventEmitter2,
) {
super(model, Language);
}
/**
* Pre-delete hook that triggers before an language is deleted.
*
* @param query The query used to delete the language.
* @param criteria The filter criteria used to find the language for deletion.
*/
async preDelete(
_query: Query<
DeleteResult,
Document<Language, any, any>,
unknown,
Language,
'deleteOne' | 'deleteMany'
>,
criteria: TFilterQuery<Language>,
): Promise<void> {
if (criteria._id) {
const language = await this.findOne(
typeof criteria === 'string' ? { _id: criteria } : criteria,
);
this.eventEmitter.emit('hook:language:delete', language);
} else {
throw new Error('Attempted to delete language using unknown criteria');
}
}
}

View File

@@ -11,6 +11,7 @@ import { Prop, Schema, SchemaFactory, ModelDefinition } from '@nestjs/mongoose';
import { THydratedDocument } from 'mongoose';
import { BaseSchema } from '@/utils/generics/base-schema';
import { LifecycleHookManager } from '@/utils/generics/lifecycle-hook-manager';
@Schema({ timestamps: true })
export class Language extends BaseSchema {
@@ -41,10 +42,10 @@ export class Language extends BaseSchema {
isRTL?: boolean;
}
export const LanguageModel: ModelDefinition = {
export const LanguageModel: ModelDefinition = LifecycleHookManager.attach({
name: Language.name,
schema: SchemaFactory.createForClass(Language),
};
});
export type LanguageDocument = THydratedDocument<Language>;

View File

@@ -49,15 +49,15 @@ export class NlpSampleStub extends BaseSchema {
@Prop({
type: MongooseSchema.Types.ObjectId,
ref: 'Language',
required: true,
required: false,
})
language: unknown;
language: unknown | null;
}
@Schema({ timestamps: true })
export class NlpSample extends NlpSampleStub {
@Transform(({ obj }) => obj.language.toString())
language: string;
language: string | null;
@Exclude()
entities?: never;
@@ -66,7 +66,7 @@ export class NlpSample extends NlpSampleStub {
@Schema({ timestamps: true })
export class NlpSampleFull extends NlpSampleStub {
@Type(() => Language)
language: Language;
language: Language | null;
@Type(() => NlpSampleEntity)
entities: NlpSampleEntity[];

View File

@@ -8,6 +8,7 @@
*/
import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import {
CommonExample,
@@ -16,6 +17,7 @@ import {
ExampleEntity,
LookupTable,
} from '@/extensions/helpers/nlp/default/types';
import { Language } from '@/i18n/schemas/language.schema';
import { LanguageService } from '@/i18n/services/language.service';
import { BaseService } from '@/utils/generics/base-service';
@@ -140,4 +142,21 @@ export class NlpSampleService extends BaseService<
entity_synonyms,
};
}
/**
* When a language gets deleted, we need to set related samples to null
*
* @param language The language that has been deleted.
*/
@OnEvent('hook:language:delete')
async handleLanguageDelete(language: Language) {
await this.updateMany(
{
language: language.id,
},
{
language: null,
},
);
}
}