Skip to content

feat(queue): 新增循环队列模式 - #268

Open
qiyinxi wants to merge 5 commits into
AUTO-MAS-Project:devfrom
qiyinxi:feat/circle-mode-pr
Open

feat(queue): 新增循环队列模式#268
qiyinxi wants to merge 5 commits into
AUTO-MAS-Project:devfrom
qiyinxi:feat/circle-mode-pr

Conversation

@qiyinxi

@qiyinxi qiyinxi commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

摘要

  • 新增循环队列类型与 CycleRun 调度模式,支持队列按脚本级循环配置持续运行。
  • 为队列项增加循环配置与运行数据,包括固定时间、间隔分钟、间隔基准、插入一次时间和任务级开关。
  • 调度台新增循环运行入口、下轮任务预览和运行中等待状态展示,队列配置页区分定时队列与循环队列。
  • 循环队列运行期间锁定队列配置,并在脚本冲突、执行失败时按等待与优先重试逻辑处理。

Summary by Sourcery

为队列引入新的循环运行调度模式,使脚本级的周期性执行支持针对每个队列项的独立计划和 UI 展示。

新功能:

  • 为每个队列项新增循环调度配置,包括启用开关、固定时间或时间间隔模式、工作日选择、间隔锚点,以及一次性“下次运行时间”插入。
  • 在后端支持新的 CycleRun 任务模式,以持续循环的方式运行队列,并包含冲突处理、重试逻辑和下次运行时间计算。
  • 扩展调度器 UI,增加 CycleRun 模式,包括下一个循环的预览面板,以及过滤功能,确保只有队列可以被选择用于循环运行。
  • 允许创建并区分定时队列和循环队列,启动时会选择合适的运行模式,并通过弹窗(modal)让用户选择队列类型。

缺陷修复:

  • 规范并简化任务树和概览中的状态文案展示,将“等待重试”统一归为通用的等待状态,并隐藏非活跃条目。

增强改进:

  • 在循环队列运行期间禁用对队列和队列项的编辑和结构变更,并在前端和后端均强制执行该限制。
  • 改进队列项和调度器的 UI,提供更清晰的布局、标签和响应式样式,包括队列类型标签和调整后的控件尺寸。
  • 通过 API 和 websocket 暴露循环调度和运行时元数据,以便客户端展示即将到来的和正在进行中的循环运行。
Original summary in English

Summary by Sourcery

Introduce a new cycle-run scheduling mode for queues, enabling script-level recurring execution with per-item schedules and UI support.

New Features:

  • Add per-queue-item cycle scheduling configuration including enable switch, fixed time or interval mode, weekday selection, interval anchor, and one-off next-run insertion.
  • Support a new CycleRun task mode in the backend, running queues in a continuous loop with conflict handling, retry logic, and next-run calculations.
  • Extend the scheduler UI with a CycleRun mode, including a next-cycle preview panel and filtering so only queues can be selected for cycle runs.
  • Allow creating and distinguishing between timed queues and cycle queues, with startup behavior selecting the appropriate run mode and a modal for choosing the queue type.

Bug Fixes:

  • Normalize and simplify status text display in the task tree and overview, consolidating "等待重试" into a generic waiting state and hiding inactive items.

Enhancements:

  • Disable editing and structural changes for queues and queue items while a cycle queue is running, enforcing this both in the frontend and backend.
  • Improve queue item and scheduler UIs with clearer layout, tags, and responsive styles, including labels for queue types and adjusted control sizes.
  • Expose cycle schedule and runtime metadata via API and websocket so clients can display upcoming and in-progress cycle runs.
Original summary in English

Summary by Sourcery

为队列引入新的循环运行调度模式,使脚本级的周期性执行支持针对每个队列项的独立计划和 UI 展示。

新功能:

  • 为每个队列项新增循环调度配置,包括启用开关、固定时间或时间间隔模式、工作日选择、间隔锚点,以及一次性“下次运行时间”插入。
  • 在后端支持新的 CycleRun 任务模式,以持续循环的方式运行队列,并包含冲突处理、重试逻辑和下次运行时间计算。
  • 扩展调度器 UI,增加 CycleRun 模式,包括下一个循环的预览面板,以及过滤功能,确保只有队列可以被选择用于循环运行。
  • 允许创建并区分定时队列和循环队列,启动时会选择合适的运行模式,并通过弹窗(modal)让用户选择队列类型。

