-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Motivation:
Applications implementing storage traits must construct complex StorageError<C> with subject, verb, and metadata. This is unnecessary - applications only need to signal "something went wrong".
However, applications still need to receive structured StorageError<C> FROM Openraft for rich error information, serde support, and debugging.
Proposed Changes:
-
Storage trait methods return
io::Errorinstead ofStorageError<C>:// Before async fn save_vote(&mut self, vote: &Vote<C>) -> Result<(), StorageError<C>>; // After async fn save_vote(&mut self, vote: &Vote<C>) -> Result<(), io::Error>;
-
Openraft manually converts
io::ErrortoStorageError<C>with proper context at call sites:// In Openraft's internal code self.log_store.save_vote(vote) .await .map_err(|e| StorageError::write_vote(&e))?; // Add context here self.log_store.get_log_state() .await .map_err(|e| StorageError::read(&e))?; // Different context
-
No
From<io::Error>trait implementation - manual conversion preserves semantic context (subject/verb) -
Openraft continues returning
StorageError<C>to applications throughRaftError::Fatal(Fatal::StorageError(StorageError<C>))
Benefits:
✅ For application developers:
- Return simple
io::Error- no need to choose subject/verb - Significant reduction in boilerplate
- Direct compatibility with Rust error ecosystem
✅ For Openraft:
- Full control over error context (knows which operation was called)
- Maintains structured
StorageError<C>with accurate metadata - Can add proper subject/verb based on operation
✅ For error consumers:
- Still receive full
StorageError<C>with rich information - Serde support unchanged
- Accurate error context (subject/verb match actual operation)
Implementation Checklist:
- Update all storage trait method signatures to return
Result<T, io::Error>:RaftLogStorage(8 methods)RaftLogReader(4 methods)RaftStateMachine(5 methods)RaftSnapshotBuilder(1 method)
- Update all Openraft internal call sites to manually convert
io::Error→StorageError<C>with appropriate helper - Keep
Fatal::StorageError(StorageError<C>)unchanged - Update examples (memstore, rocksstore, raft-kv-memstore) to return
io::Error - Update documentation and migration guide
- Keep existing
StorageError::write_logs()helpers for Openraft's internal use
Example Before/After:
// Before: Application constructs StorageError
impl RaftLogStorage for MyStore {
async fn save_vote(&mut self, vote: &Vote<C>) -> Result<(), StorageError<C>> {
self.db.write(vote)
.await
.map_err(|e| StorageError::write_vote(&e))?; // Application adds context
Ok(())
}
}
// After: Application returns io::Error, Openraft adds context
impl RaftLogStorage for MyStore {
async fn save_vote(&mut self, vote: &Vote<C>) -> Result<(), io::Error> {
self.db.write(vote).await?; // Simple\!
Ok(())
}
}
// In Openraft core:
log_store.save_vote(vote)
.await
.map_err(|e| StorageError::write_vote(&e))?; // Openraft adds contextFiles Affected:
openraft/src/storage/v2/*.rs- Update trait method signatures (18 methods)openraft/src/core/*.rs- Add.map_err(|e| StorageError::xxx(&e))at all storage call sitesopenraft/src/storage/helper.rs- Update call sitesstores/memstore/src/*.rs- Returnio::Errorinstead ofStorageError<C>examples/*/src/*.rs- Returnio::Errorinstead ofStorageError<C>
Migration Impact:
- Breaking change for all storage implementations
- Applications must change return types from
StorageError<C>toio::Error - Migration is straightforward: remove
.map_err(|e| StorageError::xxx(&e))from application code - Target for 0.11.0 release