Skip to content

fix(log): 缓存链接失效时重新上传日志 - #1811

Open
ShiaNyaa wants to merge 4 commits into
sealdice:masterfrom
ShiaNyaa:fix/log-cache-url-validation
Open

ShiaNyaa wants to merge 4 commits into
sealdice:masterfrom
ShiaNyaa:fix/log-cache-url-validation

Conversation

@ShiaNyaa

@ShiaNyaa ShiaNyaa commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

背景

SealDice 会在日志内容没有变化时,直接复用本地数据库中保存的 upload_url,不再请求日志后端。

当日志后端启用滚动清理后,远端日志数据可能已经被删除,但 SealDice 本地仍保留原链接。此时用户执行 .log get 或从 UI 提取日志,仍会得到已经失效的链接。

Fixes #1563

修改内容

在复用缓存日志链接前增加远端存活校验:

  1. 从缓存链接中提取 key 和密码。
  2. 根据实际上传地址推导查询地址,只将末尾的 /log 替换为 /load_data,不写死路径前缀:
    • /dice/api/log/dice/api/load_data
    • /custom/path/log/custom/path/load_data
  3. 查询设置 3 秒总超时,并携带自定义后端的 Bearer Token。
  4. 根据查询结果处理:
    • 2xx:远端日志仍存在,继续复用缓存链接。
    • 404/410:远端日志已明确失效,重新上传并保存新链接。
    • 网络错误、超时或 5xx:无法确认链接状态,尝试重新上传。
    • 无法确认且重新上传也失败:明确提示新上传失败,同时返回可能仍然有效的旧链接。
    • 已明确失效且重新上传失败:正常返回上传失败,不再提供已知失效的链接。

该逻辑同时应用于 V1 和 V105 日志格式,因此 .log get 与 UI 日志提取会保持一致。

改动范围

  • 不修改数据库结构。
  • 不修改 UI。
  • 不修改日志后端协议。
  • 日志内容发生变化时,仍沿用原有的直接重新上传逻辑。

Sourcery 总结

确保在重复使用缓存的日志链接前对其进行验证,并在远程日志已过期时安全恢复。

错误修复:

  • 在重复使用前验证缓存的日志链接;当确认远程资源缺失或无法验证其可用性时,重新上传日志。
  • 对 V1 和 V105 日志格式一致地应用缓存链接恢复机制,包括在重新上传失败时提供明确的回退提示。

增强功能:

  • 根据自定义或默认的上传路径推导远程可用性检查端点,并添加身份验证和有界请求超时。

测试:

  • 增加对已过期缓存链接、不确定的探测和上传失败、端点推导、身份验证、状态处理以及格式错误的缓存 URL 的覆盖。
Original summary in English

Sourcery 总结

在复用缓存日志链接前确认其仍然有效,并在失效时安全恢复日志上传。

Bug 修复:

  • 在复用缓存日志链接前验证远端资源状态,发现链接失效时自动重新上传日志。
  • 统一修复 V1 和 V105 日志格式在缓存链接失效、探测不确定或重新上传失败时的处理,并避免返回已明确失效的链接。

功能增强:

  • 支持从默认或自定义日志上传路径推导可用性检查端点,并使用 Bearer Token 和 3 秒超时进行探测。

测试:

  • 增加对缓存链接失效、不确定状态回退、端点推导、鉴权、状态码处理和无效缓存 URL 的测试。
Original summary in English

Sourcery 摘要

在复用缓存日志链接前验证其有效性,并在失效或无法确认时安全地恢复日志上传。

错误修复:

  • 验证缓存日志链接的远端状态,并在链接明确失效时重新上传日志,避免返回已失效的链接。
  • 统一修复 V1 和 V105 日志格式在缓存链接失效、状态无法确认及重新上传失败时的处理。

改进:

  • 支持从默认或自定义日志后端路径推导存活检查端点,并使用 Bearer Token 和有限超时进行请求。

