Skip to content

fix(chat): surface trigger_task dispatch failure + test env isolation - #17

Merged
2233admin merged 1 commit into
mainfrom
fix/chat-confirm-dispatch
Jul 18, 2026
Merged

fix(chat): surface trigger_task dispatch failure + test env isolation#17
2233admin merged 1 commit into
mainfrom
fix/chat-confirm-dispatch

Conversation

@2233admin

Copy link
Copy Markdown
Owner

What

  1. /chat/confirm trigger_task 吞错修复 — dispatch_collection 异常后仍回 applied=true 的静默失败改为 502 + task_id (任务行已提交, 提示去工作项重试); 成功响应带 executor dispatch 信息
  2. 测试环境隔离 — tests/conftest.py 在 backend import 前清 API_AUTH_TOKEN/AGENT_API_TOKEN; 此前部署 .env 配了 fleet token 会挂 19 个单测 (401)
  3. 新增 dispatch 失败回归测试
  4. 附 docs/BUG-TRIAGE-20260718.md 后端问题账本 (P0 identity 缺失 / P1 workflow importer 校验脱节等, 后续单独 PR)

Test

  • tests/integration/test_chat_api.py + tests/unit/test_workers_api.py: 21 passed (故意保留根 .env 的 token 跑, 验证隔离生效)
  • unit+skills 基线 1355 passed 不变

- /chat/confirm trigger_task: wrap dispatch_collection in try/except;
  dispatch failure after task commit now returns 502 with task_id instead
  of swallowing the error and reporting applied=true (F841 result unused)
- success response now includes executor dispatch info
- tests/conftest.py: clear API_AUTH_TOKEN/AGENT_API_TOKEN before backend
  import — deployment .env with fleet token was failing 19 unit tests (401)
- add dispatch-failure regression test

Triage ledger: docs/BUG-TRIAGE-20260718.md
@repowise-bot

repowise-bot Bot commented Jul 18, 2026

Copy link
Copy Markdown

✅ Health: 8.2

📋 At a glance
3 new findings introduced.

🚨 Change risk: 7.9/10 (high)
This change's risk is driven by:

  • more lines added than baseline
  • more scattered than baseline

📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-18 11:12 UTC
Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Chat task confirmations now report a clear error when task dispatch fails, prompting users to retry from work items.
    • Successful confirmations now include dispatch details in the response.
  • Tests

    • Added coverage for dispatch failure responses.
    • Improved test reliability by isolating authentication environment settings.

Walkthrough

The chat confirmation endpoint now surfaces task dispatch failures as HTTP 502 errors, successful responses include dispatch results, integration tests cover the failure path, test authentication variables are cleared, and a dated triage report documents related findings.

Changes

Chat dispatch and test reliability

Layer / File(s) Summary
Trigger-task dispatch error handling
backend/api/v1/chat.py
trigger_task dispatch failures now return HTTP 502 responses, while successful responses include the dispatch result.
Dispatch regression coverage and test isolation
tests/conftest.py, tests/integration/test_chat_api.py
Tests clear authentication environment variables before settings load and verify that executor dispatch failures are reported by the endpoint.
Bug triage findings and test baseline
docs/BUG-TRIAGE-20260718.md
The report records identity, workflow validation, chat dispatch, test isolation, tooling findings, and post-fix test results.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Poem

I’m a rabbit with a task in flight,
Dispatch errors now shine in sight.
Tests shed tokens, clean and bright,
Triage notes arrange the night,
Hop, hop—retries now feel right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: trigger_task dispatch failure handling and test environment isolation.
Description check ✅ Passed The description is directly related to the PR and describes the same fixes, tests, and docs update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request addresses several backend issues identified during bug triage. Specifically, it wraps the task dispatch call in backend/api/v1/chat.py with error handling to surface dispatch failures as 502 errors, adds a triage documentation file, isolates test environments from local .env configurations in tests/conftest.py, and introduces an integration test for dispatch failures. The review feedback recommends updating the task status to 'failed' in the database upon dispatch failure to prevent tasks from being permanently stuck in a 'pending' state, and suggests adding a corresponding assertion in the new integration test.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread backend/api/v1/chat.py
Comment on lines +439 to +445
except Exception as exc:
# Task row is already committed; surface the dispatch failure instead
# of reporting applied=True with a silently dead task.
logger.exception("chat confirm | trigger_task dispatch failed source=%s task=%s", source.id, task.id)
raise HTTPException(
status_code=502, detail=f"任务已创建但派发失败 (task_id={task.id}), 请到工作项里重试"
) from exc

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

当任务派发失败时,虽然 API 抛出了 502 异常,但由于 task 记录在前面已经通过 db.commit() 提交到了数据库,此时该任务在数据库中的状态仍然会保持为 pending。这会导致该任务在数据库和前端 UI 中永久处于“等待中”状态,给用户带来困惑。

建议在捕获到异常时,将 task.status 更新为 "failed" 并再次提交,以便准确反映任务的实际状态。

        except Exception as exc:
            # Task row is already committed; surface the dispatch failure instead
            # of reporting applied=True with a silently dead task.
            logger.exception("chat confirm | trigger_task dispatch failed source=%s task=%s", source.id, task.id)
            task.status = "failed"
            await db.commit()
            raise HTTPException(
                status_code=502, detail=f"任务已创建但派发失败 (task_id={task.id}), 请到工作项里重试"
            ) from exc

