@@ -44,8 +44,8 @@ type RaftNode interface {
4444 SendSnapshot (snap []byte ) error
4545 NeedSnapshot () bool
4646 Applied (index uint64 ) (entries uint64 , bytes uint64 )
47- TrackWrite (index uint64 )
48- WritePersisted (index uint64 )
47+ ApplyWritePending (index uint64 )
48+ ApplyWritePersisted (index uint64 )
4949 State () RaftState
5050 Size () (entries , bytes uint64 )
5151 Progress () (index , commit , applied uint64 )
@@ -1126,42 +1126,49 @@ func (n *raft) appliedLocked(index uint64) {
11261126 }
11271127}
11281128
1129- // TrackWrite signals writes need to happen for the specified index.
1130- // Applied can still be called, but will not move up until WritePersisted
1131- // is called, signaling writes were persisted.
1132- func (n * raft ) TrackWrite (index uint64 ) {
1129+ // ApplyWritePending signals writes need to happen for the specified index,
1130+ // i.e. writes are done asynchronously and might take some time for them to hit the disk.
1131+ // Applied can still be called after ApplyWritePending if there are any async writes.
1132+ // But applied will not move up until ApplyWritePersisted is called, signaling writes
1133+ // were persisted.
1134+ // If there are async writes ApplyWritePending MUST ALWAYS be called before Applied.
1135+ // This ensures Applied can be blocked from moving up until the writes are fully persisted.
1136+ // If ApplyWritePending is not called, for example when all writes are persisted by default,
1137+ // Applied will be able to freely move up.
1138+ func (n * raft ) ApplyWritePending (index uint64 ) {
11331139 n .Lock ()
11341140 defer n .Unlock ()
1135- n .trackWritesLocked (index , false )
1141+ n .applyWritesLocked (index , false )
11361142}
11371143
1138- // WritePersisted signals all writes up to and including the index were persisted.
1139- // Applied automatically moves up if it was called in the meantime.
1140- func (n * raft ) WritePersisted (index uint64 ) {
1144+ // ApplyWritePersisted signals all writes up to and including the index were persisted,
1145+ // this can be called either before Applied or after as long as the writes were persisted.
1146+ // ApplyWritePending MUST be called before this for every index that requires persisting.
1147+ // Applied will have been called in the meantime, and it will be moved up either:
1148+ // - up to the point where we're waiting for other writes to be persisted
1149+ // - or all writes are persisted, and it can fully move up.
1150+ func (n * raft ) ApplyWritePersisted (index uint64 ) {
11411151 n .Lock ()
11421152 defer n .Unlock ()
1143- n .trackWritesLocked (index , true )
1153+ n .applyWritesLocked (index , true )
11441154}
11451155
1146- // trackWritesLocked keeps track of pending and persisted writes.
1147- func (n * raft ) trackWritesLocked (index uint64 , persisted bool ) {
1156+ // applyWritesLocked keeps track of pending and persisted writes.
1157+ func (n * raft ) applyWritesLocked (index uint64 , persisted bool ) {
11481158 if persisted {
11491159 // Persisted moves the floor up.
1160+ // This indicates all writes up to and including this floor were persisted.
11501161 n .persistFloor = max (n .persistFloor , index )
1151- } else if n .persistFloor > 0 {
1152- // Track the lowest to-be-persisted index.
1153- n .persistFloor = min (n .persistFloor , index )
1154- } else {
1162+ n .persistFloorApplied = true
1163+ } else if n .persistFloor == 0 {
11551164 // Initializes if not set.
11561165 n .persistFloor = index
11571166 }
11581167 // Track the highest observed pending write.
11591168 n .persistHigh = max (n .persistHigh , index )
1160- // Track whether the floor was persisted.
1161- n .persistFloorApplied = n .persistFloorApplied || persisted
11621169
11631170 if n .persistFloorApplied {
1164- // Move applied up partially .
1171+ // If the floor is persisted, we can move applied up if possible .
11651172 if n .persistFloor != n .persistHigh {
11661173 n .appliedLocked (min (n .persistFloor , n .pendingApplied ))
11671174 return
0 commit comments