diff --git a/.auto/log.jsonl b/.auto/log.jsonl index b1df4fd6..c5d008d7 100644 --- a/.auto/log.jsonl +++ b/.auto/log.jsonl @@ -6,3 +6,4 @@ {"run":5,"commit":"d0414b4","metric":45,"metrics":{"golint_canonicalheader":0,"golint_errname":1,"golint_errorlint":12,"golint_forcetypeassert":3,"golint_gosec":0,"golint_intrange":3,"golint_modernize":5,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":3,"golint_recvcheck":7,"golint_usestdlibvars":0,"golint_wastedassign":7,"golint_total":44,"eslint_problems":1,"eslint_errors":0,"eslint_warnings":1,"tsc_errors":0,"measure_s":38},"status":"keep","description":"canonicalheader 8→0 + usestdlibvars 3→0:header key 改为 Go 规范大小写(wire 格式本就如此,纯代码修正)、HTTP 方法常量替代字符串字面量。","timestamp":1786873098921,"segment":0,"confidence":2.1724137931034484,"asi":{"hypothesis":"canonicalheader+usestdlibvars --fix:Header key 统一规范大小写、GET/OPTIONS 等方法常量","insight":"GitHub header 修正前后的 wire 格式完全一致(Go 在 Set 时本来就会规范化),纯代码层面修正,零行为风险;下次遇到同类 100% 安全","next_action_hint":"剩余:errorlint(12) 需逐处人工判断(其中 3 处 err != context.Canceled、2 处 %v wrap、若干 ==/类型断言);recvcheck(7) 是模型接收者一致性;wastedassign(7) 删 TODO 赋值;intrange(3)/modernize(5)/nilnil(3)/prealloc(3)/forcetypeassert(3)/errname(1)/eslint(1)"}} {"run":6,"commit":"ce28f63","metric":38,"metrics":{"golint_canonicalheader":0,"golint_errname":1,"golint_errorlint":12,"golint_forcetypeassert":3,"golint_gosec":0,"golint_intrange":3,"golint_modernize":5,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":3,"golint_recvcheck":7,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":37,"eslint_problems":1,"eslint_errors":0,"eslint_warnings":1,"tsc_errors":0,"measure_s":47},"status":"keep","description":"wastedassign 7→0:删除 7 处死初始化(snapshot.go 三连、push 三件套 content、format.go numStr),改 var 声明,零行为变化。","timestamp":1786873485497,"segment":0,"confidence":2.978723404255319,"asi":{"hypothesis":"wastedassign 7→0:删除 7 处死初始化(x := \"\" 后所有分支都赋值)改为 var 声明","insight":"replace 工具会归一化 replacement_text 的前导空白;对需要缩进的编辑直接用 sed/gofmt -w 处理更稳","next_action_hint":"剩余:errorlint(12)、recvcheck(7)、modernize(5)、intrange(3)、nilnil(3)、prealloc(3)、forcetypeassert(3)、errname(1)、eslint(1)"}} {"run":7,"commit":"288b74d","metric":33,"metrics":{"golint_canonicalheader":0,"golint_errname":1,"golint_errorlint":12,"golint_forcetypeassert":3,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":3,"golint_recvcheck":7,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":32,"eslint_problems":1,"eslint_errors":0,"eslint_warnings":1,"tsc_errors":0,"measure_s":45},"status":"keep","description":"intrange 3→0 + modernize 5→3:for i:=0;i 0 { - var replicaDialectors []gorm.Dialector + var replicaDialectors = make([]gorm.Dialector, 0, len(dbConfig.Replicas)) for _, replica := range dbConfig.Replicas { username := replica.Username if username == "" { @@ -156,11 +159,12 @@ func initPostgres() { // newGORMTracingPlugin 构造数据库链路追踪插件。查询参数只保留占位符,避免凭据等绑定值进入 Span。 func newGORMTracingPlugin(attrs []attribute.KeyValue, extraOptions ...tracing.Option) gorm.Plugin { - options := []tracing.Option{ + options := make([]tracing.Option, 0, baseTracingOptionCount+len(extraOptions)) + options = append(options, tracing.WithoutMetrics(), tracing.WithoutQueryVariables(), tracing.WithAttributes(attrs...), - } + ) options = append(options, extraOptions...) return tracing.NewPlugin(options...) } diff --git a/pkg/cache/disk/cache.go b/pkg/cache/disk/cache.go index 2dbc0590..33758175 100644 --- a/pkg/cache/disk/cache.go +++ b/pkg/cache/disk/cache.go @@ -123,7 +123,10 @@ func (c *Cache) Set(key string, value []byte, ttl time.Duration) error { // Update memory tracker if elem, ok := c.items[key]; ok { - item := elem.Value.(*cacheItem) + item, ok := elem.Value.(*cacheItem) + if !ok { + return fmt.Errorf("cache: evict list entry for %q has invalid type %T", key, elem.Value) + } c.currentSize += size - item.size item.size = size item.expiredAt = expiredAt @@ -154,7 +157,11 @@ func (c *Cache) Get(key string) ([]byte, error) { return nil, ErrCacheMiss } - item := elem.Value.(*cacheItem) + item, ok := elem.Value.(*cacheItem) + if !ok { + c.mu.RUnlock() + return nil, ErrCacheMiss + } if !item.expiredAt.IsZero() && time.Now().After(item.expiredAt) { c.mu.RUnlock() return c.getAndDeleteIfExpired(key) @@ -204,7 +211,11 @@ func (c *Cache) getAndDeleteIfExpired(key string) ([]byte, error) { return nil, ErrCacheMiss } - item := elem.Value.(*cacheItem) + item, ok := elem.Value.(*cacheItem) + if !ok { + _ = c.deleteUnlocked(key) + return nil, ErrCacheMiss + } if !item.expiredAt.IsZero() && time.Now().After(item.expiredAt) { _ = c.deleteUnlocked(key) return nil, ErrCacheMiss @@ -234,8 +245,9 @@ func (c *Cache) Delete(key string) error { func (c *Cache) deleteUnlocked(key string) error { if elem, ok := c.items[key]; ok { - item := elem.Value.(*cacheItem) - c.currentSize -= item.size + if item, ok := elem.Value.(*cacheItem); ok { + c.currentSize -= item.size + } c.evictList.Remove(elem) delete(c.items, key) } @@ -288,7 +300,11 @@ func (c *Cache) evict() { for c.currentSize > c.maxSize && c.evictList.Len() > 0 { elem := c.evictList.Back() - item := elem.Value.(*cacheItem) + item, ok := elem.Value.(*cacheItem) + if !ok { + c.evictList.Remove(elem) + continue + } c.currentSize -= item.size c.evictList.Remove(elem) delete(c.items, item.key) @@ -380,7 +396,12 @@ func (c *Cache) cleanExpired() { now := time.Now() for key, elem := range c.items { - item := elem.Value.(*cacheItem) + item, ok := elem.Value.(*cacheItem) + if !ok { + c.evictList.Remove(elem) + delete(c.items, key) + continue + } if !item.expiredAt.IsZero() && now.After(item.expiredAt) { c.currentSize -= item.size c.evictList.Remove(elem)