Skip to content

Commit

Permalink
Feature: add feature-flag: bt enables backtrace
Browse files Browse the repository at this point in the history
`--features bt` enables backtrace when generating errors.
By default errors does not contain backtrace info.

Thus openraft can be built on stable rust by default.

To use on stable rust with backtrace, set `RUSTC_BOOTSTRAP=1`, e.g.:
```
RUSTUP_TOOLCHAIN=stable RUSTC_BOOTSTRAP=1 make test
```

- fix: #241

commit-id:933ca964
  • Loading branch information
drmingdrmer committed Mar 12, 2022
1 parent f5b5d54 commit 2a5c1b9
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 65 deletions.
57 changes: 57 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,63 @@ jobs:
args: --all-targets -- -D warnings -A clippy::bool-assert-comparison


- name: Upload artifact
uses: actions/upload-artifact@v2
if: failure()
with:
path: |
openraft/_log/
ut-on-stable-rust:
name: unittest on stable rust
runs-on: ubuntu-latest

steps:
- name: Setup | Checkout
uses: actions/checkout@v2

- name: Setup | Toolchain
uses: actions-rs/toolchain@v1.0.6
with:
toolchain: "stable"
override: true
components: rustfmt, clippy

- name: Unit Tests
uses: actions-rs/cargo@v1
with:
command: test
env:
# Parallel tests block each other and result in timeout.
RUST_TEST_THREADS: 2
RUST_LOG: debug
RUST_BACKTRACE: full


- name: Test example-raft-kv
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path example-raft-kv/Cargo.toml


- name: Build | Release Mode | No features
uses: actions-rs/cargo@v1
with:
command: build
args: --release


- name: Build | Release Mode | No features
uses: actions-rs/cargo@v1
with:
command: build
args: --release --all-features
env:
# Enable unstable feature on stalbe rust.
RUSTC_BOOTSTRAP: 1


- name: Upload artifact
uses: actions/upload-artifact@v2
if: failure()
Expand Down
1 change: 0 additions & 1 deletion example-raft-kv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ path = "src/bin/main.rs"

[dependencies]
actix-web = "4.0.0-rc.2"
anyerror = { version = "0.1.4"}
async-trait = "0.1.36"
clap = { version = "3.0.13", features = ["derive", "env"] }
env_logger = "0.9.0"
Expand Down
2 changes: 1 addition & 1 deletion example-raft-kv/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use std::ops::RangeBounds;
use std::sync::Arc;
use std::sync::Mutex;

use anyerror::AnyError;
use openraft::async_trait::async_trait;
use openraft::raft::Entry;
use openraft::raft::EntryPayload;
use openraft::storage::LogState;
use openraft::storage::Snapshot;
use openraft::AnyError;
use openraft::EffectiveMembership;
use openraft::ErrorSubject;
use openraft::ErrorVerb;
Expand Down
2 changes: 1 addition & 1 deletion example-raft-kv/tests/cluster/test_cluster.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::thread;
use std::time::Duration;

use anyerror::AnyError;
use example_raft_key_value::client::ExampleClient;
use example_raft_key_value::start_example_raft_node;
use example_raft_key_value::store::ExampleRequest;
use example_raft_key_value::ExampleTypeConfig;
use maplit::btreemap;
use maplit::btreeset;
use openraft::error::NodeNotFound;
use openraft::AnyError;
use openraft::Node;
use tokio::runtime::Runtime;

Expand Down
1 change: 0 additions & 1 deletion memstore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ repository = "https://github.com/datafuselabs/openraft"
readme = "README.md"

[dependencies]
anyerror = { version = "0.1.4"}
openraft = { version="0.6", path= "../openraft" }
async-trait = "0.1.36"
serde = { version="1.0.114", features=["derive"] }
Expand Down
4 changes: 1 addition & 3 deletions memstore/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![feature(backtrace)]

#[cfg(test)]
mod test;

Expand All @@ -11,14 +9,14 @@ use std::ops::RangeBounds;
use std::sync::Arc;
use std::sync::Mutex;

