From ec229dbd3b50fdb644dd9e6903e0544be21e55f1 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Tue, 8 Aug 2023 06:26:03 +0200 Subject: [PATCH] fix(backend/ApNoteService): try retrieving again when failed by duplication (#11472) * fix(backend/ApNoteService): try retrieving again when failed by duplication * Update CHANGELOG.md --------- Co-authored-by: syuilo --- CHANGELOG.md | 1 + .../core/activitypub/models/ApNoteService.ts | 52 ++++++++++++------- packages/backend/test/unit/activitypub.ts | 15 ++++++ 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2620db00..a5c74258d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ ### Server - cacheRemoteFilesの初期値はfalseになりました +- 一部のfeatured noteを照会できない問題を修正 - ファイルアップロード時等にファイル名の拡張子を修正する関数(correctFilename)の挙動を改善 - fix: muteがapiからのuser list timeline取得で機能しない問題を修正 diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index e107b9fe5..41d1bc48a 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -131,13 +131,13 @@ export class ApNoteService { this.logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`); if (note.id && !checkHttps(note.id)) { - throw new Error('unexpected shcema of note.id: ' + note.id); + throw new Error('unexpected schema of note.id: ' + note.id); } const url = getOneApHrefNullable(note.url); if (url && !checkHttps(url)) { - throw new Error('unexpected shcema of note url: ' + url); + throw new Error('unexpected schema of note url: ' + url); } this.logger.info(`Creating the Note: ${note.id}`); @@ -271,24 +271,36 @@ export class ApNoteService { const poll = await this.apQuestionService.extractPollFromQuestion(note, resolver).catch(() => undefined); - return await this.noteCreateService.create(actor, { - createdAt: note.published ? new Date(note.published) : null, - files, - reply, - renote: quote, - name: note.name, - cw, - text, - localOnly: false, - visibility, - visibleUsers, - apMentions, - apHashtags, - apEmojis, - poll, - uri: note.id, - url: url, - }, silent); + try { + return await this.noteCreateService.create(actor, { + createdAt: note.published ? new Date(note.published) : null, + files, + reply, + renote: quote, + name: note.name, + cw, + text, + localOnly: false, + visibility, + visibleUsers, + apMentions, + apHashtags, + apEmojis, + poll, + uri: note.id, + url: url, + }, silent); + } catch (err: any) { + if (err.name !== 'duplicated') { + throw err; + } + this.logger.info('The note is already inserted while creating itself, reading again'); + const duplicate = await this.fetchNote(value); + if (!duplicate) { + throw new Error('The note creation failed with duplication error even when there is no duplication'); + } + return duplicate; + } } /** diff --git a/packages/backend/test/unit/activitypub.ts b/packages/backend/test/unit/activitypub.ts index 378f02e8e..73209523b 100644 --- a/packages/backend/test/unit/activitypub.ts +++ b/packages/backend/test/unit/activitypub.ts @@ -259,6 +259,21 @@ describe('ActivityPub', () => { assert.strictEqual(note.text, 'test test foo'); assert.strictEqual(note.uri, actor2Note.id); }); + + test('Fetch a note that is a featured note of the attributed actor', async () => { + const actor = createRandomActor(); + actor.featured = `${actor.id}/collections/featured`; + + const featured = createRandomFeaturedCollection(actor, 5); + const firstNote = (featured.items as NonTransientIPost[])[0]; + + resolver.register(actor.id, actor); + resolver.register(actor.featured, featured); + resolver.register(firstNote.id, firstNote); + + const note = await noteService.createNote(firstNote.id as string, resolver); + assert.strictEqual(note?.uri, firstNote.id); + }); }); describe('Images', () => {