缺陷修复:

  • 规范并简化任务树和概览中的状态文案展示,将“等待重试”统一归为通用的等待状态,并隐藏非活跃条目。

增强改进:

  • 在循环队列运行期间禁用对队列和队列项的编辑和结构变更,并在前端和后端均强制执行该限制。
  • 改进队列项和调度器的 UI,提供更清晰的布局、标签和响应式样式,包括队列类型标签和调整后的控件尺寸。
  • 通过 API 和 websocket 暴露循环调度和运行时元数据,以便客户端展示即将到来的和正在进行中的循环运行。
Original summary in English

Summary by Sourcery

Introduce a new cycle-run scheduling mode for queues, enabling script-level recurring execution with per-item schedules and UI support.

New Features:

  • Add per-queue-item cycle scheduling configuration including enable switch, fixed time or interval mode, weekday selection, interval anchor, and one-off next-run insertion.
  • Support a new CycleRun task mode in the backend, running queues in a continuous loop with conflict handling, retry logic, and next-run calculations.
  • Extend the scheduler UI with a CycleRun mode, including a next-cycle preview panel and filtering so only queues can be selected for cycle runs.
  • Allow creating and distinguishing between timed queues and cycle queues, with startup behavior selecting the appropriate run mode and a modal for choosing the queue type.

Bug Fixes:

  • Normalize and simplify status text display in the task tree and overview, consolidating "等待重试" into a generic waiting state and hiding inactive items.

Enhancements:

  • Disable editing and structural changes for queues and queue items while a cycle queue is running, enforcing this both in the frontend and backend.
  • Improve queue item and scheduler UIs with clearer layout, tags, and responsive styles, including labels for queue types and adjusted control sizes.
  • Expose cycle schedule and runtime metadata via API and websocket so clients can display upcoming and in-progress cycle runs.

@sourcery-ai

sourcery-ai Bot commented Jun 27, 2026

Copy link
Copy Markdown

审阅者指南

为队列实现新的 CycleRun 模式,用于按队列项的循环计划执行;新增后端计划/数据字段和调度逻辑,用于持续执行与预览;更新队列/定时器行为以区分“定时队列”和“循环队列”;并新增前端 UI,用于配置循环计划、启动循环运行、预览即将运行的任务,以及在循环队列运行期间锁定编辑操作。

CycleRun 队列执行与预览的时序图

sequenceDiagram
    actor User
    participant SchedulerUI as SchedulerCenter
    participant TaskManager as TaskManager.add_task
    participant Task as Task.main_task
    participant QueueCycle as collect_queue_cycle_entries

    User->>SchedulerUI: startTask(tab) with mode = CycleRun
    SchedulerUI->>TaskManager: add_task(mode="CycleRun", id=selectedTaskId)
    TaskManager-->>SchedulerUI: task_uid
    TaskManager->>Task: execute() -> main_task()
    Task->>Task: prepare()
    Task->>Task: _run_cycle_task()
    Task->>Task: _run_cycle_loop(queue_uid)
    loop cycle loop
        Task->>QueueCycle: collect_queue_cycle_entries(queue, ScriptConfig, now)
        QueueCycle-->>Task: entries
        Task->>Task: _set_cycle_preview(entries)
        alt entries due
            Task->>Task: _run_cycle_script(queue_uid, entry,...)
            Task->>QueueCycle: calculate_next_after_start/finish()
            Task->>Task: _refresh_cycle_preview(queue_uid)
        else no due entries
            Task->>Task: asyncio.sleep(wait_seconds)
        end
    end
Loading

文件级变更

Change Details Files
为每个队列项新增循环调度模型和持久化,并添加队列级的循环模式标记。
  • 扩展后端 QueueItem 配置,新增 Schedule(mode, days, time, interval, nextRunAt)和 Data(上次循环时间戳)两个部分及其校验器。
  • 在 API 类型中暴露新的 QueueItem_Schedule 和 QueueItem_Data 模型,并将它们接入 QueueItem schema 和 TS 类型。
  • 在后端和前端 API 模型中,为 QueueConfig.Info 增加 CycleEnabled 标记。