Comment on lines +170 to +171
assert response.status_code == 502
assert "派发失败" in response.json()["detail"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

为了确保在派发失败时,数据库中的任务状态确实被正确更新为了 "failed",建议在测试中增加对任务状态的断言。

Suggested change
assert response.status_code == 502
assert "派发失败" in response.json()["detail"]
assert response.status_code == 502
assert "派发失败" in response.json()["detail"]
from backend.models.task import CollectionTask
from sqlalchemy import select
stmt = select(CollectionTask).where(CollectionTask.source_id == source.id)
db_task = (await db_session.execute(stmt)).scalar_one()
assert db_task.status == "failed"

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/api/v1/chat.py`:
- Around line 437-438: The executor factory currently loses LocalExecutor state
and dispatch_collection does not retain spawned tasks. Cache get_executor so
repeated calls return the same LocalExecutor instance, and update
LocalExecutor.dispatch_collection to store each created asyncio task in an
instance-level tracking dictionary, removing it when it completes while
preserving existing dispatch and cancellation behavior.

In `@docs/BUG-TRIAGE-20260718.md`:
- Around line 26-28: Update the triage entry for chat confirm trigger_task to
mark the dispatch issue resolved and document the shipped behavior:
dispatch_collection failures are caught, the API returns HTTP 502 with the
committed task_id, and the prior unchecked-result/applied:true behavior no
longer applies.
- Around line 32-35: Update the “单测无 .env 隔离” finding and remediation text to
document both authentication variables, API_AUTH_TOKEN and AGENT_API_TOKEN.
State that the conftest autouse fixture clears both variables before backend
imports, while preserving the existing test-isolation context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f1c21d8e-b00f-4129-b0f6-8238e1970800

📥 Commits

Reviewing files that changed from the base of the PR and between 50f48c8 and be2e16b.

📒 Files selected for processing (4)
  • backend/api/v1/chat.py
  • docs/BUG-TRIAGE-20260718.md
  • tests/conftest.py
  • tests/integration/test_chat_api.py

Comment thread backend/api/v1/chat.py
Comment on lines +437 to +438
try:
dispatch = await get_executor().dispatch_collection(task.id, {})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

State loss and GC hazards in LocalExecutor.

While reviewing the get_executor().dispatch_collection() invocation, I noticed two critical concurrency and state issues in the LocalExecutor implementation provided in the context snippets:

  1. State loss in get_executor: get_executor() returns a new instance of LocalExecutor on every call. Because LocalExecutor relies on an instance-level _acquisition_tasks dictionary to track tasks, returning a new instance each time means previously dispatched tasks cannot be found or canceled later via cancel_acquisition.
  2. Task garbage collection hazard: LocalExecutor.dispatch_collection fires and forgets the collection task (t = asyncio.create_task(...)) without keeping a strong reference. The Python event loop only keeps weak references to tasks; this means active collection pipelines can be silently garbage-collected mid-execution when they yield to I/O.

Please consider applying @functools.lru_cache to get_executor in backend/executor/__init__.py to preserve the executor state, and updating LocalExecutor.dispatch_collection to track its spawned tasks in an instance dictionary (similar to _acquisition_tasks) to prevent them from vanishing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/api/v1/chat.py` around lines 437 - 438, The executor factory
currently loses LocalExecutor state and dispatch_collection does not retain
spawned tasks. Cache get_executor so repeated calls return the same
LocalExecutor instance, and update LocalExecutor.dispatch_collection to store
each created asyncio task in an instance-level tracking dictionary, removing it
when it completes while preserving existing dispatch and cancellation behavior.

Comment on lines +26 to +28
### 3. chat confirm `trigger_task` 吞掉派发失败
- `backend/api/v1/chat.py:437`: `result = await get_executor().dispatch_collection(task.id, {})` 结果未检查, 派发炸了 API 仍回 `applied: true`
- 修法: 检查 result / try-except 回 `applied: false` + 原因

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Mark the dispatch issue as resolved.

This entry still documents the pre-fix behavior (result unchecked and applied: true). The current implementation catches dispatch_collection failures and returns HTTP 502 with the committed task_id; update the triage record to reflect the shipped contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/BUG-TRIAGE-20260718.md` around lines 26 - 28, Update the triage entry
for chat confirm trigger_task to mark the dispatch issue resolved and document
the shipped behavior: dispatch_collection failures are caught, the API returns
HTTP 502 with the committed task_id, and the prior unchecked-result/applied:true
behavior no longer applies.

Comment on lines +32 to +35
### 4. 单测无 .env 隔离
- 根 `.env` 配了 `API_AUTH_TOKEN` (部署必需) 时, `tests/unit` 挂 19 个 (workers/nodes_install/geo 全是 401 或 token 注入断言)
- pydantic Settings 直读仓库根 `.env`; conftest 未清空鉴权相关 env
- 修法: conftest autouse fixture 强制 `API_AUTH_TOKEN=''`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document both authentication variables in test isolation.

The remediation currently names only API_AUTH_TOKEN, but this PR also clears AGENT_API_TOKEN before backend import. Update the finding and fix description to cover both variables.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/BUG-TRIAGE-20260718.md` around lines 32 - 35, Update the “单测无 .env 隔离”
finding and remediation text to document both authentication variables,
API_AUTH_TOKEN and AGENT_API_TOKEN. State that the conftest autouse fixture
clears both variables before backend imports, while preserving the existing
test-isolation context.

@2233admin
2233admin merged commit 8bbb02c into main Jul 18, 2026
5 checks passed
@2233admin
2233admin deleted the fix/chat-confirm-dispatch branch July 18, 2026 11:51
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