diff --git a/src/client/app/common/views/deck/deck.widgets-column.vue b/src/client/app/common/views/deck/deck.widgets-column.vue index 47a584a53..fcf3afd3f 100644 --- a/src/client/app/common/views/deck/deck.widgets-column.vue +++ b/src/client/app/common/views/deck/deck.widgets-column.vue @@ -26,6 +26,7 @@ + diff --git a/src/client/app/common/views/widgets/index.ts b/src/client/app/common/views/widgets/index.ts index 05aa08375..d923a0194 100644 --- a/src/client/app/common/views/widgets/index.ts +++ b/src/client/app/common/views/widgets/index.ts @@ -31,3 +31,4 @@ Vue.component('mkw-version', wVersion); Vue.component('mkw-hashtags', wHashtags); Vue.component('mkw-instance', wInstance); Vue.component('mkw-post-form', wPostForm); +Vue.component('mkw-queue', () => import('./queue.vue').then(m => m.default)); diff --git a/src/client/app/common/views/widgets/queue.vue b/src/client/app/common/views/widgets/queue.vue new file mode 100644 index 000000000..18bfeb3ba --- /dev/null +++ b/src/client/app/common/views/widgets/queue.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/src/client/app/desktop/views/home/home.vue b/src/client/app/desktop/views/home/home.vue index 740aa1289..fb7af5a9a 100644 --- a/src/client/app/desktop/views/home/home.vue +++ b/src/client/app/desktop/views/home/home.vue @@ -27,6 +27,7 @@ + diff --git a/src/client/app/mobile/views/pages/widgets.vue b/src/client/app/mobile/views/pages/widgets.vue index 7722104af..96dcb977f 100644 --- a/src/client/app/mobile/views/pages/widgets.vue +++ b/src/client/app/mobile/views/pages/widgets.vue @@ -19,6 +19,7 @@ + diff --git a/src/daemons/queue-stats.ts b/src/daemons/queue-stats.ts new file mode 100644 index 000000000..26f2bf7c0 --- /dev/null +++ b/src/daemons/queue-stats.ts @@ -0,0 +1,43 @@ +import * as Deque from 'double-ended-queue'; +import Xev from 'xev'; +import { deliverQueue, inboxQueue } from '../queue'; + +const ev = new Xev(); + +const interval = 1000; + +/** + * Report queue stats regularly + */ +export default function() { + const log = new Deque(); + + ev.on('requestQueueStatsLog', x => { + ev.emit(`queueStatsLog:${x.id}`, log.toArray().slice(0, x.length || 50)); + }); + + async function tick() { + const deliverJobCounts = await deliverQueue.getJobCounts(); + const inboxJobCounts = await inboxQueue.getJobCounts(); + + const stats = { + deliver: { + active: Math.floor(Math.random() * 100), + delayed: Math.floor(Math.random() * 1000), + }, + inbox: { + active: Math.floor(Math.random() * 100), + delayed: Math.floor(Math.random() * 1000), + } + }; + + ev.emit('queueStats', stats); + + log.unshift(stats); + if (log.length > 200) log.pop(); + } + + tick(); + + setInterval(tick, interval); +} diff --git a/src/index.ts b/src/index.ts index 0df38b596..e55ba5115 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,7 @@ import Xev from 'xev'; import Logger from './services/logger'; import serverStats from './daemons/server-stats'; import notesStats from './daemons/notes-stats'; +import queueStats from './daemons/queue-stats'; import loadConfig from './config/load'; import { Config } from './config/types'; import { lessThan } from './prelude/array'; @@ -50,6 +51,7 @@ function main() { if (program.daemons) { serverStats(); notesStats(); + queueStats(); } } diff --git a/src/server/api/stream/channels/index.ts b/src/server/api/stream/channels/index.ts index 02f71b585..4527fb1e4 100644 --- a/src/server/api/stream/channels/index.ts +++ b/src/server/api/stream/channels/index.ts @@ -5,6 +5,7 @@ import hybridTimeline from './hybrid-timeline'; import globalTimeline from './global-timeline'; import notesStats from './notes-stats'; import serverStats from './server-stats'; +import queueStats from './queue-stats'; import userList from './user-list'; import messaging from './messaging'; import messagingIndex from './messaging-index'; @@ -23,6 +24,7 @@ export default { globalTimeline, notesStats, serverStats, + queueStats, userList, messaging, messagingIndex, diff --git a/src/server/api/stream/channels/queue-stats.ts b/src/server/api/stream/channels/queue-stats.ts new file mode 100644 index 000000000..0bda0cfcb --- /dev/null +++ b/src/server/api/stream/channels/queue-stats.ts @@ -0,0 +1,41 @@ +import autobind from 'autobind-decorator'; +import Xev from 'xev'; +import Channel from '../channel'; + +const ev = new Xev(); + +export default class extends Channel { + public readonly chName = 'queueStats'; + public static shouldShare = true; + public static requireCredential = false; + + @autobind + public async init(params: any) { + ev.addListener('queueStats', this.onStats); + } + + @autobind + private onStats(stats: any) { + this.send('stats', stats); + } + + @autobind + public onMessage(type: string, body: any) { + switch (type) { + case 'requestLog': + ev.once(`queueStatsLog:${body.id}`, statsLog => { + this.send('statsLog', statsLog); + }); + ev.emit('requestQueueStatsLog', { + id: body.id, + length: body.length + }); + break; + } + } + + @autobind + public dispose() { + ev.removeListener('queueStats', this.onStats); + } +}