use anyerror::AnyError;
use openraft::async_trait::async_trait;
use openraft::raft::Entry;
use openraft::raft::EntryPayload;
use openraft::storage::LogState;
use openraft::storage::RaftLogReader;
use openraft::storage::RaftSnapshotBuilder;
use openraft::storage::Snapshot;
use openraft::AnyError;
use openraft::EffectiveMembership;
use openraft::ErrorSubject;
use openraft::ErrorVerb;
Expand Down
8 changes: 7 additions & 1 deletion openraft/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ repository = "https://github.com/datafuselabs/openraft"
readme = "../README.md"

[dependencies]
anyerror = { version = "0.1.4", features = ["anyhow"]}
anyerror = { version = "0.1.6" }
# Leave it for debug
# anyerror = { git = "https://github.com/drmingdrmer/anyerror", branch = "ci", features = ["anyhow"]}
async-trait = "0.1.36"
byte-unit = "4.0.12"
bytes = "1.0"
Expand Down Expand Up @@ -44,5 +46,9 @@ tracing-subscriber = { version = "0.3.3", features=["env-filter"] }
[features]
docinclude = [] # Used only for activating `doc(include="...")` on nightly.

# Enable backtrace when generating an error.
# Stable rust does not support backtrace.
bt = ["anyerror/backtrace", "anyhow/backtrace"]

