Problem
A failed splitSegment or mergeSegment leaves the segment unclaimable for a full minute, even though nothing was changed.
Both instructions mark the segment "do not re-claim for 60 seconds" as their first action, and clear that mark only on the path that actually rewrites the token. If the instruction fails earlier the mark is never cleared. The most common early failure is the ordinary one: another processor instance owns the segment's token, so fetching it throws UnableToClaimTokenException.
For a merge it is worse. Both halves are marked, so one half failing to be fetched strands both for the minute.
How to reproduce
- Run a
PooledStreamingEventProcessor and let it own a segment.
- Call
mergeSegment(0) while another instance holds the token for segment 1.
- The token fetch for segment 1 fails with
UnableToClaimTokenException, so the merge fails.
Both segment 0 and segment 1 are now in the coordinator's releasesDeadlines map with a deadline 60 seconds out. For the next minute the coordinator logs Segment N is still marked to not be claimed till [...] and claims neither, even after the other instance releases them.
Same shape for splitSegment(n) when the coordinator does not already hold the segment and fetchSegment fails.
Suspect
The block is installed unconditionally at the start of the instruction, but cleared only inside the last stage.
SplitTask.java:113 installs it; the clear at :143 is never reached when fetchSegment or WorkPackage.abort fails.
MergeTask.java:141 installs it per half; the clear at :177 is reached only when both halves' tokens resolve.
Related: the 60 seconds is a bare literal with an inline comment, not configurable and not scaled by anything.
Possible fix
Move each clear up to the point where every outcome of the instruction converges, attached to the whole chain rather than to the success branch, so a failed split or merge releases the block immediately.
The 60 seconds is then only reachable by a task whose future never completes, making it a watchdog rather than a routine delay. Worth naming it as a documented constant and saying so in the Javadoc at the same time.
One thing a reviewer should look at: releasesDeadlines.remove is unconditional, so a split or merge still clobbers a longer user-requested releaseUntil deadline on the same segment. That is unchanged by the suggested fix, since the put already clobbered it.
Problem
A failed
splitSegmentormergeSegmentleaves the segment unclaimable for a full minute, even though nothing was changed.Both instructions mark the segment "do not re-claim for 60 seconds" as their first action, and clear that mark only on the path that actually rewrites the token. If the instruction fails earlier the mark is never cleared. The most common early failure is the ordinary one: another processor instance owns the segment's token, so fetching it throws
UnableToClaimTokenException.For a merge it is worse. Both halves are marked, so one half failing to be fetched strands both for the minute.
How to reproduce
PooledStreamingEventProcessorand let it own a segment.mergeSegment(0)while another instance holds the token for segment 1.UnableToClaimTokenException, so the merge fails.Both segment 0 and segment 1 are now in the coordinator's
releasesDeadlinesmap with a deadline 60 seconds out. For the next minute the coordinator logsSegment N is still marked to not be claimed till [...]and claims neither, even after the other instance releases them.Same shape for
splitSegment(n)when the coordinator does not already hold the segment andfetchSegmentfails.Suspect
The block is installed unconditionally at the start of the instruction, but cleared only inside the last stage.
SplitTask.java:113installs it; the clear at:143is never reached whenfetchSegmentorWorkPackage.abortfails.MergeTask.java:141installs it per half; the clear at:177is reached only when both halves' tokens resolve.Related: the 60 seconds is a bare literal with an inline comment, not configurable and not scaled by anything.
Possible fix
Move each clear up to the point where every outcome of the instruction converges, attached to the whole chain rather than to the success branch, so a failed split or merge releases the block immediately.
The 60 seconds is then only reachable by a task whose future never completes, making it a watchdog rather than a routine delay. Worth naming it as a documented constant and saying so in the Javadoc at the same time.
One thing a reviewer should look at:
releasesDeadlines.removeis unconditional, so a split or merge still clobbers a longer user-requestedreleaseUntildeadline on the same segment. That is unchanged by the suggested fix, since theputalready clobbered it.