app/models/config.py
app/models/schema.py
frontend/src/api/models/QueueItem.ts
frontend/src/api/models/QueueItem_Schedule.ts
frontend/src/api/models/QueueItem_Data.ts
frontend/src/api/models/QueueConfig_Info.ts
frontend/src/api/index.ts
为队列实现 CycleRun 执行管线,包括调度、冲突处理、重试/等待行为以及预览数据。
  • 新增 queue_cycle 辅助模块,用于计算固定时间与间隔模式的下一次运行时间,并收集/筛选符合条件的条目。
  • 扩展 Task/TaskManager/Config,用于跟踪 CycleRun 模式、正在运行的循环队列,并防止同一队列并发运行。
  • 新增 Task._run_cycle_task 循环,反复选择到期项,使用现有管理器运行脚本,更新 NextRunAt/最近循环时间戳,裁剪日志历史,并填充通过 WebSocket 推送的 cycleNext/cycleNextList 预览数据。
  • 更新启动/定时器行为,使启动队列在启用 CycleEnabled 时以 CycleRun 运行,而定时调度器忽略循环队列。
app/core/queue_cycle.py
app/core/task_manager.py
app/models/task.py
app/core/config.py
app/core/timer.py
保护后端队列/时间集/队列项变更 API,防止在对应循环队列运行时进行编辑。
  • 在 Config 和 TaskManager 中跟踪 running_cycle_queue_ids,并在任务生命周期内维护该集合。
  • 在 Config 中新增 _ensure_queue_editable,并在队列/时间集/队列项的新增/更新/删除/重排路径中调用,当队列当前以循环模式运行时抛出异常。
app/core/config.py
app/core/task_manager.py
增强队列配置和队列项管理 UI,以支持定时队列与循环队列、循环项调度控制,以及循环队列运行期间的编辑锁定。
  • 在队列页面引入 QueueKind(timed/cycle)概念,增加类型标签、创建队列时选择类型的弹窗,以及 TimeEnabled 与 CycleEnabled 开关;按条件渲染仅限“定时队列”的设置和 TimeSetManager。
  • 从调度器标签页状态(sessionStorage)中检测正在运行的循环队列,并暴露 currentQueueEditingDisabled,用于禁用删除/重命名/配置字段并展示警告提示。
  • 扩展 QueueItemManager 以接受 showCycleConfig/disabled 属性,切换为强类型的 QueueItemRecord,为每个队列项增加计划控制(mode, days, time, interval, nextRunAt, 启用开关),并通过 updateQueueItemSchedule 统一更新逻辑,对时间选择器采用类似防抖的草稿处理;在相关变更后广播自定义的 queue-cycle-schedule-updated 事件。
  • 调整队列项控件与按钮的布局/间距,以容纳新的循环配置 UI。
frontend/src/views/queue/index.vue
frontend/src/views/queue/components/QueueItemManager.vue
扩展调度器 UI/逻辑,以支持 CycleRun 模式、仅队列任务选择、循环预览面板,以及与 cycleNext 更新的集成。
  • 在 schedulerConstants 中新增 CycleRun 模式常量与选项,以及 SchedulerTab 上的 CycleNextInfo/cycleNext(cycleNextList) 字段,并贯穿到 SchedulerTaskControl/Scheduler index 组件。
  • 在 SchedulerTaskControl 中,当选择 CycleRun 时,将任务选项过滤为队列类型,并显示一个四格“下次运行”预览面板,使用 cycleNextList/cycleNext;在切换模式时自动清理不兼容的选择和 resumeFromScriptId。
  • 在 useSchedulerLogic 中,从后端任务创建结果中持久化 tab.selectedMode,校验 CycleRun 只能绑定队列;当选择/配置变更或任务完成时,从队列项刷新循环预览;在 WebSocket Update 消息中处理 cycleNext/cycleNextList,并响应 queue-cycle-schedule-updated 事件重新计算预览。
  • 将“继续脚本”下拉框限制为非 CycleRun 的队列任务,并通过 session storage 将标签页状态与新模式字段同步。
frontend/src/views/scheduler/SchedulerTaskControl.vue
frontend/src/views/scheduler/useSchedulerLogic.ts
frontend/src/views/scheduler/schedulerConstants.ts
frontend/src/views/scheduler/index.vue
优化任务总览和任务树展示,聚焦活跃/重试中的条目,并改进状态文案。
  • 在 TaskOverviewPanel 中,将 taskData 过滤为仅包含状态为 running/processing/retry-wait 的脚本/用户,以获得更聚焦的总览。
  • 在 TaskTree 中将状态标签“等待重试”统一为“等待”,同时保留原有颜色映射;保持现有悬停与布局行为不变。
  • 微调导入和少量布局样式,以适应新的行为。
frontend/src/views/scheduler/TaskOverviewPanel.vue
frontend/src/components/TaskTree.vue

提示与命令

与 Sourcery 交互

  • 触发新审查: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 在某条审查评论下回复,请求 Sourcery 以该评论创建 issue。你也可以直接在该评论下回复 @sourcery-ai issue 来生成 issue。
  • 生成 pull request 标题: 在 pull request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文任意位置写上 @sourcery-ai summary,即可在该位置生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来在任意时间(重新)生成摘要。
  • 生成审阅者指南: 在 pull request 中评论 @sourcery-ai guide,即可在任意时间(重新)生成审阅者指南。
  • 一次性解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可将所有 Sourcery 评论标记为已解决。当你已经处理完所有评论且不想再看到它们时,此功能非常有用。
  • 批量忽略所有 Sourcery 审查: 在 pull request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。尤其适用于你想从一次全新的审查开始时——别忘了随后评论 @sourcery-ai review 以触发新的审查!

自定义使用体验

打开你的 dashboard 以:

  • 启用或禁用诸如 Sourcery 生成的 pull request 摘要、审阅者指南等审查功能。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

Implements a new CycleRun mode for queues with per-item recurring schedules, adds backend schedule/data fields and scheduler logic for continuous execution and preview, updates queue/timer behavior to distinguish timed vs cycle queues, and introduces frontend UI for configuring cycle schedules, starting cycle runs, previewing upcoming runs, and locking editing while a cycle queue is running.

Sequence diagram for CycleRun queue execution and preview

sequenceDiagram
    actor User
    participant SchedulerUI as SchedulerCenter
    participant TaskManager as TaskManager.add_task
    participant Task as Task.main_task
    participant QueueCycle as collect_queue_cycle_entries

    User->>SchedulerUI: startTask(tab) with mode = CycleRun
    SchedulerUI->>TaskManager: add_task(mode="CycleRun", id=selectedTaskId)
    TaskManager-->>SchedulerUI: task_uid
    TaskManager->>Task: execute() -> main_task()
    Task->>Task: prepare()
    Task->>Task: _run_cycle_task()
    Task->>Task: _run_cycle_loop(queue_uid)
    loop cycle loop
        Task->>QueueCycle: collect_queue_cycle_entries(queue, ScriptConfig, now)
        QueueCycle-->>Task: entries
        Task->>Task: _set_cycle_preview(entries)
        alt entries due
            Task->>Task: _run_cycle_script(queue_uid, entry,...)
            Task->>QueueCycle: calculate_next_after_start/finish()
            Task->>Task: _refresh_cycle_preview(queue_uid)
        else no due entries
            Task->>Task: asyncio.sleep(wait_seconds)
        end
    end
Loading

File-Level Changes

Change Details Files
Add per-queue-item cycle scheduling model and persistence, plus queue-level cycle mode flag.
  • Extend backend QueueItem config with Schedule (mode, days, time, interval, nextRunAt) and Data (last cycle timestamps) sections and validators.
  • Expose new QueueItem_Schedule and QueueItem_Data models in API types and wire them into QueueItem schema and TS types.
  • Add CycleEnabled flag to QueueConfig.Info on backend and in frontend API model.
app/models/config.py
app/models/schema.py
frontend/src/api/models/QueueItem.ts
frontend/src/api/models/QueueItem_Schedule.ts
frontend/src/api/models/QueueItem_Data.ts
frontend/src/api/models/QueueConfig_Info.ts
frontend/src/api/index.ts
Implement CycleRun execution pipeline for queues, including scheduling, conflict handling, retry/wait behavior, and preview data.
  • Add queue_cycle helper module to compute next run times for fixed-time and interval modes and to collect/pick eligible entries.
  • Extend Task/TaskManager/Config to track CycleRun mode, running cycle queues, and to prevent concurrent runs on the same queue.
  • Add Task._run_cycle_task loop that repeatedly selects due items, runs scripts with existing managers, updates NextRunAt/last cycle timestamps, trims log history, and populates cycleNext/cycleNextList preview data pushed over WebSocket.
  • Update startup/timer behavior so startup queues run in CycleRun when CycleEnabled, and timed scheduler ignores cycle queues.