测试:

  • 增加对缓存链接状态探测、端点推导、鉴权、网络异常、上传失败回退及无效缓存 URL 的测试。
Original summary in English

Summary by Sourcery

在复用缓存日志链接前验证其有效性,并在失效或无法确认时安全地恢复日志上传。

Bug Fixes:

  • 验证缓存日志链接的远端状态,并在链接明确失效时重新上传日志,避免返回已失效的链接。
  • 统一修复 V1 和 V105 日志格式在缓存链接失效、状态无法确认及重新上传失败时的处理。

Enhancements:

  • 支持从默认或自定义日志后端路径推导存活检查端点,并使用 Bearer Token 和有限超时进行请求。

Tests:

  • 增加对缓存链接状态探测、端点推导、鉴权、网络异常、上传失败回退及无效缓存 URL 的测试。
Original summary in English

@sourcery-ai

sourcery-ai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

审查者指南

本 PR 为 V1 和 V105 日志上传增加缓存链接的远端存活校验:通过派生的 /load_data 查询接口确认链接状态,在失效或无法确认时重新上传,并在不确定且重传失败时安全地带提示回退到旧链接,同时补充了覆盖关键状态和请求构造的测试。

缓存日志 URL 校验与重新上传时序图

sequenceDiagram
    participant U as 日志请求方
    participant L as uploadV1_or_uploadV105
    participant DB as 本地数据库
    participant B as 日志后端

    U->>L: 上传(env)
    L->>DB: LogGetUploadInfo()
    DB-->>L: 缓存的 URL 和时间戳
    alt 缓存 URL 比日志更新
        L->>B: 使用 key、password、Range 和 Bearer token GET 派生的 /load_data
        alt 2xx 响应
            B-->>L: 日志存在
            L-->>U: 返回缓存 URL
        else 404 或 410
            B-->>L: 日志缺失
            L->>B: 上传日志
            alt 上传成功
                B-->>L: 新 URL
                L-->>U: 返回新 URL
            else 上传失败
                L-->>U: 返回上传错误,不返回过期 URL
            end
        else 网络错误、超时或 5xx
            B-->>L: 状态未知
            L->>B: 上传日志
            alt 上传成功
                B-->>L: 新 URL
                L-->>U: 返回新 URL
            else 上传失败
                L-->>U: 返回带警告的缓存 URL
            end
        end
    else 日志已更改或没有缓存 URL
        L->>B: 上传日志
        B-->>L: 新 URL 或上传失败
        L-->>U: 返回上传结果
    end
Loading

缓存日志 URL 探测决策流程图

flowchart TD
    A[缓存的上传 URL 比日志更新] --> B[提取 key 和 password]
    B --> C[从后端 /log 推导 /load_data]
    C --> D[使用 3 秒超时进行探测]
    D --> E{探测结果}
    E -->|2xx| F[复用缓存 URL]
    E -->|404 或 410| G[重新上传日志]
    E -->|网络错误、超时或 5xx| G
    G --> H{上传成功}
    H -->|是| I[保存并返回新 URL]
    H -->|否且状态明确缺失| J[返回上传失败]
    H -->|否且状态未知| K[返回带警告的缓存 URL]
Loading

文件级变更

变更 详细信息 文件
在复用缓存日志链接前增加远端存活探测,并根据探测结果决定复用、重新上传或回退。
  • 从缓存 URL 提取 key 和片段密码,并将配置后端路径末尾的 /log 转换为 /load_data。
  • 使用 3 秒超时发起带 Range 头的 GET 探测,并在配置 Token 时携带 Bearer Authorization。
  • 将 2xx、404/410、网络错误或 5xx 分别映射为存活、明确失效和未知状态。
  • 未知状态下重新上传失败时返回旧链接并附加可能仍有效的提示;明确失效时不返回旧链接。
dice/storylog/storylog.go
将缓存链接校验和失败回退逻辑接入 V1 与 V105 日志上传流程。
  • 仅在日志内容未更新且存在缓存链接时执行远端探测。
  • 存活链接继续直接复用,失效或无法确认时尝试重新上传。
  • 保持日志内容变化时的原有直接重新上传行为,并统一处理上传失败结果。
dice/storylog/upload_v1.go
dice/storylog/upload_v105.go
增加缓存链接失效、探测失败、路径推导和请求鉴权的自动化测试。
  • 验证 404 会触发重新上传并返回新链接。
  • 验证探测返回 5xx 且重新上传失败时会返回旧链接及明确提示。
  • 验证自定义后端路径、key、密码和 Bearer Token 的构造,以及各类 HTTP 状态和网络错误的分类。
dice/ext_log_upload_cache_test.go
dice/storylog/cache_validation_test.go

针对关联 Issue 的评估

Issue 目标 已解决 说明
#1563 当日志内容未更新但缓存的远程日志链接已失效时,能够自动重新上传日志并保存、返回新的链接。
#1563 在无法确认缓存链接状态或重新上传失败时,提供合理的降级处理和明确提示,避免在已明确失效时继续返回失效链接。
#1563 该强制重新上传/失效检测逻辑同时覆盖 V1 和 V105 日志格式,使命令行获取日志和 UI 提取日志行为一致。

提示和命令

与 Sourcery 交互

  • 触发新的审查: 在拉取请求中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub Issue: 回复审查评论,请 Sourcery 根据该评论创建 Issue。你也可以回复 @sourcery-ai issue,根据该评论创建 Issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title,随时重新生成标题。
  • 生成拉取请求摘要: 在拉取请求正文中任意位置写入 @sourcery-ai summary,即可在指定位置生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary,随时重新生成摘要。
  • 生成审查者指南: 在拉取请求中评论 @sourcery-ai guide,即可随时重新生成审查者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,此功能会很有用。
  • 忽略所有 Sourcery 审查: 在拉取请求中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。如果你想从新的审查开始,这一功能尤其有用——别忘了评论 @sourcery-ai review 以触发新的审查!

自定义使用体验

访问你的控制面板以:

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审查者指南等。
  • 更改审查语言。
  • 添加、移除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

本 PR 为 V1 和 V105 日志上传增加缓存链接的远端存活校验:通过派生的 /load_data 查询接口确认链接状态,在失效或无法确认时重新上传,并在不确定且重传失败时安全地带提示回退到旧链接,同时补充了覆盖关键状态和请求构造的测试。

Sequence diagram for cached log URL validation and re-upload

sequenceDiagram
    participant U as Log requester
    participant L as uploadV1_or_uploadV105
    participant DB as Local database
    participant B as Log backend

    U->>L: Upload(env)
    L->>DB: LogGetUploadInfo()
    DB-->>L: cached URL and timestamps
    alt Cached URL is newer than log
        L->>B: GET derived /load_data with key, password, Range, Bearer token
        alt 2xx response
            B-->>L: Log exists
            L-->>U: Return cached URL
        else 404 or 410
            B-->>L: Log missing
            L->>B: Upload log
            alt Upload succeeds
                B-->>L: New URL
                L-->>U: Return new URL
            else Upload fails
                L-->>U: Return upload error without stale URL
            end
        else Network error, timeout, or 5xx
            B-->>L: Unknown status
            L->>B: Upload log
            alt Upload succeeds
                B-->>L: New URL
                L-->>U: Return new URL
            else Upload fails
                L-->>U: Return cached URL with warning
            end
        end
    else Log changed or no cached URL
        L->>B: Upload log
        B-->>L: New URL or upload failure
        L-->>U: Return upload result
    end
Loading

Flow diagram for cached log URL probe decision

flowchart TD
    A[Cached upload URL is newer than log] --> B[Extract key and password]
    B --> C[Derive /load_data from backend /log]
    C --> D[Probe with 3-second timeout]
    D --> E{Probe result}
    E -->|2xx| F[Reuse cached URL]
    E -->|404 or 410| G[Re-upload log]
    E -->|Network error timeout or 5xx| G
    G --> H{Upload succeeds}
    H -->|Yes| I[Save and return new URL]
    H -->|No and status missing| J[Return upload failure]
    H -->|No and status unknown| K[Return cached URL with warning]
