feat: TruncateFront & TruncateBack support truncating all entries #31
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Currently, it seems like there is no way to truncate entire log, which causes the duplicate transaction issue (#20).
This PR provides the ability of truncating all entries, by extending the index range 1 step further than the last(TruncateFront) or 1 step before the first(TruncateBack) entry.
For example, if the log has 3 entries
[10, 11, 12]
:TruncateFront(13)
will truncate all entries, and leftfirstIndex
as 13 andlastIndex
as 12.TruncateBack(9)
will truncate all entries, and leftfirstIndex
as 10 andlastIndex
as 9.Why this feature is needed
While I was working on a project that uses this package as WAL implementation, I've met the situation that described in #20. I can't simply mark all jobs as done if the program exits unexpectedly, and next time it starts, it will duplicate the last job. So I need a way to remove this last job from wal once it's done.
With this PR, I can call
TruncateFront(index + 1)
when I've poppedindex
th job from wal, and let the program wait for incomingindex + 1
th job.What's the difference between #29 and this PR
Thanks to @DStrand1 for providing a solution. However, #29 can't fulfill my requirements, by providing a
Clear
function.Complexity of usage
In my use case, I'm running a long-lived goroutine as a consumer(
Read
), and a gin server as producers(Write
).With
Clear
from #29, after the consumer finishes all jobs, it will first detect whether wal is empty (by either callingRead(index + 1)
withErrNotFound
returned, or checking a seperate counter), and then callClear
to remove all entries. The problem is that, these two steps are not atomic, so I have to add another lock to protect them which is complicated.With this PR, both
TruncateFront
andTruncateBack
hold internal lock, so they are atomic. And caller don't need to care about how many jobs left in wal, just callRead
andTruncateFront
in a loop untilRead
returnsErrNotFound
, then wait for incoming jobs.Corruption-safty
Clear
function in #29 isn't corruption-safe, like #29 (comment) pointed out.This PR modifies
TruncateFront
andTruncateBack
, following the original corruption-safe mechanism.Index continuity
#29 clears all entries, also resets
firstIndex
andlastIndex
to 1 and 0. BothWrite
andRead
have to reset its own index counter afterClear
.This PR keeps
firstIndex
andlastIndex
continuous,Write
andRead
can keep using previous index counter.