app/core/queue_cycle.py
app/core/task_manager.py
app/models/task.py
app/core/config.py
app/core/timer.py
Guard backend queue/time-set/item mutation APIs against editing while the corresponding cycle queue is running.
  • Track running_cycle_queue_ids in Config and TaskManager and maintain it across task lifecycle.
  • Introduce _ensure_queue_editable on Config and call it from queue/time-set/item add/update/delete/reorder paths to raise if the queue is currently running in cycle mode.
app/core/config.py
app/core/task_manager.py
Enhance queue configuration and item management UI to support timed vs cycle queues, cycle item scheduling controls, and edit locking while a cycle queue is running.
  • Add QueueKind (timed/cycle) concept on the queue page, with type tag, creation modal choosing queue type, and toggles for TimeEnabled vs CycleEnabled; conditionally render timed-only settings and TimeSetManager.
  • Detect running cycle queues from scheduler tab state (sessionStorage) and expose currentQueueEditingDisabled, using it to disable delete/rename/config fields and show a warning alert.
  • Extend QueueItemManager to accept showCycleConfig/disabled props, switch to strongly-typed QueueItemRecord, add per-item schedule controls (mode, days, time, interval, nextRunAt, enabled switch), and centralize updates via updateQueueItemSchedule with debounce-like draft handling for time pickers; also broadcast a custom queue-cycle-schedule-updated event after relevant changes.
  • Adjust layout/spacing for queue item controls and buttons to accommodate new cycle configuration UI.
frontend/src/views/queue/index.vue
frontend/src/views/queue/components/QueueItemManager.vue
Extend scheduler UI/logic to support CycleRun mode, queue-only task selection, cycle preview panel, and integration with cycleNext updates.
  • Add CycleRun mode constant and option, plus CycleNextInfo/cycleNext(cycleNextList) fields on SchedulerTab in schedulerConstants and wire them through SchedulerTaskControl/Scheduler index components.
  • In SchedulerTaskControl, filter task options to queues when CycleRun is selected and show a four-slot "next run" preview grid that uses cycleNextList/cycleNext; automatically clear incompatible selections and resumeFromScriptId when switching modes.
  • In useSchedulerLogic, persist tab.selectedMode from backend task creation, validate CycleRun can only target queues, refresh cycle preview from queue items when selection/config changes or on task completion, handle cycleNext/cycleNextList in WebSocket Update messages, and react to queue-cycle-schedule-updated events to recompute previews.
  • Restrict resume script dropdown to non-CycleRun queue tasks and keep tabs in sync with new mode field in session storage.
frontend/src/views/scheduler/SchedulerTaskControl.vue
frontend/src/views/scheduler/useSchedulerLogic.ts
frontend/src/views/scheduler/schedulerConstants.ts
frontend/src/views/scheduler/index.vue
Refine task overview and task tree presentation to focus on active/retrying items and improve status text.
  • Filter TaskOverviewPanel taskData to only scripts/users with running/processing/retry-wait statuses for a more focused overview.
  • Normalize status label "等待重试" to "等待" in TaskTree while preserving color mapping; keep existing hover and layout behavior.
  • Tweak imports and minor layout styles consistent with new behavior.
frontend/src/views/scheduler/TaskOverviewPanel.vue
frontend/src/components/TaskTree.vue

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@qiyinxi
qiyinxi marked this pull request as ready for review June 27, 2026 15:11
@qiyinxi
qiyinxi requested a review from DLmaster361 June 27, 2026 15:11

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题,并且有一些整体性的反馈:

  • TaskManager 和 Config 都在跟踪 running_cycle_queue_ids,但更新逻辑分散在多个地方;建议把这块状态管理集中起来(例如把队列运行的相关簿记封装成一个单独的 helper),以避免两处状态之间出现细微且难以排查的不一致。
  • Task._run_cycle_loop 中与 cycle-run 相关的路径已经变得非常庞大,并且混合了调度、冲突处理、日志记录和预览更新等逻辑;建议拆分成更小、更聚焦的 helpers(例如:计算到期条目、更新 NextRunAt、处理失败等),以便让控制流更容易理解和维护。
