Skip to content

fix(knowledge): bubble embedding model resolution failure for retry - #2620

Open
mdrkrg wants to merge 7 commits into
Tencent:mainfrom
mdrkrg:fix/embedding-model-failure-retry
Open

fix(knowledge): bubble embedding model resolution failure for retry#2620
mdrkrg wants to merge 7 commits into
Tencent:mainfrom
mdrkrg:fix/embedding-model-failure-retry

Conversation

@mdrkrg

@mdrkrg mdrkrg commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Description

processChunks 在获取 embedding 模型失败时直接静默返回,ProcessDocument 因此将任务视为成功,knowledge 停留在 processing 状态

修复将错误向上传递:

  • asynq 会对瞬时性故障自动重试,在最后一次重试时把 knowledge 标记为失败
  • 没有重试机制的同步路径(processDocumentFromPassagetriggerManualProcessing 的 goroutine),在出错时立即标记失败

提取 markKnowledgeFailed / failKnowledgeRetryable 两个公共 helper,统一散落的失败标记逻辑

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📚 Documentation update
  • 🎨 Refactor
  • ⚡ Performance improvement
  • 🧪 Test
  • 🔧 Configuration / Build / CI

Related Issue

Testing

  • asynq 文档处理(文件导入 和 段落导入):embedding 模型解析失败时向上返回错误,触发 asynq 自动重试,非最终重试时 knowledge 保持 processing
  • asynq 文档处理:重试次数耗尽时 knowledge 被标记为 failed 并写入错误信息,不再卡在 processing
  • 手动重新解析 asynq 任务:失败返回错误触发重试,非最终重试时 knowledge 保持 processing
  • 手动重新解析:重试耗尽后标记 failed 并写入错误信息
  • 同步路径(无重试机制),失败时标记 failed 并写入错误信息
  • 异步 goroutine 路径,失败时在 goroutine 内标记 failed 并写入错误信息
  • knowledge 已被用户取消或正在删除时,跳过失败写入(状态与错误信息不覆盖)

Checklist

  • git diff --check origin/main...HEAD passes
  • Changed source files are formatted
  • Targeted tests for the changed packages/components pass
  • Diff-scoped lint passes where applicable (for Go: golangci-lint run --new-from-rev=origin/main ./...)
  • Full-repository checks were run, or any unrelated/environment-dependent failures are documented above
  • Self-reviewed the code
  • Added/updated tests covering the change
  • Updated related documentation (README, docs/, Swagger annotations, etc.)
  • Breaking changes are clearly called out in the description above

Screenshots / Recordings

mdrkrg added 5 commits August 9, 2026 08:58
processChunks silently returned when GetEmbeddingModel failed, leaving
the knowledge row stuck in "processing" with no retry or error message.
It now bubbles the error so asynq retries transient outages; only the
final attempt marks the row failed.
- Unify the repeated mark-failed and mark-on-last-retry blocks
- failKnowledge delegates to the helpers
markKnowledgeFailed now re-checks the row and skips the failed write
when it has been cancelled or is being deleted while the failing call
was in flight, so a late failure can't overwrite a newer user action.
- sync passage path (processDocumentFromPassage) marks failed immediately
- async triggerManualProcessing goroutine marks failed itself
- ProcessManualUpdate returns the error for retry and marks failed on the
  final attempt
- markKnowledgeFailed leaves a user-cancelled row alone

@jiahao6635 jiahao6635 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The main retry/final-state direction looks good, but the async manual-reparse path still has a context-lifetime hole.

triggerManualProcessing correctly detaches background work into newCtx, and processChunks(newCtx, ...) runs with it. On failure, however, the goroutine calls markKnowledgeFailed(ctx, ...) with the original request context. Once the move request returns or is cancelled, markKnowledgeFailed first calls isKnowledgeAborted through that cancelled context. A repository read can then return context canceled; isKnowledgeAborted deliberately treats any read error as deleting, so the terminal failed write is skipped and the row can remain stuck in processing/pending—the same class of state this PR is trying to remove.

I reproduced this with a repository fake that returns ctx.Err() from GetKnowledgeByID: the async regression times out on this head. Changing the call to s.markKnowledgeFailed(newCtx, knowledge, err.Error()) makes it pass. Please use the detached context for the whole goroutine failure path and add a cancelled-parent-context regression test.

Other validation I ran on this head: the focused embedding-failure tests, repeated service tests, the service package, and go vet passed; this is the only blocking finding from my review.

mdrkrg added 2 commits August 12, 2026 20:24
Pins the failure write surviving a cancelled parent request context.
The failure write used the cancelled request context, which made
isKnowledgeAborted skip it and left the row stuck in processing.
sakitam-fdd added a commit to sakitam-fdd/WeKnora that referenced this pull request Aug 21, 2026
Port Tencent#2620 latest HEAD into stability Wave 2. Includes the detached-context follow-up and cancelled-parent regression so async manual processing cannot remain stuck in processing after an embedding model resolution failure.
sakitam-fdd added a commit to sakitam-fdd/WeKnora that referenced this pull request Aug 21, 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.

2 participants