Loading

File-Level Changes

Change Details Files
在复用缓存日志链接前增加远端存活探测,并根据探测结果决定复用、重新上传或回退。
  • 从缓存 URL 提取 key 和片段密码,并将配置后端路径末尾的 /log 转换为 /load_data。
  • 使用 3 秒超时发起带 Range 头的 GET 探测,并在配置 Token 时携带 Bearer Authorization。
  • 将 2xx、404/410、网络错误或 5xx 分别映射为存活、明确失效和未知状态。
  • 未知状态下重新上传失败时返回旧链接并附加可能仍有效的提示;明确失效时不返回旧链接。
dice/storylog/storylog.go
将缓存链接校验和失败回退逻辑接入 V1 与 V105 日志上传流程。
  • 仅在日志内容未更新且存在缓存链接时执行远端探测。
  • 存活链接继续直接复用,失效或无法确认时尝试重新上传。
  • 保持日志内容变化时的原有直接重新上传行为,并统一处理上传失败结果。
dice/storylog/upload_v1.go
dice/storylog/upload_v105.go
增加缓存链接失效、探测失败、路径推导和请求鉴权的自动化测试。
  • 验证 404 会触发重新上传并返回新链接。
  • 验证探测返回 5xx 且重新上传失败时会返回旧链接及明确提示。
  • 验证自定义后端路径、key、密码和 Bearer Token 的构造,以及各类 HTTP 状态和网络错误的分类。
dice/ext_log_upload_cache_test.go
dice/storylog/cache_validation_test.go

Assessment against linked issues

Issue Objective Addressed Explanation
#1563 当日志内容未更新但缓存的远程日志链接已失效时,能够自动重新上传日志并保存、返回新的链接。
#1563 在无法确认缓存链接状态或重新上传失败时,提供合理的降级处理和明确提示,避免在已明确失效时继续返回失效链接。
#1563 该强制重新上传/失效检测逻辑同时覆盖 V1 和 V105 日志格式,使命令行获取日志和 UI 提取日志行为一致。

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

@sourcery-ai sourcery-ai Bot 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.

嘿——我发现了 1 个问题

给 AI Agent 的提示
请处理此次代码审查中的评论:

## 单独评论

### 评论 1
<location path="dice/storylog/upload_v1.go" line_range="79-82" />
<code_context>
 		env.Log.Errorf("记录Log上传信息失败: %v", errDB)
 	}
 	if len(url) == 0 {
+		if fallbackURL, notice, ok := fallbackToCachedLogURL(&env, cachedURL, probeResult); ok {
+			return fallbackURL, notice, nil
+		}
 		return "", env.Notice, errors.New("上传 log 到服务器失败,未能获取染色器链接")
 	}
 	return url, env.Notice, nil
</code_context>
<issue_to_address>
**问题(更广泛的影响):** 当缓存链接探测结果未知,且在 `LogGetAllLines``formatAndBackup`/`formatAndBackupV105` 或压缩/文件生成过程中为重新上传进行本地准备失败时,函数会在到达 `fallbackToCachedLogURL` 之前返回该错误;因此,它会丢弃可能仍然有效的缓存 URL,而不是带着不确定性提示返回该 URL。

**触发条件:** 当无法确认缓存 URL,且重新上传在调用后端上传接口之前失败时。

**建议修复:** 对探测结果未知时的所有重新上传失败,都通过 `fallbackToCachedLogURL` 处理;或者使用覆盖完整重新上传流程的延迟回退机制。
</issue_to_address>

Sourcery 评估