给 AI Agents 的提示词
Please address the comments from this code review:

## Overall Comments
- TaskManager 和 Config 都在跟踪 running_cycle_queue_ids,但更新逻辑分散在多个地方;建议把这块状态管理集中起来(例如把队列运行的相关簿记封装成一个单独的 helper),以避免两处状态之间出现细微且难以排查的不一致。
- Task._run_cycle_loop 中与 cycle-run 相关的路径已经变得非常庞大,并且混合了调度、冲突处理、日志记录和预览更新等逻辑;建议拆分成更小、更聚焦的 helpers(例如:计算到期条目、更新 NextRunAt、处理失败等),以便让控制流更容易理解和维护。

## Individual Comments

### Comment 1
<location path="frontend/src/views/scheduler/SchedulerTaskControl.vue" line_range="172-173" />
<code_context>
 // 模式选项
 const modeOptions = TASK_MODE_OPTIONS

+const isQueueOption = (option?: ComboBoxItem | null) => {
+  return Boolean(option?.label?.startsWith('队列 - '))
+}
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 使用 label 前缀启发式来识别队列任务比较脆弱;可以考虑使用显式标记或约定的 value 模式。

`isQueueOption` 目前完全依赖 `"队列 - "` 这个 label 前缀来推断队列选项,而这个结果同时影响 cycle 模式过滤以及是否显示“恢复脚本”下拉框。把逻辑耦合到用户可见的文案上比较危险(本地化、文案调整或重命名都会在没有任何提示的情况下改变行为)。

更推荐使用更稳定的信号,例如在 option 上增加一个显式字段(`kind: 'queue' | 'script'`),或使用 value 的某个稳定特征(例如属于 `QueueConfig`)。如果暂时无法调整 API,至少可以把这一假设集中到一个地方并清晰注释,以降低未来修改 label 文案时误伤这段逻辑的风险。

Suggested implementation:

```
 // 本地状态,用于双向绑定
const localSelectedTaskId = ref(props.selectedTaskId)
const localSelectedMode = ref(props.selectedMode)
// 模式选项
const modeOptions = TASK_MODE_OPTIONS

// 队列任务识别相关:优先使用稳定信号,其次才回退到 label 前缀的启发式
// - 推荐:在 ComboBoxItem 上增加 `kind: 'queue' | 'script' | ...` 字段
// - 备选:统一使用 `value` 前缀(例如 `queue:`)标识队列任务
// - 最后:为了兼容旧数据,保留对「队列 - 」label 前缀的回退逻辑
const QUEUE_LABEL_PREFIX = '队列 - '

const isQueueOption = (option?: ComboBoxItem | null) => {
  if (!option) return false

  // 1. 显式类型标记(推荐方式)
  if ((option as any).kind === 'queue') return true

  // 2. value 约定前缀(例如后端约定队列任务值以 `queue:` 开头)
  if (typeof (option as any).value === 'string' && (option as any).value.startsWith('queue:')) {
    return true
  }

  // 3. 兼容旧逻辑:仅在上述信号都不存在时,才使用 label 前缀启发式
  return Boolean(option.label?.startsWith(QUEUE_LABEL_PREFIX))
}

interface Props {

```

1. **如果还没有显式标记:** 在构造 `ComboBoxItem` 的地方(通常是任务列表、队列配置映射处),为队列任务项补充 `kind: 'queue'` 字段,并/或约定队列任务使用 `value` 前缀(如 `queue:${id}`),这样 `isQueueOption` 将依赖这些稳定信号而不是 label 前缀。
2. **全局复用:** 如果其它组件也需要识别队列任务,可以将 `QUEUE_LABEL_PREFIX``isQueueOption` 抽到一个共享的 util(例如 `@/views/scheduler/utils/taskOption.ts`),并在本组件中按约定路径导入,以消除重复逻辑。
</issue_to_address>

