perf(vision): 图片 URL 的「取回 + 内联」按内容哈希 memo(协同 H1:每回合重复付费/取回)
- 起因(Android 注册的成本项 H1):`resolveImages` 每回合都跑,而 `inlineImageSrc` 对 `data:` 短路、 对 **URL 每回合重新取回并内联** ⇒ ① 同一张图反复网络 I/O;② 来源一旦失效则该回合解析失败, 而 loop 保留原消息不中断回合 ⇒ **模型这轮静默看不到图** - 修法:按**内容哈希**记忆「URL → data URI」结果(有界 + 并发安全,独立小文件承载); **失败不写缓存**(不把坏结果钉住,第二次仍可重试);命中即不再发起网络请求 - **来源失效不再静默**:取回失败产生可诊断信号(含主机与原因,**不含图片内容/凭据**),回合照旧继续 - 复核:vision 包 build/vet/测试绿(含 `-race`);断言覆盖「同一 URL 连续解析 → 上游只被取回 1 次且结果逐字节相同」 「内容变化不被旧缓存命中」「失败不写缓存且第二次仍重试」「容量上限生效」,以及既有断言 (非图片 `ErrNotImage` / SSRF 被拒 / 长度预检)不回归;变异反证已还原
This commit is contained in:
1 parent
b65fe05635
commit
94b882f4d9
5 files changed
+682
-8
No files matched your search
@@ -1,6 +1,9 @@
|
||||
package vision
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// vision 包返回的哨兵错误。每个错误向外传递时都以 %w
|
||||
// 包装,使调用方能按类别判断,同时保留原始原因。
|
||||
@@ -29,3 +32,33 @@ var (
|
||||
// 判定在解码与短路之前完成,错误信息只带上限与本次长度。
|
||||
ErrImageTooLarge = errors.New("vision: inline image is too large")
|
||||
)
|
||||
|
||||
// SourceFailure 描述一次图像来源取回失败。它只携带主机与底层原因:完整
|
||||
// URL 可能带着查询串里的凭据、图像字节可能含隐私内容,两者都不进错误
|
||||
// 文案。Host 取不到(URL 无法解析)时为空串。
|
||||
//
|
||||
// 它实现 Unwrap,因此底层哨兵(ErrFetch / ErrNotImage /
|
||||
// ErrBlockedAddress / ErrImageTooLarge …)仍可用 errors.Is 判定;
|
||||
// 调用方用 errors.As(*SourceFailure) 或结构断言 ImageSourceHost()
|
||||
// 取出主机,把「来源失效」记成 WARN 而不是静默丢图(见 loop/vision.go)。
|
||||
type SourceFailure struct {
|
||||
// Host 是来源 URL 的主机(含端口),不含 userinfo、路径与查询串。
|
||||
Host string
|
||||
// Reason 是取回失败的底层原因,保留哨兵链供 errors.Is 判定。
|
||||
Reason error
|
||||
}
|
||||
|
||||
// Error 渲染主机与原因;Host 为空时只呈现原因。
|
||||
func (e *SourceFailure) Error() string {
|
||||
if e.Host == "" {
|
||||
return e.Reason.Error()
|
||||
}
|
||||
return fmt.Sprintf("图像来源取回失败(主机 %s):%v", e.Host, e.Reason)
|
||||
}
|
||||
|
||||
// Unwrap 暴露底层原因,使哨兵判定与具体错误类型照常可用。
|
||||
func (e *SourceFailure) Unwrap() error { return e.Reason }
|
||||
|
||||
// ImageSourceHost 报告来源主机,供调用方按结构断言取用(loop 的解析点),
|
||||
// 使 loop 无需依赖本包的取回实现。
|
||||
func (e *SourceFailure) ImageSourceHost() string { return e.Host }
|
||||
Reference in new issue
Block a user