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:
parent
7ec07d5fd2
commit
60366a4558
3 changed files with 26 additions and 3 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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');
|
||||||
|
|
Loading…
Reference in a new issue