|
@@ -4,6 +4,11 @@ const mq = require('../../../plugin/mq')
|
|
|
const config = require('../../../config.json')
|
|
const config = require('../../../config.json')
|
|
|
const AccessControl = require('../../../lib/AccessControl')
|
|
const AccessControl = require('../../../lib/AccessControl')
|
|
|
const { BaseStdResponse } = require('../../../BaseStdResponse')
|
|
const { BaseStdResponse } = require('../../../BaseStdResponse')
|
|
|
|
|
+const {
|
|
|
|
|
+ SCHEDULE_KEY,
|
|
|
|
|
+ listPendingScheduledForAdmin,
|
|
|
|
|
+ countPendingScheduled
|
|
|
|
|
+} = require('../../../plugin/mq/lepaoAutoScheduleRedis')
|
|
|
|
|
|
|
|
/** 允许通过管理接口查看的队列(防任意队列名探测) */
|
|
/** 允许通过管理接口查看的队列(防任意队列名探测) */
|
|
|
const ALLOWED_QUEUES = [
|
|
const ALLOWED_QUEUES = [
|
|
@@ -118,7 +123,15 @@ class GetQueueTasks extends API {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async onRequest(req, res) {
|
|
async onRequest(req, res) {
|
|
|
- const { uuid, session, queue, limit: limitStr, summary } = req.query
|
|
|
|
|
|
|
+ const {
|
|
|
|
|
+ uuid,
|
|
|
|
|
+ session,
|
|
|
|
|
+ queue,
|
|
|
|
|
+ limit: limitStr,
|
|
|
|
|
+ summary,
|
|
|
|
|
+ includeScheduled,
|
|
|
|
|
+ scheduledLimit: scheduledLimitStr
|
|
|
|
|
+ } = req.query
|
|
|
|
|
|
|
|
if ([uuid, session].some((v) => v === '' || v == null))
|
|
if ([uuid, session].some((v) => v === '' || v == null))
|
|
|
return res.json({
|
|
return res.json({
|
|
@@ -158,11 +171,29 @@ class GetQueueTasks extends API {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ const slimit = Math.min(
|
|
|
|
|
+ 2000,
|
|
|
|
|
+ Math.max(1, parseInt(scheduledLimitStr, 10) || 800)
|
|
|
|
|
+ )
|
|
|
|
|
+ const pendingCount = await countPendingScheduled(Date.now())
|
|
|
|
|
+ const scheduledMirror = await listPendingScheduledForAdmin(Date.now(), slimit)
|
|
|
|
|
+
|
|
|
return res.json({
|
|
return res.json({
|
|
|
...BaseStdResponse.OK,
|
|
...BaseStdResponse.OK,
|
|
|
data: {
|
|
data: {
|
|
|
summary: true,
|
|
summary: true,
|
|
|
queues,
|
|
queues,
|
|
|
|
|
+ redisScheduler: {
|
|
|
|
|
+ key: SCHEDULE_KEY,
|
|
|
|
|
+ pendingCount,
|
|
|
|
|
+ note: '到期任务由本服务定时写入 runforge_task_queue;多实例共享同一 Redis ZSET。'
|
|
|
|
|
+ },
|
|
|
|
|
+ autoRunScheduledMirror: {
|
|
|
|
|
+ pendingCount,
|
|
|
|
|
+ note: scheduledMirror.note,
|
|
|
|
|
+ sample: scheduledMirror.items.slice(0, 20)
|
|
|
|
|
+ },
|
|
|
fetchedAt: Date.now()
|
|
fetchedAt: Date.now()
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
@@ -206,17 +237,49 @@ class GetQueueTasks extends API {
|
|
|
this.logger.warn(`[GetQueueTasks] Management 窥视失败: ${managementError}`)
|
|
this.logger.warn(`[GetQueueTasks] Management 窥视失败: ${managementError}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const wantScheduled =
|
|
|
|
|
+ includeScheduled !== '0' &&
|
|
|
|
|
+ includeScheduled !== 'false' &&
|
|
|
|
|
+ queueName === 'runforge_task_queue'
|
|
|
|
|
+
|
|
|
|
|
+ let autoRunScheduledMirror = null
|
|
|
|
|
+ let pendingScheduledCount = null
|
|
|
|
|
+ if (queueName === 'runforge_task_queue') {
|
|
|
|
|
+ pendingScheduledCount = await countPendingScheduled(Date.now())
|
|
|
|
|
+ if (wantScheduled) {
|
|
|
|
|
+ const slimit = Math.min(
|
|
|
|
|
+ 500,
|
|
|
|
|
+ Math.max(1, parseInt(scheduledLimitStr, 10) || 200)
|
|
|
|
|
+ )
|
|
|
|
|
+ autoRunScheduledMirror = await listPendingScheduledForAdmin(Date.now(), slimit)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const detail = {
|
|
|
|
|
+ queue: queueName,
|
|
|
|
|
+ messageCount,
|
|
|
|
|
+ consumerCount,
|
|
|
|
|
+ peekLimit: limit,
|
|
|
|
|
+ tasks,
|
|
|
|
|
+ managementError,
|
|
|
|
|
+ redisScheduler:
|
|
|
|
|
+ queueName === 'runforge_task_queue'
|
|
|
|
|
+ ? {
|
|
|
|
|
+ key: SCHEDULE_KEY,
|
|
|
|
|
+ pendingCount: pendingScheduledCount
|
|
|
|
|
+ }
|
|
|
|
|
+ : undefined,
|
|
|
|
|
+ autoRunScheduledMirror,
|
|
|
|
|
+ fetchedAt: Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+ if (queueName === 'runforge_task_queue') {
|
|
|
|
|
+ detail.peekNote =
|
|
|
|
|
+ 'tasks:已在主队列中的消息;autoRunScheduledMirror:尚未到 fireAt、仍只在 Redis 中的调度(到期后由服务写入 MQ)。'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return res.json({
|
|
return res.json({
|
|
|
...BaseStdResponse.OK,
|
|
...BaseStdResponse.OK,
|
|
|
- data: {
|
|
|
|
|
- queue: queueName,
|
|
|
|
|
- messageCount,
|
|
|
|
|
- consumerCount,
|
|
|
|
|
- peekLimit: limit,
|
|
|
|
|
- tasks,
|
|
|
|
|
- managementError,
|
|
|
|
|
- fetchedAt: Date.now()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ data: detail
|
|
|
})
|
|
})
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
this.logger.error(`GetQueueTasks: ${error.stack || error}`)
|
|
this.logger.error(`GetQueueTasks: ${error.stack || error}`)
|