wip
This commit is contained in:
parent
631715c86e
commit
417969604e
|
@ -595,7 +595,7 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async ogogogo(noteIds: MiNote['id'][]) {
|
public async fetchDiffs(noteIds: MiNote['id'][]) {
|
||||||
if (noteIds.length === 0) return [];
|
if (noteIds.length === 0) return [];
|
||||||
|
|
||||||
const notes = await this.notesRepository.find({
|
const notes = await this.notesRepository.find({
|
||||||
|
@ -603,25 +603,32 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
id: In(noteIds),
|
id: In(noteIds),
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
|
id: true,
|
||||||
|
userHost: true,
|
||||||
reactions: true,
|
reactions: true,
|
||||||
reactionAndUserPairCache: true,
|
reactionAndUserPairCache: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(notes);
|
|
||||||
|
|
||||||
const bufferedReactionsMap = this.meta.enableReactionsBuffering ? await this.reactionsBufferingService.getMany(noteIds) : null;
|
const bufferedReactionsMap = this.meta.enableReactionsBuffering ? await this.reactionsBufferingService.getMany(noteIds) : null;
|
||||||
|
|
||||||
const results = [];
|
const packings = notes.map(note => {
|
||||||
|
|
||||||
for (const note of notes) {
|
|
||||||
const bufferedReactions = bufferedReactionsMap?.get(note.id);
|
const bufferedReactions = bufferedReactionsMap?.get(note.id);
|
||||||
const reactionAndUserPairCache = note.reactionAndUserPairCache.concat(bufferedReactions.pairs.map(x => x.join('/')));
|
//const reactionAndUserPairCache = note.reactionAndUserPairCache.concat(bufferedReactions.pairs.map(x => x.join('/')));
|
||||||
|
|
||||||
results.push({
|
const reactions = this.reactionService.convertLegacyReactions(this.reactionsBufferingService.mergeReactions(note.reactions, bufferedReactions?.deltas ?? {}));
|
||||||
|
|
||||||
|
const reactionEmojiNames = Object.keys(reactions)
|
||||||
|
.filter(x => x.startsWith(':') && x.includes('@') && !x.includes('@.')) // リモートカスタム絵文字のみ
|
||||||
|
.map(x => this.reactionService.decodeReaction(x).reaction.replaceAll(':', ''));
|
||||||
|
|
||||||
|
return this.customEmojiService.populateEmojis(reactionEmojiNames, note.userHost).then(reactionEmojis => ({
|
||||||
id: note.id,
|
id: note.id,
|
||||||
reactions: this.reactionService.convertLegacyReactions(this.reactionsBufferingService.mergeReactions(note.reactions, bufferedReactions.deltas ?? {})),
|
reactions,
|
||||||
|
reactionEmojis,
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
return await Promise.all(packings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,6 +317,7 @@ export * as 'notes/replies' from './endpoints/notes/replies.js';
|
||||||
export * as 'notes/search' from './endpoints/notes/search.js';
|
export * as 'notes/search' from './endpoints/notes/search.js';
|
||||||
export * as 'notes/search-by-tag' from './endpoints/notes/search-by-tag.js';
|
export * as 'notes/search-by-tag' from './endpoints/notes/search-by-tag.js';
|
||||||
export * as 'notes/show' from './endpoints/notes/show.js';
|
export * as 'notes/show' from './endpoints/notes/show.js';
|
||||||
|
export * as 'notes/show-partial-bulk' from './endpoints/notes/show-partial-bulk.js';
|
||||||
export * as 'notes/state' from './endpoints/notes/state.js';
|
export * as 'notes/state' from './endpoints/notes/state.js';
|
||||||
export * as 'notes/thread-muting/create' from './endpoints/notes/thread-muting/create.js';
|
export * as 'notes/thread-muting/create' from './endpoints/notes/thread-muting/create.js';
|
||||||
export * as 'notes/thread-muting/delete' from './endpoints/notes/thread-muting/delete.js';
|
export * as 'notes/thread-muting/delete' from './endpoints/notes/thread-muting/delete.js';
|
||||||
|
|
|
@ -38,9 +38,10 @@ export const paramDef = {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||||
constructor(
|
constructor(
|
||||||
|
private noteEntityService: NoteEntityService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
return await this.noteEntityService.fetchDiffs(ps.noteIds);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import type { Ref, ShallowRef } from 'vue';
|
||||||
import { useStream } from '@/stream.js';
|
import { useStream } from '@/stream.js';
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
import { store } from '@/store.js';
|
import { store } from '@/store.js';
|
||||||
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
|
|
||||||
const noteEvents = new EventEmitter<{
|
const noteEvents = new EventEmitter<{
|
||||||
reacted: Misskey.entities.Note;
|
reacted: Misskey.entities.Note;
|
||||||
|
@ -18,16 +19,31 @@ const noteEvents = new EventEmitter<{
|
||||||
deleted: Misskey.entities.Note;
|
deleted: Misskey.entities.Note;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const fetchEvent = new EventEmitter<{
|
||||||
|
[id: string]: Pick<Misskey.entities.Note, 'reactions' | 'reactionEmojis'>;
|
||||||
|
}>();
|
||||||
|
|
||||||
const capturedNoteIdMapForPolling = new Map<string, number>();
|
const capturedNoteIdMapForPolling = new Map<string, number>();
|
||||||
|
|
||||||
|
const CAPTURE_MAX = 30;
|
||||||
const POLLING_INTERVAL = 1000 * 10;
|
const POLLING_INTERVAL = 1000 * 10;
|
||||||
|
|
||||||
window.setInterval(() => {
|
window.setInterval(() => {
|
||||||
const ids = [...capturedNoteIdMapForPolling.keys()];
|
const ids = [...capturedNoteIdMapForPolling.keys()].sort((a, b) => (a > b ? -1 : 1)).slice(0, CAPTURE_MAX); // 新しいものを優先するためにIDで降順ソート
|
||||||
if (ids.length === 0) return;
|
if (ids.length === 0) return;
|
||||||
if (window.document.hidden) return;
|
if (window.document.hidden) return;
|
||||||
|
|
||||||
console.log('Polling notes', ids);
|
// まとめてリクエストするのではなく、個別にHTTPリクエスト投げてCDNにキャッシュさせた方がサーバーの負荷低減には良いかもしれない
|
||||||
|
misskeyApi('notes/show-partial-bulk', {
|
||||||
|
noteIds: ids,
|
||||||
|
}).then((items) => {
|
||||||
|
for (const item of items) {
|
||||||
|
fetchEvent.emit(item.id, {
|
||||||
|
reactions: item.reactions,
|
||||||
|
reactionEmojis: item.reactionEmojis,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}, POLLING_INTERVAL);
|
}, POLLING_INTERVAL);
|
||||||
|
|
||||||
function pseudoNoteCapture(props: {
|
function pseudoNoteCapture(props: {
|
||||||
|
@ -43,17 +59,27 @@ function pseudoNoteCapture(props: {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onFetched(data: Pick<Misskey.entities.Note, 'reactions' | 'reactionEmojis'>): void {
|
||||||
|
note.value.reactions = data.reactions;
|
||||||
|
note.value.reactionCount = Object.values(data.reactions).reduce((a, b) => a + b, 0);
|
||||||
|
note.value.reactionEmojis = data.reactionEmojis;
|
||||||
|
}
|
||||||
|
|
||||||
if (capturedNoteIdMapForPolling.has(note.value.id)) {
|
if (capturedNoteIdMapForPolling.has(note.value.id)) {
|
||||||
capturedNoteIdMapForPolling.set(note.value.id, capturedNoteIdMapForPolling.get(note.value.id)! + 1);
|
capturedNoteIdMapForPolling.set(note.value.id, capturedNoteIdMapForPolling.get(note.value.id)! + 1);
|
||||||
} else {
|
} else {
|
||||||
capturedNoteIdMapForPolling.set(note.value.id, 1);
|
capturedNoteIdMapForPolling.set(note.value.id, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchEvent.on(note.value.id, onFetched);
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
capturedNoteIdMapForPolling.set(note.value.id, capturedNoteIdMapForPolling.get(note.value.id)! - 1);
|
capturedNoteIdMapForPolling.set(note.value.id, capturedNoteIdMapForPolling.get(note.value.id)! - 1);
|
||||||
if (capturedNoteIdMapForPolling.get(note.value.id) === 0) {
|
if (capturedNoteIdMapForPolling.get(note.value.id) === 0) {
|
||||||
capturedNoteIdMapForPolling.delete(note.value.id);
|
capturedNoteIdMapForPolling.delete(note.value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchEvent.off(note.value.id, onFetched);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue