Red phase for #51: covers strict cache_max_bytes parsing (invalid explicit values abort naming key and value), the computed default of max(75% of free space, 500 MiB) via an injectable free-space probe, explicit-value-no-floor, zero-disables-cache, size accounting over source blobs and variants, LRU eviction under the limit, the multi-referenced blob case, write-pressure and periodic eviction triggers, and startup reconciliation. Minimal API skeletons keep the tree compiling and lint-clean; only the new tests fail.
61 lines
2.1 KiB
Go
61 lines
2.1 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"path/filepath"
|
|
"syscall"
|
|
)
|
|
|
|
// DefaultCacheMaxBytesFloor is the minimum computed default for the
|
|
// cache_max_bytes setting: 500 MiB. The floor applies only to the
|
|
// computed default (when the key is omitted from the configuration),
|
|
// never to explicitly configured values.
|
|
const DefaultCacheMaxBytesFloor int64 = 524288000
|
|
|
|
// FreeSpaceProbeFunc reports the number of free bytes available on the
|
|
// filesystem containing path. It is a function type so tests can
|
|
// inject a fake probe instead of depending on the host disk.
|
|
type FreeSpaceProbeFunc func(path string) (uint64, error)
|
|
|
|
// defaultFreeSpaceProbe reports free filesystem bytes via statfs on
|
|
// the given path, as available to unprivileged processes.
|
|
func defaultFreeSpaceProbe(path string) (uint64, error) {
|
|
var stat syscall.Statfs_t
|
|
if err := syscall.Statfs(path, &stat); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if stat.Bsize < 0 {
|
|
return 0, fmt.Errorf("statfs reported negative block size %d for %q", stat.Bsize, path)
|
|
}
|
|
|
|
blockSize := uint64(stat.Bsize) //nolint:gosec // G115: negative Bsize rejected above
|
|
|
|
return stat.Bavail * blockSize, nil
|
|
}
|
|
|
|
// ComputeDefaultCacheMaxBytes returns the default cache size limit for
|
|
// the filesystem containing cacheDir: 75% of the free bytes reported
|
|
// by probe, with a floor of DefaultCacheMaxBytesFloor.
|
|
func ComputeDefaultCacheMaxBytes(_ string, _ FreeSpaceProbeFunc) (int64, error) {
|
|
// Red phase: implementation follows the failing tests.
|
|
return 0, nil
|
|
}
|
|
|
|
// resolveCacheMaxBytes finalizes CacheMaxBytes after state_dir
|
|
// validation: an explicitly configured value is kept as-is (no floor
|
|
// applies), while an omitted key receives the computed default based
|
|
// on free space in <state_dir>/cache/. The effective limit is logged.
|
|
func (c *Config) resolveCacheMaxBytes(log *slog.Logger, probe FreeSpaceProbeFunc) error {
|
|
// Red phase: implementation follows the failing tests.
|
|
limit, err := ComputeDefaultCacheMaxBytes(filepath.Join(c.StateDir, "cache"), probe)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Debug("cache size limit resolution not implemented", "computed", limit)
|
|
|
|
return nil
|
|
}
|