summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-03-21 15:35:02 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-03-21 15:35:02 +0900
commit630464f38d2524ddc5d11d2abd4fddcccc4240d4 (patch)
tree54d61708d279205f1da4fb81cfd42959f0bbcaf5 /src
parentperf: 各ストリーミング接続ごとにポーリングしないように (diff)
downloadsharkey-630464f38d2524ddc5d11d2abd4fddcccc4240d4.tar.gz
sharkey-630464f38d2524ddc5d11d2abd4fddcccc4240d4.tar.bz2
sharkey-630464f38d2524ddc5d11d2abd4fddcccc4240d4.zip
Revert "perf: Reduce database query"
This reverts commit 87c8f9ff953499340496e9c5db09c93eaff08851.
Diffstat (limited to 'src')
-rw-r--r--src/client/components/note-detailed.vue10
-rw-r--r--src/client/components/note.vue10
-rw-r--r--src/client/ui/chat/note.vue10
-rw-r--r--src/server/api/endpoints/notes/mentions.ts6
-rw-r--r--src/server/api/stream/index.ts38
-rw-r--r--src/services/note/read-mention.ts29
-rw-r--r--src/services/note/read-specified-note.ts29
-rw-r--r--src/services/note/read.ts105
8 files changed, 123 insertions, 114 deletions
diff --git a/src/client/components/note-detailed.vue b/src/client/components/note-detailed.vue
index 4ad3d2d898..1ef3f43389 100644
--- a/src/client/components/note-detailed.vue
+++ b/src/client/components/note-detailed.vue
@@ -350,15 +350,7 @@ export default defineComponent({
capture(withHandler = false) {
if (this.$i) {
- this.connection.send('sn', { id: this.appearNote.id });
- if (this.appearNote.userId !== this.$i.id) {
- if (this.appearNote.mentions && this.appearNote.mentions.includes(this.$i.id)) {
- this.connection.send('readMention', { id: this.appearNote.id });
- }
- if (this.appearNote.visibleUserIds && this.appearNote.visibleUserIds.includes(this.$i.id)) {
- this.connection.send('readSpecifiedNote', { id: this.appearNote.id });
- }
- }
+ this.connection.send(document.body.contains(this.$el) ? 'sn' : 's', { id: this.appearNote.id });
if (withHandler) this.connection.on('noteUpdated', this.onStreamNoteUpdated);
}
},
diff --git a/src/client/components/note.vue b/src/client/components/note.vue
index 3b59afd71d..65e09b7802 100644
--- a/src/client/components/note.vue
+++ b/src/client/components/note.vue
@@ -325,15 +325,7 @@ export default defineComponent({
capture(withHandler = false) {
if (this.$i) {
- this.connection.send('sn', { id: this.appearNote.id });
- if (this.appearNote.userId !== this.$i.id) {
- if (this.appearNote.mentions && this.appearNote.mentions.includes(this.$i.id)) {
- this.connection.send('readMention', { id: this.appearNote.id });
- }
- if (this.appearNote.visibleUserIds && this.appearNote.visibleUserIds.includes(this.$i.id)) {
- this.connection.send('readSpecifiedNote', { id: this.appearNote.id });
- }
- }
+ this.connection.send(document.body.contains(this.$el) ? 'sn' : 's', { id: this.appearNote.id });
if (withHandler) this.connection.on('noteUpdated', this.onStreamNoteUpdated);
}
},
diff --git a/src/client/ui/chat/note.vue b/src/client/ui/chat/note.vue
index 29bc61d9c5..5a4a13d889 100644
--- a/src/client/ui/chat/note.vue
+++ b/src/client/ui/chat/note.vue
@@ -325,15 +325,7 @@ export default defineComponent({
capture(withHandler = false) {
if (this.$i) {
- this.connection.send('sn', { id: this.appearNote.id });
- if (this.appearNote.userId !== this.$i.id) {
- if (this.appearNote.mentions && this.appearNote.mentions.includes(this.$i.id)) {
- this.connection.send('readMention', { id: this.appearNote.id });
- }
- if (this.appearNote.visibleUserIds && this.appearNote.visibleUserIds.includes(this.$i.id)) {
- this.connection.send('readSpecifiedNote', { id: this.appearNote.id });
- }
- }
+ this.connection.send(document.body.contains(this.$el) ? 'sn' : 's', { id: this.appearNote.id });
if (withHandler) this.connection.on('noteUpdated', this.onStreamNoteUpdated);
}
},
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 56640ec1ab..30844774e0 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -1,12 +1,12 @@
import $ from 'cafy';
import { ID } from '../../../../misc/cafy-id';
import define from '../../define';
+import read from '../../../../services/note/read';
import { Notes, Followings } from '../../../../models';
import { generateVisibilityQuery } from '../../common/generate-visibility-query';
import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
import { makePaginationQuery } from '../../common/make-pagination-query';
import { Brackets } from 'typeorm';
-import { readMention } from '../../../../services/note/read-mention';
export const meta = {
desc: {
@@ -83,7 +83,9 @@ export default define(meta, async (ps, user) => {
const mentions = await query.take(ps.limit!).getMany();
- readMention(user.id, mentions.map(n => n.id));
+ for (const note of mentions) {
+ read(user.id, note.id);
+ }
return await Notes.packMany(mentions, user);
});
diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts
index 748e894f83..f67faee1ce 100644
--- a/src/server/api/stream/index.ts
+++ b/src/server/api/stream/index.ts
@@ -2,6 +2,7 @@ import autobind from 'autobind-decorator';
import * as websocket from 'websocket';
import { readNotification } from '../common/read-notification';
import call from '../call';
+import readNote from '../../../services/note/read';
import Channel from './channel';
import channels from './channels';
import { EventEmitter } from 'events';
@@ -13,8 +14,6 @@ import { AccessToken } from '../../../models/entities/access-token';
import { UserProfile } from '../../../models/entities/user-profile';
import { publishChannelStream, publishGroupMessagingStream, publishMessagingStream } from '../../../services/stream';
import { UserGroup } from '../../../models/entities/user-group';
-import { readMention } from '../../../services/note/read-mention';
-import { readSpecifiedNote } from '../../../services/note/read-specified-note';
/**
* Main stream connection
@@ -116,10 +115,9 @@ export default class Connection {
switch (type) {
case 'api': this.onApiRequest(body); break;
case 'readNotification': this.onReadNotification(body); break;
- case 'readMention': this.onReadMention(body); break;
- case 'readSpecifiedNote': this.onReadSpecifiedNote(body); break;
- case 'subNote': this.onSubscribeNote(body); break;
- case 'sn': this.onSubscribeNote(body); break; // alias
+ case 'subNote': this.onSubscribeNote(body, true); break;
+ case 'sn': this.onSubscribeNote(body, true); break; // alias
+ case 's': this.onSubscribeNote(body, false); break;
case 'unsubNote': this.onUnsubscribeNote(body); break;
case 'un': this.onUnsubscribeNote(body); break; // alias
case 'connect': this.onChannelConnectRequested(body); break;
@@ -172,31 +170,11 @@ export default class Connection {
readNotification(this.user!.id, [payload.id]);
}
- @autobind
- private onReadMention(payload: any) {
- if (!payload.id) return;
- if (this.user) {
- // TODO: ある程度まとめてreadMentionするようにする
- // 具体的には、この箇所ではキュー的な配列にread予定ノートを溜めておくに留めて、別の箇所で定期的にキューにあるノートを配列でreadMentionに渡すような実装にする
- readMention(this.user.id, [payload.id]);
- }
- }
-
- @autobind
- private onReadSpecifiedNote(payload: any) {
- if (!payload.id) return;
- if (this.user) {
- // TODO: ある程度まとめてreadSpecifiedNoteするようにする
- // 具体的には、この箇所ではキュー的な配列にread予定ノートを溜めておくに留めて、別の箇所で定期的にキューにあるノートを配列でreadSpecifiedNoteに渡すような実装にする
- readSpecifiedNote(this.user.id, [payload.id]);
- }
- }
-
/**
* 投稿購読要求時
*/
@autobind
- private onSubscribeNote(payload: any) {
+ private onSubscribeNote(payload: any, read: boolean) {
if (!payload.id) return;
if (this.subscribingNotes[payload.id] == null) {
@@ -208,6 +186,12 @@ export default class Connection {
if (this.subscribingNotes[payload.id] === 1) {
this.subscriber.on(`noteStream:${payload.id}`, this.onNoteStreamMessage);
}
+
+ if (this.user && read) {
+ // TODO: クライアントでタイムライン読み込みなどすると、一度に大量のreadNoteが発生しクエリ数がすごいことになるので、ある程度まとめてreadNoteするようにする
+ // 具体的には、この箇所ではキュー的な配列にread予定ノートを溜めておくに留めて、別の箇所で定期的にキューにあるノートを配列でreadNoteに渡すような実装にする
+ readNote(this.user.id, payload.id);
+ }
}
/**
diff --git a/src/services/note/read-mention.ts b/src/services/note/read-mention.ts
deleted file mode 100644
index 2a668ecd6c..0000000000
--- a/src/services/note/read-mention.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { publishMainStream } from '../stream';
-import { Note } from '../../models/entities/note';
-import { User } from '../../models/entities/user';
-import { NoteUnreads } from '../../models';
-import { In } from 'typeorm';
-
-/**
- * Mark a mention note as read
- */
-export async function readMention(
- userId: User['id'],
- noteIds: Note['id'][]
-) {
- // Remove the records
- await NoteUnreads.delete({
- userId: userId,
- noteId: In(noteIds),
- });
-
- const mentionsCount = await NoteUnreads.count({
- userId: userId,
- isMentioned: true
- });
-
- if (mentionsCount === 0) {
- // 全て既読になったイベントを発行
- publishMainStream(userId, 'readAllUnreadMentions');
- }
-}
diff --git a/src/services/note/read-specified-note.ts b/src/services/note/read-specified-note.ts
deleted file mode 100644
index 0fcb66bf98..0000000000
--- a/src/services/note/read-specified-note.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { publishMainStream } from '../stream';
-import { Note } from '../../models/entities/note';
-import { User } from '../../models/entities/user';
-import { NoteUnreads } from '../../models';
-import { In } from 'typeorm';
-
-/**
- * Mark a specified note as read
- */
-export async function readSpecifiedNote(
- userId: User['id'],
- noteIds: Note['id'][]
-) {
- // Remove the records
- await NoteUnreads.delete({
- userId: userId,
- noteId: In(noteIds),
- });
-
- const specifiedCount = await NoteUnreads.count({
- userId: userId,
- isSpecified: true
- });
-
- if (specifiedCount === 0) {
- // 全て既読になったイベントを発行
- publishMainStream(userId, 'readAllUnreadSpecifiedNotes');
- }
-}
diff --git a/src/services/note/read.ts b/src/services/note/read.ts
new file mode 100644
index 0000000000..5a39ab30b7
--- /dev/null
+++ b/src/services/note/read.ts
@@ -0,0 +1,105 @@
+import { publishMainStream } from '../stream';
+import { Note } from '../../models/entities/note';
+import { User } from '../../models/entities/user';
+import { NoteUnreads, Antennas, AntennaNotes, Users } from '../../models';
+import { Not, IsNull } from 'typeorm';
+
+/**
+ * Mark a note as read
+ */
+export default async function(
+ userId: User['id'],
+ noteId: Note['id']
+) {
+ async function careNoteUnreads() {
+ const exist = await NoteUnreads.findOne({
+ userId: userId,
+ noteId: noteId,
+ });
+
+ if (!exist) return;
+
+ // Remove the record
+ await NoteUnreads.delete({
+ userId: userId,
+ noteId: noteId,
+ });
+
+ if (exist.isMentioned) {
+ NoteUnreads.count({
+ userId: userId,
+ isMentioned: true
+ }).then(mentionsCount => {
+ if (mentionsCount === 0) {
+ // 全て既読になったイベントを発行
+ publishMainStream(userId, 'readAllUnreadMentions');
+ }
+ });
+ }
+
+ if (exist.isSpecified) {
+ NoteUnreads.count({
+ userId: userId,
+ isSpecified: true
+ }).then(specifiedCount => {
+ if (specifiedCount === 0) {
+ // 全て既読になったイベントを発行
+ publishMainStream(userId, 'readAllUnreadSpecifiedNotes');
+ }
+ });
+ }
+
+ if (exist.noteChannelId) {
+ NoteUnreads.count({
+ userId: userId,
+ noteChannelId: Not(IsNull())
+ }).then(channelNoteCount => {
+ if (channelNoteCount === 0) {
+ // 全て既読になったイベントを発行
+ publishMainStream(userId, 'readAllChannels');
+ }
+ });
+ }
+ }
+
+ async function careAntenna() {
+ const beforeUnread = await Users.getHasUnreadAntenna(userId);
+ if (!beforeUnread) return;
+
+ const antennas = await Antennas.find({ userId });
+
+ await Promise.all(antennas.map(async antenna => {
+ const countBefore = await AntennaNotes.count({
+ antennaId: antenna.id,
+ read: false
+ });
+
+ if (countBefore === 0) return;
+
+ await AntennaNotes.update({
+ antennaId: antenna.id,
+ noteId: noteId
+ }, {
+ read: true
+ });
+
+ const countAfter = await AntennaNotes.count({
+ antennaId: antenna.id,
+ read: false
+ });
+
+ if (countAfter === 0) {
+ publishMainStream(userId, 'readAntenna', antenna);
+ }
+ }));
+
+ Users.getHasUnreadAntenna(userId).then(unread => {
+ if (!unread) {
+ publishMainStream(userId, 'readAllAntennas');
+ }
+ });
+ }
+
+ careNoteUnreads();
+ careAntenna();
+}