summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorzyoshoka <107108195+zyoshoka@users.noreply.github.com>2024-06-22 12:43:03 +0900
committerGitHub <noreply@github.com>2024-06-22 12:43:03 +0900
commit8a9de081f1efd78117c30bdc721785ca323b202c (patch)
tree2cc7aeafff6dea52c3314453ecf9e238ade5a84a /packages
parentReplace with `vue/no-setup-props-reactivity-loss` rule (#14062) (diff)
downloadsharkey-8a9de081f1efd78117c30bdc721785ca323b202c.tar.gz
sharkey-8a9de081f1efd78117c30bdc721785ca323b202c.tar.bz2
sharkey-8a9de081f1efd78117c30bdc721785ca323b202c.zip
fix(backend): fallback if `sinceId` is older than the oldest in cache when using FTT (#14061)
* fix(backend): fallback if `sinceId` is older than the oldest in cache when using FTT * Update CHANGELOG.md * chore: fix description of test
Diffstat (limited to 'packages')
-rw-r--r--packages/backend/src/core/FanoutTimelineEndpointService.ts12
-rw-r--r--packages/backend/test/e2e/timelines.ts35
2 files changed, 39 insertions, 8 deletions
diff --git a/packages/backend/src/core/FanoutTimelineEndpointService.ts b/packages/backend/src/core/FanoutTimelineEndpointService.ts
index d5058f37c2..b05af99c5e 100644
--- a/packages/backend/src/core/FanoutTimelineEndpointService.ts
+++ b/packages/backend/src/core/FanoutTimelineEndpointService.ts
@@ -55,9 +55,6 @@ export class FanoutTimelineEndpointService {
@bindThis
private async getMiNotes(ps: TimelineOptions): Promise<MiNote[]> {
- let noteIds: string[];
- let shouldFallbackToDb = false;
-
// 呼び出し元と以下の処理をシンプルにするためにdbFallbackを置き換える
if (!ps.useDbFallback) ps.dbFallback = () => Promise.resolve([]);
@@ -67,12 +64,11 @@ export class FanoutTimelineEndpointService {
const redisResult = await this.fanoutTimelineService.getMulti(ps.redisTimelines, ps.untilId, ps.sinceId);
// TODO: いい感じにgetMulti内でソート済だからuniqするときにredisResultが全てソート済なのを利用して再ソートを避けたい
- const redisResultIds = Array.from(new Set(redisResult.flat(1)));
-
- redisResultIds.sort(idCompare);
- noteIds = redisResultIds.slice(0, ps.limit);
+ const redisResultIds = Array.from(new Set(redisResult.flat(1))).sort(idCompare);
- shouldFallbackToDb = shouldFallbackToDb || (noteIds.length === 0);
+ let noteIds = redisResultIds.slice(0, ps.limit);
+ const oldestNoteId = ascending ? redisResultIds[0] : redisResultIds[redisResultIds.length - 1];
+ const shouldFallbackToDb = noteIds.length === 0 || ps.sinceId != null && ps.sinceId < oldestNoteId;
if (!shouldFallbackToDb) {
let filter = ps.noteFilter ?? (_note => true);
diff --git a/packages/backend/test/e2e/timelines.ts b/packages/backend/test/e2e/timelines.ts
index 5487292afc..f6cc2bac28 100644
--- a/packages/backend/test/e2e/timelines.ts
+++ b/packages/backend/test/e2e/timelines.ts
@@ -7,6 +7,8 @@
// pnpm jest -- e2e/timelines.ts
import * as assert from 'assert';
+import { Redis } from 'ioredis';
+import { loadConfig } from '@/config.js';
import { api, post, randomString, sendEnvUpdateRequest, signup, sleep, uploadUrl } from '../utils.js';
function genHost() {
@@ -17,7 +19,13 @@ function waitForPushToTl() {
return sleep(500);
}
+let redisForTimelines: Redis;
+
describe('Timelines', () => {
+ beforeAll(() => {
+ redisForTimelines = new Redis(loadConfig().redisForTimelines);
+ });
+
describe('Home TL', () => {
test.concurrent('自分の visibility: followers なノートが含まれる', async () => {
const [alice] = await Promise.all([signup()]);
@@ -1272,6 +1280,33 @@ describe('Timelines', () => {
assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false);
});
+
+ /** @see https://github.com/misskey-dev/misskey/issues/14000 */
+ test.concurrent('FTT: sinceId にキャッシュより古いノートを指定しても、sinceId による絞り込みが正しく動作する', async () => {
+ const alice = await signup();
+ const noteSince = await post(alice, { text: 'Note where id will be `sinceId`.' });
+ const note1 = await post(alice, { text: '1' });
+ const note2 = await post(alice, { text: '2' });
+ await redisForTimelines.del('list:userTimeline:' + alice.id);
+ const note3 = await post(alice, { text: '3' });
+
+ const res = await api('users/notes', { userId: alice.id, sinceId: noteSince.id });
+ assert.deepStrictEqual(res.body, [note1, note2, note3]);
+ });
+
+ test.concurrent('FTT: sinceId にキャッシュより古いノートを指定しても、sinceId と untilId による絞り込みが正しく動作する', async () => {
+ const alice = await signup();
+ const noteSince = await post(alice, { text: 'Note where id will be `sinceId`.' });
+ const note1 = await post(alice, { text: '1' });
+ const note2 = await post(alice, { text: '2' });
+ await redisForTimelines.del('list:userTimeline:' + alice.id);
+ const note3 = await post(alice, { text: '3' });
+ const noteUntil = await post(alice, { text: 'Note where id will be `untilId`.' });
+ await post(alice, { text: '4' });
+
+ const res = await api('users/notes', { userId: alice.id, sinceId: noteSince.id, untilId: noteUntil.id });
+ assert.deepStrictEqual(res.body, [note3, note2, note1]);
+ });
});
// TODO: リノートミュート済みユーザーのテスト