November 26, 2017·4 min read·engineeringcassandrarepairmetadata

Reaper 1.0.1 records repair starts before notifications arrive

Missing JMX start notifications could leave repair segments with inconsistent timestamps. Reaper 1.0.1 changes when it records the start and reruns a metadata correction for existing records.

A repair service needs to distinguish starting work from hearing that the work started. Reaper 1.0.1 moves its segment start timestamp to the point where it triggers repair. Previously, it relied on a later JMX notification, which the commit message says does not always arrive. That could leave a segment with an end time but no start time.

The 26 November release includes the timestamp correction, a migration for existing metadata, and a fix for parsing Elassandra gossip output. The timestamp work is a small example of a larger coordination problem. An external controller must maintain its own coherent state while receiving incomplete information about work another system performs.

I find repair orchestration relevant to Cassandra's appeal for distributed systems. Moving maintenance into a service does not remove the need to understand its recovery behavior. A missing notification should have a defined effect on the service's metadata, especially when that metadata is needed to continue operating.

Record the event the controller can establish

The timestamp commit explains the change directly. Setting startTime when repair is triggered gives the controller a definite point at which to record it. Waiting for a notification that the repair started introduces a dependency on delivery of that notification.

In the release comparison, the resulting implementation stores the coordinator host and DateTime.now() in the segment record inside processTriggeredSegment. The notification handlers still update the segment to RUNNING. They no longer supply the start timestamp as part of that state update.

This changes the meaning of the recorded time slightly. It describes the controller's triggering point, rather than the later receipt of a start notification. That is an operationally useful distinction because a duration computed from this timestamp includes the interval after triggering. The source does not establish a bound on that interval, so it should not be interpreted as an exact measure of time spent executing inside Cassandra.

The correction preserves an explicit invariant in the segment model. The comparison shows a precondition stating that startTime must be set when the segment is RUNNING or DONE. An end time without a start time is therefore more than an incomplete display field. It conflicts with the state the model expects to reconstruct and use.

One commit in the comparison temporarily removed precondition checks that broke Reaper when timestamps were inconsistent. Another reverted that removal. The final release instead changes the producer of the timestamp and includes a correction for existing records. That sequence explains the implementation without treating relaxed validation as the finished repair.

Existing records need a separate correction

Changing when future segments receive their start time does not populate fields in segments already stored. The release therefore duplicates the earlier migration under a new migration number. Its migration commit explicitly says the script must run again to fix missing repair-segment start times.

The new Migration011 delegates to Migration009. Its comment describes correcting segment start and end times in the repair-run table. Reusing the implementation under a later migration number gives installations that already passed the earlier migration another opportunity to apply the correction.

This is an important distinction in stateful software maintenance. The new execution path prevents a known route to inconsistent records. A database migration addresses records that path already produced. Shipping only the execution change would leave the model's preconditions relevant to old metadata that had not been corrected.

I regard the combined change as more informative than a general statement that timestamps are fixed. It identifies where the missing value came from and why a migration accompanies the runtime change. The service has to account for both newly triggered work and the persistent history it reads after an upgrade.

Gossip parsing must preserve embedded slashes

The release's Elassandra parser correction addresses a different boundary assumption. Previously, the code split endpoint-state text at every slash. The new regular expression avoids splitting a slash immediately preceded by an ASCII letter, digit, or space.

The added test includes an X2 gossip field whose value contains an identifier followed by /15. That slash belongs inside the field value. Treating it as an endpoint separator divides one node's state at the wrong position, so later parsing receives fragments that do not represent whole endpoints.

The test supplies three endpoints and checks their placement under a datacenter and rack, together with endpoint addresses and statuses. It also checks fields such as host identifier, release version, and load. These assertions tie the parser correction to the information Reaper displays about nodes, without implying any change to Cassandra's gossip protocol.

Both corrections concern the service's interpretation of external events or text. Triggering repair provides a timestamp independently of a potentially missing notification. Preserving an embedded slash lets the parser retain the endpoint record it actually received. Existing repair metadata receives its own migration so that the stricter segment-state checks can operate on coherent stored records.