Skip to content

fix: bind reclaim deletion threshold as a timestamp, stop swallowing binding errors - #132

Merged
geored merged 1 commit into
masterfrom
fix/reclaim-timestamp-binding
Sep 9, 2026
Merged

fix: bind reclaim deletion threshold as a timestamp, stop swallowing binding errors#132
geored merged 1 commit into
masterfrom
fix/reclaim-timestamp-binding

Conversation

@geored

@geored geored commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

listOrphanedFiles() has returned an empty list since #130 was merged, so gc() reclaims nothing. Four tests have failed on master ever since. This restores gc and makes the failure mode loud.

What broke

#130 moved the reclaim query from a simple statement to a prepared statement.

A simple statement carries no column type information, so binding the cutoff as a long worked — a long and a CQL timestamp share the same 8-byte wire format. The original code documented this:

// timestamp data type is encoded as the number of milliseconds since epoch

#130 removed that comment and switched to a prepared statement, which does know the column type and rejects the Long:

Failed to query reclaim partition 0: Codec not found for requested operation: [timestamp <-> java.lang.Long]
... all 24 partitions, on every call
List orphaned files, cur: ..., limit: 100, size: 0

#130 also wrapped each partition query in catch (Exception e) with a WARN carrying only e.getMessage(). All 24 partitions threw, all 24 were swallowed, and the method returned an empty list. Surefire redirects test output to a file, so the warning never reached the CI console — the build just showed four assertion failures with no visible cause.

Failing tests on master

GcTest.gcTest:41                       expected:<1> but was:<0>
SimpleIOTest.gc:363                    Expected: <false> but: was <true>
ChecksumDedupeTest.checksumDupe:67     Expected: <1> but: was <2>
ChecksumDedupeTest.checksumDelete:127  Expected: <1> but: was <3>

Tests run: 45, Failures: 4, Errors: 0, Skipped: 2

All four are the same defect: gc finds no orphans, so physical files are never deleted.

The fix

Bind the threshold as a Date, and restore the comment explaining why the long was previously safe.

Split the catch as well:

  • A CodecNotFoundException or InvalidTypeException is a defect that affects every partition. Rethrow it — swallowing it disables gc silently and lets reclaimable storage grow without bound.
  • Any other DriverException on a single partition is still tolerated, since the next gc run retries it, but it now logs at ERROR with the stack trace rather than a WARN with only the message.

Verification

Full suite, JDK 11, mvn -B -V clean install -Prun-its -Pci:

Tests run: 45, Failures: 0, Errors: 0, Skipped: 2
BUILD SUCCESS

Codec not found no longer appears anywhere in the surefire reports, and listOrphanedFiles now returns real results (size: 1, size: 2) where every call previously returned size: 0.

Impact

Not in any release. The newest tag is path-mapped-3.2 (March 30), and #130 landed on master after it, so only 3.3-SNAPSHOT consumers are affected. Anything tracking the snapshot has had no working gc since 2026-06-24 and will have accumulated unreclaimed storage.

Backward compatibility

No schema, API or data migration changes.

…binding errors

listOrphanedFiles() has returned an empty list since #130, so gc() reclaims
nothing.

#130 moved the reclaim query from a simple statement to a prepared statement.
A simple statement carries no column type information, so passing the cutoff
as a long worked: a long and a CQL timestamp share the same 8-byte wire
format. A prepared statement knows the column type and rejects it with
"Codec not found for requested operation: [timestamp <-> java.lang.Long]".

#130 also wrapped each partition query in catch (Exception e) with a WARN, so
all 24 partitions failed, all 24 were swallowed, and the method returned an
empty list on every call. Four tests have failed on master since then:
GcTest.gcTest, SimpleIOTest.gc, ChecksumDedupeTest.checksumDupe and
ChecksumDedupeTest.checksumDelete.

Bind the threshold as a Date, and restore the comment #130 removed that
explained why the long was previously safe.

Split the catch as well. A codec or type error is a defect that affects every
partition, so rethrow it rather than log it. A driver fault on a single
partition is still tolerated, because the next gc run retries it, but it now
logs at ERROR with the stack trace instead of a WARN carrying only the
message. The blanket catch is why this went unnoticed for eleven weeks.
@geored
geored merged commit c930ade into master Sep 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants