filer: an unrepresentable remaining TTL means no volume TTL

The fallback capped the remainder at MaxInt32 seconds, which the volume
TTL grid encodes as 68 years - about 35 days shorter than the entry's
lifetime. For the narrow band nothing can round up within int32, store
the chunks without a volume TTL instead: they outlive the entry rather
than predecease it.
This commit is contained in:
Chris Lu
2026-08-10 18:42:18 -07:00
parent 10b64686ba
commit 35e9f84334
2 changed files with 12 additions and 9 deletions
+3 -1
View File
@@ -65,7 +65,9 @@ func roundUpToVolumeTTL(seconds int64) int32 {
return int32(count * unit)
}
}
return math.MaxInt32
// Nothing above ~68 years rounds up within int32; no volume TTL keeps the
// chunks past the entry, which is the safe direction.
return 0
}
// formatChunkSizeLimit mirrors the autoChunk maxMB resolution.
+9 -8
View File
@@ -23,23 +23,24 @@ func TestRoundUpToVolumeTTL(t *testing.T) {
{3601, 3660},
{255 * 60, 255 * 60},
{255*60 + 1, 5 * 3600}, // minutes overflow 255, ceil to hours
{20_000_000, 232 * 24 * 3600}, // ~231.5 days, ceil to days
{int64(math.MaxInt32), math.MaxInt32}, // beyond every unit's 255 cap
{20_000_000, 232 * 24 * 3600}, // ~231.5 days, ceil to days
{int64(math.MaxInt32), 0}, // beyond every unit's 255 cap: no TTL, never a shortened one
}
for _, test := range tests {
got := roundUpToVolumeTTL(test.seconds)
if got != test.want {
t.Fatalf("roundUpToVolumeTTL(%d) = %d, want %d", test.seconds, got, test.want)
}
if int64(got) < test.seconds && got != math.MaxInt32 {
if got == 0 {
continue // no volume TTL: chunks outlive the entry
}
if int64(got) < test.seconds {
t.Fatalf("roundUpToVolumeTTL(%d) = %d shortened the lifetime", test.seconds, got)
}
// the rounded value must survive the volume TTL string conversion intact
if got != math.MaxInt32 {
ttl, err := needle.ReadTTL(needle.SecondsToTTL(got))
if err != nil || int64(ttl.Minutes())*60 != int64(got) {
t.Fatalf("SecondsToTTL(%d) = %q does not round-trip (err %v)", got, needle.SecondsToTTL(got), err)
}
ttl, err := needle.ReadTTL(needle.SecondsToTTL(got))
if err != nil || int64(ttl.Minutes())*60 != int64(got) {
t.Fatalf("SecondsToTTL(%d) = %q does not round-trip (err %v)", got, needle.SecondsToTTL(got), err)
}
}
}