需要人工审查。 首先需要处理 1 个发现;当缓存 URL 的探测结果无法确定时,此更改会再次上传日志,并可能创建第二条存储在外部的日志记录;即使回滚此更改,也不会删除这次上传,不过其影响范围有限且可以修复。它还可能返回一个已经失效的缓存链接,这属于普通的运行时失败,而不是不可逆的数据或访问权限变更。

阻塞性发现:dice/storylog/upload_v1.go:82


Sourcery 对开源项目免费——如果您喜欢我们的审查结果,请考虑分享给他人 ✨
帮助我变得更有用!请在每条评论上点击 👍 或 👎,我会利用反馈来改进审查结果。
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="dice/storylog/upload_v1.go" line_range="79-82" />
<code_context>
 		env.Log.Errorf("记录Log上传信息失败: %v", errDB)
 	}
 	if len(url) == 0 {
+		if fallbackURL, notice, ok := fallbackToCachedLogURL(&env, cachedURL, probeResult); ok {
+			return fallbackURL, notice, nil
+		}
 		return "", env.Notice, errors.New("上传 log 到服务器失败,未能获取染色器链接")
 	}
 	return url, env.Notice, nil
</code_context>
<issue_to_address>
**issue (broader_impact):** When the cached-link probe is unknown and local preparation for re-upload fails in `LogGetAllLines`, `formatAndBackup`/`formatAndBackupV105`, or compression/file generation, the function returns that error before reaching `fallbackToCachedLogURL`; it therefore discards the potentially valid cached URL instead of returning it with an uncertainty notice.

**Triggers:** When the cached URL cannot be confirmed and the re-upload fails before the backend upload call.

**Suggested fix:** Route all re-upload failures after an unknown probe through `fallbackToCachedLogURL`, or use a deferred fallback covering the complete re-upload path.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and when probing the cached URL is inconclusive, this change uploads the log again and may create a second externally stored log record; reverting the change would not remove that upload, although the impact is bounded and repairable. It can also return a cached link that may no longer work, which is an ordinary runtime failure rather than an irreversible data or access change.

Blocking findings: dice/storylog/upload_v1.go:82


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 on lines +79 to 82
if fallbackURL, notice, ok := fallbackToCachedLogURL(&env, cachedURL, probeResult); ok {
return fallbackURL, notice, nil
}
return "", env.Notice, errors.New("上传 log 到服务器失败,未能获取染色器链接")

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.

问题(更广泛的影响): 当缓存链接探测结果未知,且在 LogGetAllLinesformatAndBackup/formatAndBackupV105 或压缩/文件生成过程中为重新上传进行本地准备失败时,函数会在到达 fallbackToCachedLogURL 之前返回该错误;因此,它会丢弃可能仍然有效的缓存 URL,而不是带着不确定性提示返回该 URL。

触发条件: 当无法确认缓存 URL,且重新上传在调用后端上传接口之前失败时。

建议修复: 对探测结果未知时的所有重新上传失败,都通过 fallbackToCachedLogURL 处理;或者使用覆盖完整重新上传流程的延迟回退机制。

Original comment in English

issue (broader_impact): When the cached-link probe is unknown and local preparation for re-upload fails in LogGetAllLines, formatAndBackup/formatAndBackupV105, or compression/file generation, the function returns that error before reaching fallbackToCachedLogURL; it therefore discards the potentially valid cached URL instead of returning it with an uncertainty notice.

Triggers: When the cached URL cannot be confirmed and the re-upload fails before the backend upload call.

Suggested fix: Route all re-upload failures after an unknown probe through fallbackToCachedLogURL, or use a deferred fallback covering the complete re-upload path.

@fy0

fy0 commented Sep 10, 2026

Copy link
Copy Markdown
Member

O 这个是用于第三方log站点的?官方的目前似乎还没有失效过

@ShiaNyaa

ShiaNyaa commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

O 这个是用于第三方log站点的?官方的目前似乎还没有失效过

是的,要求自建API永久化存储不现实。

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.

[功能请求]:需要一个无视日志最后更新时间强制重新上传或者生成本地文件的命令或按钮

3 participants