summaryrefslogtreecommitdiff
path: root/packages/backend
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-04-09 10:29:36 +0900
committerGitHub <noreply@github.com>2023-04-09 10:29:36 +0900
commit8b1362ab03c273f44cbbbb3c9f900301d82aeabd (patch)
tree61fda1a1b44776e8d3a4a17511f2d510b6d9791b /packages/backend
parentMerge pull request #10506 from misskey-dev/develop (diff)
parentfix(backend): 連合しているインスタンスについて予期せず配... (diff)
downloadmisskey-8b1362ab03c273f44cbbbb3c9f900301d82aeabd.tar.gz
misskey-8b1362ab03c273f44cbbbb3c9f900301d82aeabd.tar.bz2
misskey-8b1362ab03c273f44cbbbb3c9f900301d82aeabd.zip
Merge pull request #10543 from misskey-dev/develop
Release: 13.11.1
Diffstat (limited to '')
-rw-r--r--packages/backend/src/core/CustomEmojiService.ts6
-rw-r--r--packages/backend/src/core/FederatedInstanceService.ts1
-rw-r--r--packages/backend/src/core/IdService.ts14
-rw-r--r--packages/backend/src/core/activitypub/ApDeliverManagerService.ts2
-rw-r--r--packages/backend/src/misc/cache.ts4
-rw-r--r--packages/backend/src/misc/id/aid.ts2
-rw-r--r--packages/backend/src/misc/id/meid.ts9
-rw-r--r--packages/backend/src/misc/id/meidg.ts7
-rw-r--r--packages/backend/src/misc/id/object-id.ts9
-rw-r--r--packages/backend/src/misc/id/ulid.ts14
-rw-r--r--packages/backend/src/server/api/endpoints/channels/timeline.ts18
-rw-r--r--packages/backend/test/unit/misc/id.ts44
12 files changed, 113 insertions, 17 deletions
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index 604a94707f..dc365986fe 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -44,7 +44,11 @@ export class CustomEmojiService {
memoryCacheLifetime: 1000 * 60 * 3, // 3m
fetcher: () => this.emojisRepository.find({ where: { host: IsNull() } }).then(emojis => new Map(emojis.map(emoji => [emoji.name, emoji]))),
toRedisConverter: (value) => JSON.stringify(value.values()),
- fromRedisConverter: (value) => new Map(JSON.parse(value).map((x: Emoji) => [x.name, x])), // TODO: Date型の変換
+ fromRedisConverter: (value) => {
+ // 原因不明だが配列以外が入ってくることがあるため
+ if (!Array.isArray(JSON.parse(value))) return undefined;
+ return new Map(JSON.parse(value).map((x: Emoji) => [x.name, x]));
+ }, // TODO: Date型の変換
});
}
diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts
index 1d0c87280f..56660ae0d0 100644
--- a/packages/backend/src/core/FederatedInstanceService.ts
+++ b/packages/backend/src/core/FederatedInstanceService.ts
@@ -29,6 +29,7 @@ export class FederatedInstanceService {
toRedisConverter: (value) => JSON.stringify(value),
fromRedisConverter: (value) => {
const parsed = JSON.parse(value);
+ if (parsed == null) return null;
return {
...parsed,
firstRetrievedAt: new Date(parsed.firstRetrievedAt),
diff --git a/packages/backend/src/core/IdService.ts b/packages/backend/src/core/IdService.ts
index 94084ad84f..8aa6ccfc4e 100644
--- a/packages/backend/src/core/IdService.ts
+++ b/packages/backend/src/core/IdService.ts
@@ -3,10 +3,11 @@ import { ulid } from 'ulid';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { genAid, parseAid } from '@/misc/id/aid.js';
-import { genMeid } from '@/misc/id/meid.js';
-import { genMeidg } from '@/misc/id/meidg.js';
+import { genMeid, parseMeid } from '@/misc/id/meid.js';
+import { genMeidg, parseMeidg } from '@/misc/id/meidg.js';
import { genObjectId } from '@/misc/id/object-id.js';
import { bindThis } from '@/decorators.js';
+import { parseUlid } from '@/misc/id/ulid.js';
@Injectable()
export class IdService {
@@ -37,11 +38,10 @@ export class IdService {
public parse(id: string): { date: Date; } {
switch (this.method) {
case 'aid': return parseAid(id);
- // TODO
- //case 'meid':
- //case 'meidg':
- //case 'ulid':
- //case 'objectid':
+ case 'objectid':
+ case 'meid': return parseMeid(id);
+ case 'meidg': return parseMeidg(id);
+ case 'ulid': return parseUlid(id);
default: throw new Error('unrecognized id generation method');
}
}
diff --git a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
index 70a6d32fe2..62a2a33a19 100644
--- a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
+++ b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
@@ -186,7 +186,7 @@ class DeliverManager {
for (const following of followers) {
const inbox = following.followerSharedInbox ?? following.followerInbox;
- inboxes.set(inbox, following.followerSharedInbox === null);
+ inboxes.set(inbox, following.followerSharedInbox != null);
}
}
diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts
index d35414acf7..a4abd4f878 100644
--- a/packages/backend/src/misc/cache.ts
+++ b/packages/backend/src/misc/cache.ts
@@ -8,7 +8,7 @@ export class RedisKVCache<T> {
private memoryCache: MemoryKVCache<T>;
private fetcher: (key: string) => Promise<T>;
private toRedisConverter: (value: T) => string;
- private fromRedisConverter: (value: string) => T;
+ private fromRedisConverter: (value: string) => T | undefined; // undefined means no cache
constructor(redisClient: RedisKVCache<T>['redisClient'], name: RedisKVCache<T>['name'], opts: {
lifetime: RedisKVCache<T>['lifetime'];
@@ -92,7 +92,7 @@ export class RedisSingleCache<T> {
private memoryCache: MemorySingleCache<T>;
private fetcher: () => Promise<T>;
private toRedisConverter: (value: T) => string;
- private fromRedisConverter: (value: string) => T;
+ private fromRedisConverter: (value: string) => T | undefined; // undefined means no cache
constructor(redisClient: RedisSingleCache<T>['redisClient'], name: RedisSingleCache<T>['name'], opts: {
lifetime: RedisSingleCache<T>['lifetime'];
diff --git a/packages/backend/src/misc/id/aid.ts b/packages/backend/src/misc/id/aid.ts
index 93a9929aa7..9e206ee98f 100644
--- a/packages/backend/src/misc/id/aid.ts
+++ b/packages/backend/src/misc/id/aid.ts
@@ -3,6 +3,8 @@
import * as crypto from 'node:crypto';
+export const aidRegExp = /^[0-9a-z]{10}$/;
+
const TIME2000 = 946684800000;
let counter = crypto.randomBytes(2).readUInt16LE(0);
diff --git a/packages/backend/src/misc/id/meid.ts b/packages/backend/src/misc/id/meid.ts
index 30bbdf1698..337416b059 100644
--- a/packages/backend/src/misc/id/meid.ts
+++ b/packages/backend/src/misc/id/meid.ts
@@ -1,5 +1,8 @@
const CHARS = '0123456789abcdef';
+// same as object-id
+export const meidRegExp = /^[0-9a-f]{24}$/;
+
function getTime(time: number) {
if (time < 0) time = 0;
if (time === 0) {
@@ -24,3 +27,9 @@ function getRandom() {
export function genMeid(date: Date): string {
return getTime(date.getTime()) + getRandom();
}
+
+export function parseMeid(id: string): { date: Date; } {
+ return {
+ date: new Date(parseInt(id.slice(0, 12), 16) - 0x800000000000),
+ };
+}
diff --git a/packages/backend/src/misc/id/meidg.ts b/packages/backend/src/misc/id/meidg.ts
index d4aaaea1ba..19d0bc1fd2 100644
--- a/packages/backend/src/misc/id/meidg.ts
+++ b/packages/backend/src/misc/id/meidg.ts
@@ -3,6 +3,7 @@ const CHARS = '0123456789abcdef';
// 4bit Fixed hex value 'g'
// 44bit UNIX Time ms in Hex
// 48bit Random value in Hex
+export const meidgRegExp = /^g[0-9a-f]{23}$/;
function getTime(time: number) {
if (time < 0) time = 0;
@@ -26,3 +27,9 @@ function getRandom() {
export function genMeidg(date: Date): string {
return 'g' + getTime(date.getTime()) + getRandom();
}
+
+export function parseMeidg(id: string): { date: Date; } {
+ return {
+ date: new Date(parseInt(id.slice(1, 12), 16)),
+ };
+}
diff --git a/packages/backend/src/misc/id/object-id.ts b/packages/backend/src/misc/id/object-id.ts
index 392ea43301..aec3447bd7 100644
--- a/packages/backend/src/misc/id/object-id.ts
+++ b/packages/backend/src/misc/id/object-id.ts
@@ -1,5 +1,8 @@
const CHARS = '0123456789abcdef';
+// same as meid
+export const objectIdRegExp = /^[0-9a-f]{24}$/;
+
function getTime(time: number) {
if (time < 0) time = 0;
if (time === 0) {
@@ -24,3 +27,9 @@ function getRandom() {
export function genObjectId(date: Date): string {
return getTime(date.getTime()) + getRandom();
}
+
+export function parseObjectId(id: string): { date: Date; } {
+ return {
+ date: new Date(parseInt(id.slice(0, 8), 16) * 1000),
+ };
+}
diff --git a/packages/backend/src/misc/id/ulid.ts b/packages/backend/src/misc/id/ulid.ts
new file mode 100644
index 0000000000..e8aa752890
--- /dev/null
+++ b/packages/backend/src/misc/id/ulid.ts
@@ -0,0 +1,14 @@
+// Crockford's Base32
+// https://github.com/ulid/spec#encoding
+const CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
+
+export const ulidRegExp = /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/;
+
+export function parseUlid(id: string): { date: Date; } {
+ const timestamp = id.slice(0, 10);
+ let time = 0;
+ for (let i = 0; i < 10; i++) {
+ time = time * 32 + CHARS.indexOf(timestamp[i]);
+ }
+ return { date: new Date(time) };
+}
diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts
index 2556557b24..2491d14235 100644
--- a/packages/backend/src/server/api/endpoints/channels/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts
@@ -75,13 +75,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
let timeline: Note[] = [];
- const noteIdsRes = await this.redisClient.xrevrange(
- `channelTimeline:${channel.id}`,
- ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+',
- '-',
- 'COUNT', ps.limit + 1); // untilIdに指定したものも含まれるため+1
+ const limit = ps.limit + (ps.untilId ? 1 : 0); // untilIdに指定したものも含まれるため+1
+ let noteIdsRes: [string, string[]][] = [];
+
+ if (!ps.sinceId && !ps.sinceDate) {
+ noteIdsRes = await this.redisClient.xrevrange(
+ `channelTimeline:${channel.id}`,
+ ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : ps.untilDate ?? '+',
+ '-',
+ 'COUNT', limit);
+ }
- if (noteIdsRes.length === 0) {
+ // redis から取得していないとき・取得数が足りないとき
+ if (noteIdsRes.length < limit) {
//#region Construct query
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.channelId = :channelId', { channelId: channel.id })
diff --git a/packages/backend/test/unit/misc/id.ts b/packages/backend/test/unit/misc/id.ts
new file mode 100644
index 0000000000..ecd0e60a31
--- /dev/null
+++ b/packages/backend/test/unit/misc/id.ts
@@ -0,0 +1,44 @@
+import { aidRegExp, genAid, parseAid } from '@/misc/id/aid.js';
+import { genMeid, meidRegExp, parseMeid } from '@/misc/id/meid.js';
+import { genMeidg, meidgRegExp, parseMeidg } from '@/misc/id/meidg.js';
+import { genObjectId, objectIdRegExp, parseObjectId } from '@/misc/id/object-id.js';
+import { ulidRegExp, parseUlid } from '@/misc/id/ulid.js';
+import { ulid } from 'ulid';
+import { describe, test, expect } from '@jest/globals';
+
+describe('misc:id', () => {
+ test('aid', () => {
+ const date = new Date();
+ const gotAid = genAid(date);
+ expect(gotAid).toMatch(aidRegExp);
+ expect(parseAid(gotAid).date.getTime()).toBe(date.getTime());
+ });
+
+ test('meid', () => {
+ const date = new Date();
+ const gotMeid = genMeid(date);
+ expect(gotMeid).toMatch(meidRegExp);
+ expect(parseMeid(gotMeid).date.getTime()).toBe(date.getTime());
+ });
+
+ test('meidg', () => {
+ const date = new Date();
+ const gotMeidg = genMeidg(date);
+ expect(gotMeidg).toMatch(meidgRegExp);
+ expect(parseMeidg(gotMeidg).date.getTime()).toBe(date.getTime());
+ });
+
+ test('objectid', () => {
+ const date = new Date();
+ const gotObjectId = genObjectId(date);
+ expect(gotObjectId).toMatch(objectIdRegExp);
+ expect(Math.floor(parseObjectId(gotObjectId).date.getTime() / 1000)).toBe(Math.floor(date.getTime() / 1000));
+ });
+
+ test('ulid', () => {
+ const date = new Date();
+ const gotUlid = ulid(date.getTime());
+ expect(gotUlid).toMatch(ulidRegExp);
+ expect(parseUlid(gotUlid).date.getTime()).toBe(date.getTime());
+ });
+});