Replies: 5 comments 8 replies
-
The design looks a bit complicated to me. Can you describe the expected way to use a |
Beta Was this translation helpful? Give feedback.
-
Is it a good idea to model the API with leader leases? The spanner paper provided some details in "Appendix A". |
Beta Was this translation helpful? Give feedback.
-
This thread is mainly used to answer the problems that API design of Leader based Journal has faced and the solutions given. The current trait definations of #[async_trait]
pub trait StreamReader {
/// Seeks to the given sequence.
async fn seek(&mut self, sequence: Sequence) -> Result<()>;
/// Returns the next event.
async fn next(&mut self) -> Result<Option<Vec<u8>>>;
}
#[async_trait]
pub trait StreamWriter {
/// Appends an event.
async fn append(&mut self, event: Vec<u8>) -> Result<Sequence>;
/// Truncates events up to a sequence (exclusive).
async fn truncate(&mut self, sequence: Sequence) -> Result<()>;
}
#[async_trait]
pub trait Journal: Send + Sync + 'static {
type StreamLister: BatchResultStream<Elem = String, Error = Error>;
type StreamReader: StreamReader;
type StreamWriter: StreamWriter;
/// Lists streams.
async fn list_streams(&self) -> Result<Self::StreamLister>;
/// Creates a stream.
///
/// # Errors
///
/// Returns `Error::AlreadyExists` if the stream already exists.
async fn create_stream(&self, name: &str) -> Result<()>;
/// Deletes a stream.
///
/// Using a deleted stream is an undefined behavior.
///
/// # Errors
///
/// Returns `Error::NotFound` if the stream doesn't exist.
async fn delete_stream(&self, name: &str) -> Result<()>;
/// Returns a stream reader.
async fn new_stream_reader(&self, name: &str) -> Result<Self::StreamReader>;
/// Returns a stream writer.
async fn new_stream_writer(&self, name: &str) -> Result<Self::StreamWriter>;
} When the
In addition, another important question is whether it should keep consistent with the existing The API design proposal I haved post in early thread focus on problems 1 and 2. It assumes that |
Beta Was this translation helpful? Give feedback.
-
@w41ter-l what about the In this way, the LeaderBasedJournal serves as a decorator dealing with replication stuff while all real data r/w ops delegated. Also, it keep the Journal trait clean and doesn't bothered by consensus things. |
Beta Was this translation helpful? Give feedback.
-
I found that if I change the semantics of Before start discussion, I want change the word These considrations are:
After that, the API changed to: pub enum RoleState {
Leader,
Follower,
}
pub trait SingleWriteJournal : Journal {
type Role;
type Peer;
type StateStream: Stream<Item = RoleState>;
fn state(&self, name: &str) -> (Self::Role, Option<Self::Peer>);
async fn transfer(&mut self, name: &str, peer: Self::Peer) -> Result<()>;
async fn observe_state(&self, name: &str) -> Self::StateStream;
} An Engine could open both |
Beta Was this translation helpful? Give feedback.
-
This is part of thread #251, and focus on the design of API of leader based Journal.
In #229 , @huachaohuang comment:
I have try to prototype the interfaces of leader based journal with the implementation of
Kernel::apply_update
(you can found it in here):I create a new trait named
LeaderBasedJournal
and add some methods to it:role
: returns the role of current journalleader
: returns the leader peer of current journal's replication grouptransfer
: tranfer leadership to the specified peerobserve_state
: observe the changes of roleAll these methods need to specify stream name. Once this peer become the leader of a stream, it will open a
StreamWriter
for appending.So far, this design is still a draft, and everyone is welcome to discuss it.
Beta Was this translation helpful? Give feedback.
All reactions