discovery: fix ireturn on the shared cache reader · Entire
discovery: fix ireturn on the shared cache reader
e67d7e1→main·
toothbrush·1mo ago·2 files·+18 added/-13 removed
CI's golangci-lint flagged ireturn on the generic readCacheFile, which
returned its type parameter T. (Locally the nolint directive that
silenced it kept getting stripped by golangci-lint run --fix's
nolintlint autofix, so it only surfaced in CI.)
Replace it with loadCacheFile(path, *T, newEmpty) error: it fills a destination pointer and returns error, which ireturn allows, while still sharing the read/unmarshal/corrupt-reset logic across both caches.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
6d6f3baefcd9View transcript
Changes
2
internal/entireclient/discovery
Mcache.go+15/-12
Mcluster_cores.go+3/-1
70 unmodified lines
71
72
73
74
74
75
76
77
78
79
49 unmodified lines
129
130
131
130
131
132
133
132
133
134
135
136
137
138
139
140
136
137
141
142
139
143
141
144
145
143
144
146
147
148
146
149
150
151
152
70 unmodified lines
}
func readCacheNoLock(path string) (ClusterCache, error) {
return readCacheFile(path, func() ClusterCache { return make(ClusterCache) })
cache := make(ClusterCache)
err := loadCacheFile(path, &cache, func() ClusterCache { return make(ClusterCache) })
return cache, err
}
func writeCacheNoLock(path string, cache ClusterCache) error {
49 unmodified lines
return func() { _ = fl.Unlock() }, nil //nolint:errcheck // unlock failure is non-fatal
}
// readCacheFile reads and unmarshals a JSON cache file. A missing file or a
// corrupt one both yield a fresh empty value (newEmpty), so a damaged cache
// self-heals on the next write instead of wedging callers.
func readCacheFile[T any](path string, newEmpty func() T) (T, error) {
// loadCacheFile reads path and unmarshals it into dst. A missing file leaves
// dst at its caller-initialized (empty) value; a corrupt file resets dst via
// newEmpty so a damaged cache self-heals on the next write instead of wedging
// callers. Returns an error only on a genuine read failure. Returning error
// (rather than the cache value itself) keeps this generic helper off the
// ireturn linter while still sharing the read/unmarshal logic across caches.
func loadCacheFile[T any](path string, dst *T, newEmpty func() T) error {
data, exists, err := readCacheBytes(path)
if err != nil {
var zero T
return zero, err
}
c := newEmpty()
if !exists {
return c, nil
}
if err := json.Unmarshal(data, &c); err != nil {
return newEmpty(), nil //nolint:nilerr // intentional: treat corrupt cache as empty
}
if json.Unmarshal(data, dst) != nil {
*dst = newEmpty() // corrupt → start fresh
}
return c, nil
}
// writeCacheFile marshals v and writes it atomically (tmp + rename).
Minternal/entireclient/discovery/cache.go+15/-12
48 unmodified lines
}
func readClusterCoresNoLock(path string) (ClusterCoresCache, error) { return readCacheFile(path, func() ClusterCoresCache { return make(ClusterCoresCache) }) cache := make(ClusterCoresCache) err := loadCacheFile(path, &cache, func() ClusterCoresCache { return make(ClusterCoresCache) }) return cache, err }
func writeClusterCoresNoLock(path string, cache ClusterCoresCache) error {