[package.metadata.docs.rs]
features = ["docinclude"] # Activate `docinclude` during docs.rs build.
3 changes: 2 additions & 1 deletion openraft/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,8 @@ impl<C: RaftTypeConfig, N: RaftNetworkFactory<C>, S: RaftStorage<C>> RaftCore<C,
Ok(res) => match res {
Ok(snapshot) => {
let _ = tx_compaction.try_send(SnapshotUpdate::SnapshotComplete(snapshot.meta.last_log_id));
let _ = chan_tx.send(snapshot.meta.last_log_id.index); // This will always succeed.
// This will always succeed.
let _ = chan_tx.send(snapshot.meta.last_log_id.index);
}
Err(err) => {
tracing::error!({error=%err}, "error while generating snapshot");
Expand Down
10 changes: 9 additions & 1 deletion openraft/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#![doc = include_str!("../README.md")]
#![feature(backtrace)]
#![cfg_attr(feature = "bt", feature(backtrace))]

//! # Feature flags
//!
//! - `bt`: Enable backtrace: generate backtrace for errors. This requires a unstable feature `backtrace` thus it can
//! not be used with stable rust, unless explicity allowing using unstable features in stable rust with
//! `RUSTC_BOOTSTRAP=1`.

mod config;
mod core;
Expand Down Expand Up @@ -28,6 +34,8 @@ mod leader_metrics_test;
#[cfg(test)]
mod metrics_wait_test;

pub use anyerror;
pub use anyerror::AnyError;
pub use async_trait;
use serde::de::DeserializeOwned;
use serde::Serialize;
Expand Down
14 changes: 6 additions & 8 deletions openraft/src/storage_error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::backtrace::Backtrace;
use std::fmt::Formatter;
use std::ops::Bound;

Expand Down Expand Up @@ -45,15 +44,15 @@ pub struct DefensiveError<C: RaftTypeConfig> {
/// The description of the violation.
pub violation: Violation<C>,

pub backtrace: String,
pub backtrace: Option<String>,
}

impl<C: RaftTypeConfig> DefensiveError<C> {
pub fn new(subject: ErrorSubject<C>, violation: Violation<C>) -> Self {
Self {
subject,
violation,
backtrace: format!("{:?}", Backtrace::capture()),
backtrace: anyerror::backtrace_str(),
}
}
}
Expand Down Expand Up @@ -168,15 +167,15 @@ pub enum StorageError<C: RaftTypeConfig> {
#[error(transparent)]
Defensive {
#[from]
#[backtrace]
#[cfg_attr(feature = "bt", backtrace)]
source: DefensiveError<C>,
},

/// An error raised by io operation.
#[error(transparent)]
IO {
#[from]
#[backtrace]
#[cfg_attr(feature = "bt", backtrace)]
source: StorageIOError<C>,
},
}
Expand Down Expand Up @@ -209,7 +208,7 @@ pub struct StorageIOError<C: RaftTypeConfig> {
subject: ErrorSubject<C>,
verb: ErrorVerb,
source: AnyError,
backtrace: String,
backtrace: Option<String>,
}

impl<C: RaftTypeConfig> std::fmt::Display for StorageIOError<C> {
Expand All @@ -224,8 +223,7 @@ impl<C: RaftTypeConfig> StorageIOError<C> {
subject,
verb,
source,
// TODO: use crate backtrace instead of std::backtrace.
backtrace: format!("{:?}", Backtrace::capture()),
backtrace: anyerror::backtrace_str(),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@ async fn append_entries_with_bigger_term() -> Result<()> {
assert!(resp.is_success());

// after append entries, check hard state in term 2 and vote for node 1
let mut store = router.get_storage_handle(&0)?;

router
.assert_storage_state_in_node(
0,
.assert_storage_state_with_sto(
&mut store,
&0,
2,
log_index,
Some(1),
LogId::new(LeaderId::new(1, 0), log_index),
None,
&None,
)
.await?;

Expand Down
47 changes: 10 additions & 37 deletions openraft/tests/fixtures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,39 +839,6 @@ where
Ok(())
}

/// Assert against the state of the storage system one node in the cluster.
pub async fn assert_storage_state_in_node(
&self,
node_id: C::NodeId,
expect_term: u64,
expect_last_log: u64,
expect_voted_for: Option<C::NodeId>,
expect_sm_last_applied_log: LogId<C::NodeId>,
expect_snapshot: Option<(ValueTest<u64>, u64)>,
) -> anyhow::Result<()> {
let mut rt = self.routing_table.lock().unwrap();

for (id, (_node, storage)) in rt.iter_mut() {
if *id != node_id {
continue;
}
self.assert_storage_state_with_sto(
storage,
id,
expect_term,
expect_last_log,
expect_voted_for,
expect_sm_last_applied_log,
&expect_snapshot,
)
.await?;

break;
}

Ok(())
}

/// Assert against the state of the storage system per node in the cluster.
pub async fn assert_storage_state(
&self,
Expand All @@ -881,12 +848,18 @@ where
expect_sm_last_applied_log: LogId<C::NodeId>,
expect_snapshot: Option<(ValueTest<u64>, u64)>,
) -> anyhow::Result<()> {
let mut rt = self.routing_table.lock().unwrap();
let node_ids = {
let rt = self.routing_table.lock().unwrap();
let node_ids = rt.keys().cloned().collect::<Vec<_>>();
node_ids
};

for id in node_ids {
let mut storage = self.get_storage_handle(&id)?;

for (id, (_node, storage)) in rt.iter_mut() {
self.assert_storage_state_with_sto(
storage,
id,
&mut storage,
&id,
expect_term,
expect_last_log,
expect_voted_for,
Expand Down
16 changes: 10 additions & 6 deletions openraft/tests/snapshot/snapshot_chunk_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,27 +101,31 @@ async fn snapshot_chunk_size() -> Result<()> {

// after add_learner, log_index + 1,
// leader has only log_index log in snapshot, cause it has compacted before add_learner
let mut store = router.get_storage_handle(&0)?;
router
.assert_storage_state_in_node(
0,
.assert_storage_state_with_sto(
&mut store,
&0,
1,
log_index,
Some(0),
LogId::new(LeaderId::new(1, 0), log_index),
Some(((log_index - 1).into(), 1)),
&Some(((log_index - 1).into(), 1)),
)
.await?;

// learner has log_index + 1 log in snapshot, cause it do compact after add_learner,
// so learner's snapshot include add_learner log
let mut store = router.get_storage_handle(&1)?;
router
.assert_storage_state_in_node(
1,
.assert_storage_state_with_sto(
&mut store,
&1,
1,
log_index,
Some(0),
LogId::new(LeaderId::new(1, 0), log_index),
Some(((log_index).into(), 1)),
&Some(((log_index).into(), 1)),
)
.await?;
}
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2022-02-07
nightly-2022-03-03

0 comments on commit 2a5c1b9

Please sign in to comment.