wip
This commit is contained in:
parent
59b8ca7e4e
commit
09b1773e2f
|
@ -8,6 +8,7 @@ import * as Redis from 'ioredis';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import type { NotesRepository } from '@/models/_.js';
|
||||||
|
|
||||||
const REDIS_PREFIX = 'reactionsBuffer';
|
const REDIS_PREFIX = 'reactionsBuffer';
|
||||||
|
|
||||||
|
@ -16,6 +17,9 @@ export class ReactionsBufferingService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.redis)
|
@Inject(DI.redis)
|
||||||
private redisClient: Redis.Redis, // TODO: 専用のRedisインスタンスにする
|
private redisClient: Redis.Redis, // TODO: 専用のRedisインスタンスにする
|
||||||
|
|
||||||
|
@Inject(DI.notesRepository)
|
||||||
|
private notesRepository: NotesRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +34,8 @@ export class ReactionsBufferingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async get(note: MiNote) {
|
public async get(noteId: MiNote['id']) {
|
||||||
const result = await this.redisClient.hgetall(`${REDIS_PREFIX}:${note.id}`);
|
const result = await this.redisClient.hgetall(`${REDIS_PREFIX}:${noteId}`);
|
||||||
const delta = {};
|
const delta = {};
|
||||||
for (const [name, count] of Object.entries(result)) {
|
for (const [name, count] of Object.entries(result)) {
|
||||||
delta[name] = parseInt(count);
|
delta[name] = parseInt(count);
|
||||||
|
@ -40,23 +44,23 @@ export class ReactionsBufferingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async getMany(notes: MiNote[]) {
|
public async getMany(noteIds: MiNote['id'][]) {
|
||||||
const deltas = new Map<MiNote['id'], Record<string, number>>();
|
const deltas = new Map<MiNote['id'], Record<string, number>>();
|
||||||
|
|
||||||
const pipeline = this.redisClient.pipeline();
|
const pipeline = this.redisClient.pipeline();
|
||||||
for (const note of notes) {
|
for (const noteId of noteIds) {
|
||||||
pipeline.hgetall(`${REDIS_PREFIX}:${note.id}`);
|
pipeline.hgetall(`${REDIS_PREFIX}:${noteId}`);
|
||||||
}
|
}
|
||||||
const results = await pipeline.exec();
|
const results = await pipeline.exec();
|
||||||
|
|
||||||
for (let i = 0; i < notes.length; i++) {
|
for (let i = 0; i < noteIds.length; i++) {
|
||||||
const note = notes[i];
|
const noteId = noteIds[i];
|
||||||
const result = results![i][1];
|
const result = results![i][1];
|
||||||
const delta = {};
|
const delta = {};
|
||||||
for (const [name, count] of Object.entries(result)) {
|
for (const [name, count] of Object.entries(result)) {
|
||||||
delta[name] = parseInt(count);
|
delta[name] = parseInt(count);
|
||||||
}
|
}
|
||||||
deltas.set(note.id, delta);
|
deltas.set(noteId, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
return deltas;
|
return deltas;
|
||||||
|
@ -74,5 +78,30 @@ export class ReactionsBufferingService {
|
||||||
} while (cursor !== '0');
|
} while (cursor !== '0');
|
||||||
|
|
||||||
console.log(bufferedNoteIds);
|
console.log(bufferedNoteIds);
|
||||||
|
|
||||||
|
const deltas = await this.getMany(bufferedNoteIds);
|
||||||
|
|
||||||
|
console.log(deltas);
|
||||||
|
|
||||||
|
// clear
|
||||||
|
const pipeline = this.redisClient.pipeline();
|
||||||
|
for (const noteId of bufferedNoteIds) {
|
||||||
|
pipeline.del(`${REDIS_PREFIX}:${noteId}`);
|
||||||
|
}
|
||||||
|
await pipeline.exec();
|
||||||
|
|
||||||
|
// TODO: SQL一個にまとめたい
|
||||||
|
for (const [noteId, delta] of deltas) {
|
||||||
|
const sqls = [] as string[];
|
||||||
|
for (const [reaction, count] of Object.entries(delta)) {
|
||||||
|
sqls.push(`jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + ${count})::text::jsonb)`);
|
||||||
|
}
|
||||||
|
this.notesRepository.createQueryBuilder().update()
|
||||||
|
.set({
|
||||||
|
reactions: () => sqls.join(' || '),
|
||||||
|
})
|
||||||
|
.where('id = :id', { id: noteId })
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,11 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
import { ModuleRef } from '@nestjs/core';
|
import { ModuleRef } from '@nestjs/core';
|
||||||
import * as Redis from 'ioredis';
|
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { Packed } from '@/misc/json-schema.js';
|
import type { Packed } from '@/misc/json-schema.js';
|
||||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { MiNote } from '@/models/Note.js';
|
import type { MiNote } from '@/models/Note.js';
|
||||||
import type { MiNoteReaction } from '@/models/NoteReaction.js';
|
|
||||||
import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/_.js';
|
import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/_.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { DebounceLoader } from '@/misc/loader.js';
|
import { DebounceLoader } from '@/misc/loader.js';
|
||||||
|
@ -49,9 +47,6 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
constructor(
|
constructor(
|
||||||
private moduleRef: ModuleRef,
|
private moduleRef: ModuleRef,
|
||||||
|
|
||||||
@Inject(DI.redis)
|
|
||||||
private redisClient: Redis.Redis, // TODO: 専用のRedisインスタンスにする
|
|
||||||
|
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
|
@ -423,7 +418,7 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
if (notes.length === 0) return [];
|
if (notes.length === 0) return [];
|
||||||
|
|
||||||
const rbt = true;
|
const rbt = true;
|
||||||
const reactionsDeltas = rbt ? await this.reactionsBufferingService.getMany(notes) : new Map();
|
const reactionsDeltas = rbt ? await this.reactionsBufferingService.getMany(notes.map(x => x.id)) : new Map();
|
||||||
|
|
||||||
const meId = me ? me.id : null;
|
const meId = me ? me.id : null;
|
||||||
const myReactionsMap = new Map<MiNote['id'], string | null>();
|
const myReactionsMap = new Map<MiNote['id'], string | null>();
|
||||||
|
|
Loading…
Reference in New Issue