Sourcery 对开源项目免费使用——如果你觉得我们的评审对你有帮助,欢迎分享 ✨
帮我变得更有用!请对每条评论点 👍 或 👎,我会根据这些反馈改进后续的代码评审。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • TaskManager and Config both track running_cycle_queue_ids, but updates are split across several places; consider centralizing this state management (e.g., encapsulating queue-running bookkeeping in a single helper) to avoid subtle inconsistencies between the two sets.
  • The cycle-run path in Task._run_cycle_loop has grown quite large and mixes scheduling, conflict handling, logging, and preview updates; consider breaking it into smaller, focused helpers (e.g. for computing due entries, updating NextRunAt, and handling failures) to make the control flow easier to reason about and maintain.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- TaskManager and Config both track running_cycle_queue_ids, but updates are split across several places; consider centralizing this state management (e.g., encapsulating queue-running bookkeeping in a single helper) to avoid subtle inconsistencies between the two sets.
- The cycle-run path in Task._run_cycle_loop has grown quite large and mixes scheduling, conflict handling, logging, and preview updates; consider breaking it into smaller, focused helpers (e.g. for computing due entries, updating NextRunAt, and handling failures) to make the control flow easier to reason about and maintain.

## Individual Comments

### Comment 1
<location path="frontend/src/views/scheduler/SchedulerTaskControl.vue" line_range="172-173" />
<code_context>
 // 模式选项
 const modeOptions = TASK_MODE_OPTIONS

+const isQueueOption = (option?: ComboBoxItem | null) => {
+  return Boolean(option?.label?.startsWith('队列 - '))
+}
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Using label prefix heuristics to detect queue tasks is brittle; consider an explicit flag or value pattern.

`isQueueOption` currently infers queue options solely from the `"队列 - "` label prefix, and that result drives both cycle-mode filtering and whether the resume-script select is shown. This coupling to user-visible text is fragile (localization, copy changes, or renames will silently change behavior).

Prefer a more stable signal, e.g. an explicit field on the option (`kind: 'queue' | 'script'`) or a reliable property of the value (e.g. membership in `QueueConfig`). If the API can’t change yet, at least centralize and clearly document this assumption in one place to reduce the risk of future label refactors breaking this logic.

Suggested implementation:

```
 // 本地状态,用于双向绑定
const localSelectedTaskId = ref(props.selectedTaskId)
const localSelectedMode = ref(props.selectedMode)
// 模式选项
const modeOptions = TASK_MODE_OPTIONS

// 队列任务识别相关:优先使用稳定信号,其次才回退到 label 前缀的启发式
// - 推荐:在 ComboBoxItem 上增加 `kind: 'queue' | 'script' | ...` 字段
// - 备选:统一使用 `value` 前缀(例如 `queue:`)标识队列任务
// - 最后:为了兼容旧数据,保留对「队列 - 」label 前缀的回退逻辑
const QUEUE_LABEL_PREFIX = '队列 - '

const isQueueOption = (option?: ComboBoxItem | null) => {
  if (!option) return false

  // 1. 显式类型标记(推荐方式)
  if ((option as any).kind === 'queue') return true

  // 2. value 约定前缀(例如后端约定队列任务值以 `queue:` 开头)
  if (typeof (option as any).value === 'string' && (option as any).value.startsWith('queue:')) {
    return true
  }

  // 3. 兼容旧逻辑:仅在上述信号都不存在时,才使用 label 前缀启发式
  return Boolean(option.label?.startsWith(QUEUE_LABEL_PREFIX))
}

interface Props {

```

1. **如果还没有显式标记:** 在构造 `ComboBoxItem` 的地方(通常是任务列表、队列配置映射处),为队列任务项补充 `kind: 'queue'` 字段,并/或约定队列任务使用 `value` 前缀(如 `queue:${id}`),这样 `isQueueOption` 将依赖这些稳定信号而不是 label 前缀。
2. **全局复用:** 如果其它组件也需要识别队列任务,可以将 `QUEUE_LABEL_PREFIX``isQueueOption` 抽到一个共享的 util(例如 `@/views/scheduler/utils/taskOption.ts`),并在本组件中按约定路径导入,以消除重复逻辑。
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread frontend/src/views/scheduler/SchedulerTaskControl.vue Outdated
@qiyinxi qiyinxi closed this Jul 2, 2026
@qiyinxi
qiyinxi deleted the feat/circle-mode-pr branch July 2, 2026 03:48
@qiyinxi
qiyinxi restored the feat/circle-mode-pr branch July 2, 2026 03:56
@qiyinxi qiyinxi reopened this Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant