fix(backend): Remove Meilisearch index when notes are deleted (#10988)

* fix(backend): Include feature to delete Meilisearch index notes

* Update variable name
`cascadingNotesFilter` -> `federatedLocalCascadingNotes`

* tweak

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
Caipira 2023-07-08 21:31:38 +09:00 committed by GitHub
parent 7ec07d5fd2
commit 60366a4558
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 3 deletions

View File

@ -17,6 +17,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { SearchService } from '@/core/SearchService.js';
@Injectable() @Injectable()
export class NoteDeleteService { export class NoteDeleteService {
@ -41,6 +42,7 @@ export class NoteDeleteService {
private apRendererService: ApRendererService, private apRendererService: ApRendererService,
private apDeliverManagerService: ApDeliverManagerService, private apDeliverManagerService: ApDeliverManagerService,
private metaService: MetaService, private metaService: MetaService,
private searchService: SearchService,
private notesChart: NotesChart, private notesChart: NotesChart,
private perUserNotesChart: PerUserNotesChart, private perUserNotesChart: PerUserNotesChart,
private instanceChart: InstanceChart, private instanceChart: InstanceChart,
@ -53,6 +55,7 @@ export class NoteDeleteService {
*/ */
async delete(user: { id: User['id']; uri: User['uri']; host: User['host']; isBot: User['isBot']; }, note: Note, quiet = false) { async delete(user: { id: User['id']; uri: User['uri']; host: User['host']; isBot: User['isBot']; }, note: Note, quiet = false) {
const deletedAt = new Date(); const deletedAt = new Date();
const cascadingNotes = await this.findCascadingNotes(note);
// この投稿を除く指定したユーザーによる指定したノートのリノートが存在しないとき // この投稿を除く指定したユーザーによる指定したノートのリノートが存在しないとき
if (note.renoteId && (await this.noteEntityService.countSameRenotes(user.id, note.renoteId, note.id)) === 0) { if (note.renoteId && (await this.noteEntityService.countSameRenotes(user.id, note.renoteId, note.id)) === 0) {
@ -88,8 +91,8 @@ export class NoteDeleteService {
} }
// also deliever delete activity to cascaded notes // also deliever delete activity to cascaded notes
const cascadingNotes = (await this.findCascadingNotes(note)).filter(note => !note.localOnly); // filter out local-only notes const federatedLocalCascadingNotes = (cascadingNotes).filter(note => !note.localOnly && note.userHost == null); // filter out local-only notes
for (const cascadingNote of cascadingNotes) { for (const cascadingNote of federatedLocalCascadingNotes) {
if (!cascadingNote.user) continue; if (!cascadingNote.user) continue;
if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue; if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue;
const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user)); const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user));
@ -114,6 +117,11 @@ export class NoteDeleteService {
} }
} }
for (const cascadingNote of cascadingNotes) {
this.searchService.unindexNote(cascadingNote);
}
this.searchService.unindexNote(note);
await this.notesRepository.delete({ await this.notesRepository.delete({
id: note.id, id: note.id,
userId: user.id, userId: user.id,
@ -140,7 +148,7 @@ export class NoteDeleteService {
const cascadingNotes: Note[] = await recursive(note.id); const cascadingNotes: Note[] = await recursive(note.id);
return cascadingNotes.filter(note => note.userHost === null); // filter out non-local users return cascadingNotes;
} }
@bindThis @bindThis

View File

@ -115,6 +115,15 @@ export class SearchService {
} }
} }
@bindThis
public async unindexNote(note: Note): Promise<void> {
if (!['home', 'public'].includes(note.visibility)) return;
if (this.meilisearch) {
this.meilisearchNoteIndex!.deleteDocument(note.id);
}
}
@bindThis @bindThis
public async searchNote(q: string, me: User | null, opts: { public async searchNote(q: string, me: User | null, opts: {
userId?: Note['userId'] | null; userId?: Note['userId'] | null;

View File

@ -12,6 +12,7 @@ import { bindThis } from '@/decorators.js';
import { QueueLoggerService } from '../QueueLoggerService.js'; import { QueueLoggerService } from '../QueueLoggerService.js';
import type * as Bull from 'bullmq'; import type * as Bull from 'bullmq';
import type { DbUserDeleteJobData } from '../types.js'; import type { DbUserDeleteJobData } from '../types.js';
import { SearchService } from "@/core/SearchService.js";
@Injectable() @Injectable()
export class DeleteAccountProcessorService { export class DeleteAccountProcessorService {
@ -36,6 +37,7 @@ export class DeleteAccountProcessorService {
private driveService: DriveService, private driveService: DriveService,
private emailService: EmailService, private emailService: EmailService,
private queueLoggerService: QueueLoggerService, private queueLoggerService: QueueLoggerService,
private searchService: SearchService,
) { ) {
this.logger = this.queueLoggerService.logger.createSubLogger('delete-account'); this.logger = this.queueLoggerService.logger.createSubLogger('delete-account');
} }
@ -71,6 +73,10 @@ export class DeleteAccountProcessorService {
cursor = notes[notes.length - 1].id; cursor = notes[notes.length - 1].id;
await this.notesRepository.delete(notes.map(note => note.id)); await this.notesRepository.delete(notes.map(note => note.id));
for (const note of notes) {
await this.searchService.unindexNote(note);
}
} }
this.logger.succ('All of notes deleted'); this.logger.succ('All of notes deleted');