Releases: databendlabs/openraft
v0.9.20
Summary:
- Fixed:
- 33fde29d reset progress when heartbeat response indicates conflict.
Detail:
Fixed:
-
Fixed: 33fde29d reset progress when heartbeat response indicates conflict; by Zhang Yanpo; 2025-06-19
With
loosen-follower-log-revert
enabled:Before this fix,
RaftCore
ignoredconflict
messages fromHeartbeat
RPCs,
preventing leaders from discovering follower state changes. When a follower's
state reverted and responded with a conflict message, the leader wouldn't
retransmit necessary data to the follower.This commit ensures
conflict
responses are always processed properly and
progress is reset to trigger data retransmission to the follower.
v0.9.19
Summary:
- Improved:
- 9bfd517f tolerate leader state reversion upon restart.
Detail:
Improved:
-
Improved: 9bfd517f tolerate leader state reversion upon restart; by Zhang Yanpo; 2025-06-10
When a leader restarted and its log reverted, and tried to re-elect
itself as leader:And when vote request is rejected and see a greater vote,
it should only update to the non-committed version of the responded vote
to its local state:This prevents a dangerous scenario when state reversion is allowed:
- A node was a leader but its state reverted to a previous version;
- The node restarts and begins election;
- It receives a vote response containing its own previous leader vote;
- Without this protection, it would update to that committed vote and
become leader again; - However, it lacks the necessary logs, causing committed entries to be
lost or inconsistent;
By using the non-committed version, we prevent this reverted node from
becoming leader while still allowing proper vote updates for legitimate
cases.
v0.9.18
Summary:
- Fixed:
- 5ae1965b Remove
serde
feature detection fromdeclare_raft_types!
macro.
- 5ae1965b Remove
Detail:
Fixed:
-
Fixed: 5ae1965b Remove
serde
feature detection fromdeclare_raft_types!
macro; by 张炎泼; 2024-11-30The
[cfg_attr(feature = "serde")]
feature detection for
RaftTypeConfig
implementation should not be evaluated in application
crates when thedeclare_raft_types!
macro is called. This detection
logic should be removed from the macro and instead added to each type
that usesRaftTypeConfig
.
v0.9.17
Summary:
- Improved:
Detail:
Improved:
-
Improved: 536a435e Chunk read log entry and check range on startup; by 张炎泼; 2024-09-14
-
Implement chunk-based reading of committed log entries when
re-applying to state machine upon startup. -
Add validation for log entry indexes, to avoid applying wrong entries
to state machine.
-
-
Improved: dc18dc6f remove
Copy
bound fromNodeId
; by 张炎泼; 2024-10-14The
NodeId
type is currently defined as:type NodeId: .. + Copy + .. + 'static;
This commit removes the
Copy
bound fromNodeId
.
This modification will allow the use of non-Copy
types asNodeId
,
providing greater flexibility for applications that prefer
variable-length strings or other non-Copy
types for node
identification.This change maintain compatibility by updating derived
Copy
implementations with manual implementations:// Before #[derive(Copy...)] pub struct LogId<NID: NodeId> {} // After impl<NID: Copy> Copy for LogId<NID> {}
v0.9.16
What's Changed
- Fix: Prevent panic when calling
Raft::change_membership()
on uninitialized node by @drmingdrmer in #1243
Full Changelog: v0.9.15...v0.9.16
v0.9.15
Summary:
- Fixed:
- Added:
- 5f5d7e9f Add
TypeConfigExt
to simplifyRaftTypeConfig
Access.
- 5f5d7e9f Add
Detail:
Fixed:
-
Fixed: 0b1293f3 Should not update
vote
when seeing higher vote inRequestVote
response; by 张炎泼; 2024-07-04This commit addresses an issue in the vote updating mechanism during the
handling ofRequestVote
responses. Previously, encountering a higher
vote
in a response incorrectly led to an update of the local
state.vote
, which could break Raft consistency rules.Issue Description:
- A higher
vote
seen in aRequestVote
response does not necessarily
mean that the vote is granted. The localstate.vote
should only be
updated if the vote is actually granted, i.e., the responding node has
a highervote
and alast_log_id
that allows it to become a leader.
Resolution:
- The local
state.vote
will no longer be updated upon merely seeing a
highervote
in theRequestVote
response. Instead, this higher vote
will be recorded inlast_seen_vote
for consideration in the next
election cycle, without updating the currentstate.vote
.
This bug is introduced in: f0a9e34
- A higher
-
Fixed: 94b1e843 Clarify that receiving an equal vote does not grant leadership.; by 张炎泼; 2024-08-28
A node's
vote
may be updated when a leader observes a higher vote.
In such cases, the leader updates its local vote and steps down.
However, this vote update does not imply that the node accepts the
higher vote as valid for leadership, as it has not yet compared their
logs.In this commit, re-enable
VoteResponse.vote_granted
to indicate a vote
is granted.This commit also fix:
- Fix: #1236
Added:
-
Added: 5f5d7e9f Add
TypeConfigExt
to simplifyRaftTypeConfig
Access; by 张炎泼; 2024-07-03This commit introduces a new trait,
TypeConfigExt
, which extends
RaftTypeConfig
. The purpose of this trait is to simplify the access to
various functionalities provided by theRaftTypeConfig
trait,
enhancing code readability and reducing complexity.Methods Added to
TypeConfigExt
:now()
sleep()
sleep_until()
timeout()
timeout_at()
oneshot()
spawn()
Usage Improvement:
- Instead of using the
<<C as RaftTypeConfig>::AsyncRuntime as AsyncRuntime>::Instant::now()
,
you can now simply callC::now()
.
v0.9.13
Summary:
- Added:
- fb49efb3 Add
DecomposeResult
to simplify error handling.
- fb49efb3 Add
Detail:
Added:
-
Added: fb49efb3 Add
DecomposeResult
to simplify error handling; by 张炎泼; 2024-06-20This commit treats remote errors occurring during RPC, like a
Fatal
error, as anUnreachable
error. This is due to Openraft's current
inability to distinguish between an unreachable node and a broken node.- Helper trait
DecomposeResult
: Introduced to simplify handling
composite errors. It converts a result of the
formResult<R, ErrorAOrB>
into a nested resultResult<Result<R, ErrorA>, ErrorB>
.
- Helper trait
v0.9.12
Summary:
- DocFixed:
- 1385394c RemoveNodes -> add_leaner in dynamic-membership.
- Added:
- 8cd00388 Add
RaftLogReader::limited_get_log_entries()
.
- 8cd00388 Add
Detail:
DocFixed:
- DocFixed: 1385394c RemoveNodes -> add_leaner in dynamic-membership; by shuo; 2024-06-08
Added:
-
Added: 8cd00388 Add
RaftLogReader::limited_get_log_entries()
; by 张炎泼; 2024-06-16This commit adds the
RaftLogReader::limited_get_log_entries()
method,
which enables applications to fetch log entries that are equal to or
smaller than a specified range. This functionality is particularly
useful for customizing the size of AppendEntries requests at the storage
API level.-
Applications can now decide the number of log entries to return based
on the input range. If the application determines that the requested
log entries range is too large for a single RPC, it can opt to return
only the first several requested log entries instead of the full
range. -
The method provides a default implementation that delegates the
operation toRaftLogReader::try_get_log_entries
.
This enhancement allows for more flexible and efficient handling of log
entries, particularly in scenarios where network constraints or
performance considerations require smaller data transfers. -
v0.9.11
Summary:
- Fixed:
- 30cdf5fb New leader must flush blank log.
Detail:
Fixed:
-
Fixed: 30cdf5fb New leader must flush blank log; by 张炎泼; 2024-05-14
This commit addresses a critical issue where if a new leader does not
flush the blank log to disk upon becoming established and then restarts
immediately, there is a possibility that previously committed data
becomes invisible to readers.Before the blank log is flushed, the leader (identified by vote
v3
)
assumes it will be flushed and commits this log once (|quorum|-1)
replication responses are received. If the blank log is lost and the
server is restarted, data committed by a new leader (votev2
) may
not be visible.This issue is addressed by utilizing
LeaderHandler::leader_append_entries()
instead ofReplicationHandler::append_blank_log()
, where the former
does not wait for the blank log to flush.Changes:
-
When assigning log IDs to log entries, the
Leading.last_log_id
,
which represents the state of the log proposer (equivalent term in
Paxos is Proposer), should be used instead ofRaftState.last_log_id
,
which represents the state of the log receiver (equivalent term in
Paxos is Acceptor). -
Consequently, the method
assign_log_ids()
has been moved from
RaftState
toLeading
. -
Avoid manual implementation of duplicated logic:
-
During
initialize()
, reuseFollowingHandler::do_append_entries()
to submit the very first log to storage. -
In
establish_leader()
, reuse
LeaderHandler::leader_append_entries()
to submit log to storage
and removeReplicationHandler::append_blank_log()
. -
Remove
Command::AppendEntry
.
-
-