diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index a1e806816b..04bbc7e38a 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -39,6 +39,7 @@ import type { } from './QueueModule.js'; import type httpSignature from '@peertube/http-signature'; import type * as Bull from 'bullmq'; +import type { Packed } from '@/misc/json-schema.js'; export const QUEUE_TYPES = [ 'system', @@ -774,13 +775,13 @@ export class QueueService { } @bindThis - private packJobData(job: Bull.Job) { + private packJobData(job: Bull.Job): Packed<'QueueJob'> { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const stacktrace = job.stacktrace ? job.stacktrace.filter(Boolean) : []; stacktrace.reverse(); return { - id: job.id, + id: job.id!, name: job.name, data: job.data, opts: job.opts, diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index e4eb10efca..23f6b692a7 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -31,7 +31,11 @@ import { packedChannelSchema } from '@/models/json-schema/channel.js'; import { packedAntennaSchema } from '@/models/json-schema/antenna.js'; import { packedClipSchema } from '@/models/json-schema/clip.js'; import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js'; -import { packedQueueCountSchema } from '@/models/json-schema/queue.js'; +import { + packedQueueCountSchema, + packedQueueMetricsSchema, + packedQueueJobSchema, +} from '@/models/json-schema/queue.js'; import { packedGalleryPostSchema } from '@/models/json-schema/gallery-post.js'; import { packedEmojiDetailedAdminSchema, @@ -100,6 +104,8 @@ export const refs = { PageBlock: packedPageBlockSchema, Channel: packedChannelSchema, QueueCount: packedQueueCountSchema, + QueueMetrics: packedQueueMetricsSchema, + QueueJob: packedQueueJobSchema, Antenna: packedAntennaSchema, Clip: packedClipSchema, FederationInstance: packedFederationInstanceSchema, diff --git a/packages/backend/src/models/json-schema/queue.ts b/packages/backend/src/models/json-schema/queue.ts index 2ecf5c831f..dad0cf57f6 100644 --- a/packages/backend/src/models/json-schema/queue.ts +++ b/packages/backend/src/models/json-schema/queue.ts @@ -28,3 +28,110 @@ export const packedQueueCountSchema = { }, }, } as const; + +// Bull.Metrics +export const packedQueueMetricsSchema = { + type: 'object', + properties: { + meta: { + type: 'object', + optional: false, nullable: false, + properties: { + count: { + type: 'number', + optional: false, nullable: false, + }, + prevTS: { + type: 'number', + optional: false, nullable: false, + }, + prevCount: { + type: 'number', + optional: false, nullable: false, + }, + }, + }, + data: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'number', + optional: false, nullable: false, + }, + }, + count: { + type: 'number', + optional: false, nullable: false, + }, + }, +} as const; + +export const packedQueueJobSchema = { + type: 'object', + properties: { + id: { + type: 'string', + optional: false, nullable: false, + }, + name: { + type: 'string', + optional: false, nullable: false, + }, + data: { + type: 'object', + optional: false, nullable: false, + }, + opts: { + type: 'object', + optional: false, nullable: false, + }, + timestamp: { + type: 'number', + optional: false, nullable: false, + }, + processedOn: { + type: 'number', + optional: true, nullable: false, + }, + processedBy: { + type: 'string', + optional: true, nullable: false, + }, + finishedOn: { + type: 'number', + optional: true, nullable: false, + }, + progress: { + type: 'object', + optional: false, nullable: false, + }, + attempts: { + type: 'number', + optional: false, nullable: false, + }, + delay: { + type: 'number', + optional: false, nullable: false, + }, + failedReason: { + type: 'string', + optional: false, nullable: false, + }, + stacktrace: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'string', + optional: false, nullable: false, + }, + }, + returnValue: { + type: 'object', + optional: false, nullable: false, + }, + isFailed: { + type: 'boolean', + optional: false, nullable: false, + }, + }, +} as const; diff --git a/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts b/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts index 79731c9786..155f2c4000 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts @@ -5,7 +5,6 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; import { QUEUE_TYPES, QueueService } from '@/core/QueueService.js'; export const meta = { @@ -14,6 +13,15 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'read:admin:queue', + + res: { + type: 'array', + optional: false, nullable: false, + items: { + optional: false, nullable: false, + ref: 'QueueJob', + }, + }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/queue/queue-stats.ts b/packages/backend/src/server/api/endpoints/admin/queue/queue-stats.ts index 10ce48332a..0098160165 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/queue-stats.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/queue-stats.ts @@ -5,7 +5,6 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; import { QUEUE_TYPES, QueueService } from '@/core/QueueService.js'; export const meta = { @@ -14,6 +13,118 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'read:admin:queue', + + res: { + type: 'object', + optional: false, nullable: false, + properties: { + name: { + type: 'string', + optional: false, nullable: false, + enum: QUEUE_TYPES, + }, + qualifiedName: { + type: 'string', + optional: false, nullable: false, + }, + counts: { + type: 'object', + optional: false, nullable: false, + additionalProperties: { + type: 'number', + }, + }, + isPaused: { + type: 'boolean', + optional: false, nullable: false, + }, + metrics: { + type: 'object', + optional: false, nullable: false, + properties: { + completed: { + optional: false, nullable: false, + ref: 'QueueMetrics', + }, + failed: { + optional: false, nullable: false, + ref: 'QueueMetrics', + }, + }, + }, + db: { + type: 'object', + optional: false, nullable: false, + properties: { + version: { + type: 'string', + optional: false, nullable: false, + }, + mode: { + type: 'string', + optional: false, nullable: false, + enum: ['cluster', 'standalone', 'sentinel'], + }, + runId: { + type: 'string', + optional: false, nullable: false, + }, + processId: { + type: 'string', + optional: false, nullable: false, + }, + port: { + type: 'number', + optional: false, nullable: false, + }, + os: { + type: 'string', + optional: false, nullable: false, + }, + uptime: { + type: 'number', + optional: false, nullable: false, + }, + memory: { + type: 'object', + optional: false, nullable: false, + properties: { + total: { + type: 'number', + optional: false, nullable: false, + }, + used: { + type: 'number', + optional: false, nullable: false, + }, + fragmentationRatio: { + type: 'number', + optional: false, nullable: false, + }, + peak: { + type: 'number', + optional: false, nullable: false, + }, + }, + }, + clients: { + type: 'object', + optional: false, nullable: false, + properties: { + blocked: { + type: 'number', + optional: false, nullable: false, + }, + connected: { + type: 'number', + optional: false, nullable: false, + }, + }, + }, + }, + } + }, + }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/queue/queues.ts b/packages/backend/src/server/api/endpoints/admin/queue/queues.ts index 3a38275f60..8d27e38c84 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/queues.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/queues.ts @@ -5,7 +5,6 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; import { QUEUE_TYPES, QueueService } from '@/core/QueueService.js'; export const meta = { @@ -14,6 +13,47 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'read:admin:queue', + + res: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + properties: { + name: { + type: 'string', + optional: false, nullable: false, + enum: QUEUE_TYPES, + }, + counts: { + type: 'object', + optional: false, nullable: false, + additionalProperties: { + type: 'number', + }, + }, + isPaused: { + type: 'boolean', + optional: false, nullable: false, + }, + metrics: { + type: 'object', + optional: false, nullable: false, + properties: { + completed: { + optional: false, nullable: false, + ref: 'QueueMetrics', + }, + failed: { + optional: false, nullable: false, + ref: 'QueueMetrics', + }, + }, + }, + }, + }, + }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/queue/show-job.ts b/packages/backend/src/server/api/endpoints/admin/queue/show-job.ts index 63747b5540..1735c22674 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/show-job.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/show-job.ts @@ -5,7 +5,6 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; import { QUEUE_TYPES, QueueService } from '@/core/QueueService.js'; export const meta = { @@ -14,6 +13,11 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'read:admin:queue', + + res: { + optional: false, nullable: false, + ref: 'QueueJob', + }, } as const; export const paramDef = { @@ -28,7 +32,6 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - private moderationLogService: ModerationLogService, private queueService: QueueService, ) { super(meta, paramDef, async (ps, me) => { diff --git a/packages/frontend/src/components/MkTl.vue b/packages/frontend/src/components/MkTl.vue index 95cc4d2a2a..30bf5389be 100644 --- a/packages/frontend/src/components/MkTl.vue +++ b/packages/frontend/src/components/MkTl.vue @@ -21,15 +21,19 @@ SPDX-License-Identifier: AGPL-3.0-only - + +