diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index db2e7c4fb..64dc895d9 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -6,7 +6,7 @@ on: - cron: "00 00 * * 1" env: - CI_RUST_TOOLCHAIN: 1.71.0 + CI_RUST_TOOLCHAIN: 1.74.0 jobs: benchmark: diff --git a/.github/workflows/build_xline.yml b/.github/workflows/build_xline.yml index d52951851..dcb68ef10 100644 --- a/.github/workflows/build_xline.yml +++ b/.github/workflows/build_xline.yml @@ -1,6 +1,6 @@ name: Build Xline env: - CI_RUST_TOOLCHAIN: 1.71.0 + CI_RUST_TOOLCHAIN: 1.74.0 on: workflow_call: inputs: diff --git a/.github/workflows/docker_image.yml b/.github/workflows/docker_image.yml index 2da019a0b..94a7cc8fb 100644 --- a/.github/workflows/docker_image.yml +++ b/.github/workflows/docker_image.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: { } env: - CI_RUST_TOOLCHAIN: 1.71.0 + CI_RUST_TOOLCHAIN: 1.74.0 IMAGE_ID: ghcr.io/xline-kv/xline jobs: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ca33a9b5d..5d37391b6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: - "v*" env: - CI_RUST_TOOLCHAIN: 1.71.0 + CI_RUST_TOOLCHAIN: 1.74.0 IMAGE_ID: ghcr.io/xline-kv/xline jobs: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d149e4c6e..445bd0372 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - id: conventional-commit-msg-validation name: commit message conventional validation language: pygrep - entry: '^(breaking|build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w `])+([\s\S]*)' + entry: '^(breaking|build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test|squash|fixup){1}(\([\w\-\.]+\))?(!)?: ([\w `])+([\s\S]*)' args: [--multiline, --negate] stages: [commit-msg] - id: commit-msg-needs-to-be-signed-off diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fa1fb0f0b..9a04660a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -154,7 +154,7 @@ Check the code format. cargo fmt --all -- --check ``` -**Note**: The current version of the Rust toolchain used for CI is **1.71.0** . +**Note**: The current version of the Rust toolchain used for CI is **1.74.0** . Please use this version to run the above command, otherwise you may get different results with CI. diff --git a/ci/rust-toolchain.toml b/ci/rust-toolchain.toml index bfeb00751..24a9c4639 100644 --- a/ci/rust-toolchain.toml +++ b/ci/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.71.0" +channel = "1.74.0" components = ["rustfmt", "clippy", "rust-src"] diff --git a/crates/benchmark/src/lib.rs b/crates/benchmark/src/lib.rs index 574675e69..a03cfe6ed 100644 --- a/crates/benchmark/src/lib.rs +++ b/crates/benchmark/src/lib.rs @@ -126,17 +126,23 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, )] #![allow( clippy::multiple_crate_versions, // caused by the dependency, can't be fixed diff --git a/crates/curp-external-api/src/cmd.rs b/crates/curp-external-api/src/cmd.rs index b1f809020..921268f3b 100644 --- a/crates/curp-external-api/src/cmd.rs +++ b/crates/curp-external-api/src/cmd.rs @@ -47,6 +47,9 @@ pub trait Command: pri::Serializable + ConflictCheck + PbCodec { fn keys(&self) -> &[Self::K]; /// Prepare the command + /// + /// # Errors + /// Return `Self::Error` when `CommandExecutor::prepare` goes wrong #[inline] fn prepare(&self, e: &E) -> Result where @@ -56,6 +59,9 @@ pub trait Command: pri::Serializable + ConflictCheck + PbCodec { } /// Execute the command according to the executor + /// + /// # Errors + /// Return `Self::Error` when `CommandExecutor::execute` goes wrong #[inline] async fn execute(&self, e: &E) -> Result where @@ -65,6 +71,9 @@ pub trait Command: pri::Serializable + ConflictCheck + PbCodec { } /// Execute the command after_sync callback + /// + /// # Errors + /// Return `Self::Error` when `CommandExecutor::after_sync` goes wrong #[inline] async fn after_sync( &self, @@ -111,12 +120,21 @@ where C: Command, { /// Prepare the command + /// + /// # Errors + /// This function may return an error if there is a problem preparing the command. fn prepare(&self, cmd: &C) -> Result; /// Execute the command + /// + /// # Errors + /// This function may return an error if there is a problem executing the command. async fn execute(&self, cmd: &C) -> Result; /// Execute the after_sync callback + /// + /// # Errors + /// This function may return an error if there is a problem executing the after_sync callback. async fn after_sync( &self, cmd: &C, @@ -125,15 +143,27 @@ where ) -> Result; /// Set the index of the last log entry that has been successfully applied to the command executor + /// + /// # Errors + /// Returns an error if setting the last applied log entry fails. fn set_last_applied(&self, index: LogIndex) -> Result<(), C::Error>; - /// Index of the last log entry that has been successfully applied to the command executor + /// Get the index of the last log entry that has been successfully applied to the command executor + /// + /// # Errors + /// Returns an error if retrieval of the last applied log entry fails. fn last_applied(&self) -> Result; /// Take a snapshot + /// + /// # Errors + /// This function may return an error if there is a problem taking a snapshot. async fn snapshot(&self) -> Result; /// Reset the command executor using the snapshot or to the initial state if None + /// + /// # Errors + /// This function may return an error if there is a problem resetting the command executor. async fn reset(&self, snapshot: Option<(Snapshot, LogIndex)>) -> Result<(), C::Error>; /// Trigger the barrier of the given trigger id (based on propose id) and log index. diff --git a/crates/curp-external-api/src/lib.rs b/crates/curp-external-api/src/lib.rs index 81d9bd3af..4d56f4e5e 100644 --- a/crates/curp-external-api/src/lib.rs +++ b/crates/curp-external-api/src/lib.rs @@ -44,6 +44,7 @@ clippy::pedantic, clippy::cargo, + // The followings are selected restriction lints for rust 1.57 clippy::as_conversions, clippy::clone_on_ref_ptr, @@ -126,17 +127,23 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, )] /// Log Index diff --git a/crates/curp-test-utils/src/test_cmd.rs b/crates/curp-test-utils/src/test_cmd.rs index ee56b26e5..38b1e7d51 100644 --- a/crates/curp-test-utils/src/test_cmd.rs +++ b/crates/curp-test-utils/src/test_cmd.rs @@ -265,7 +265,7 @@ impl CommandExecutor for TestCE { let keys = cmd .keys .iter() - .map(|k| k.to_be_bytes().to_vec()) + .map(|k| k.to_le_bytes().to_vec()) .collect_vec(); let result: TestCommandResult = match cmd.cmd_type { TestCommandType::Get => { @@ -275,7 +275,7 @@ impl CommandExecutor for TestCE { .map_err(|e| ExecuteError(e.to_string()))? .into_iter() .flatten() - .map(|v| u32::from_be_bytes(v.as_slice().try_into().unwrap())) + .map(|v| u32::from_le_bytes(v.as_slice().try_into().unwrap())) .collect(); let revision = self .store @@ -283,7 +283,7 @@ impl CommandExecutor for TestCE { .map_err(|e| ExecuteError(e.to_string()))? .into_iter() .flatten() - .map(|v| i64::from_be_bytes(v.as_slice().try_into().unwrap())) + .map(|v| i64::from_le_bytes(v.as_slice().try_into().unwrap())) .collect_vec(); TestCommandResult::new(value, revision) } @@ -316,11 +316,11 @@ impl CommandExecutor for TestCE { )]; if let TestCommandType::Put(v) = cmd.cmd_type { debug!("cmd {:?}-{:?} revision is {}", cmd.cmd_type, cmd, revision); - let value = v.to_be_bytes().to_vec(); + let value = v.to_le_bytes().to_vec(); let keys = cmd .keys .iter() - .map(|k| k.to_be_bytes().to_vec()) + .map(|k| k.to_le_bytes().to_vec()) .collect_vec(); wr_ops.extend( keys.clone() @@ -330,7 +330,7 @@ impl CommandExecutor for TestCE { WriteOperation::new_put( REVISION_TABLE, key, - revision.to_be_bytes().to_vec(), + revision.to_le_bytes().to_vec(), ) })), ); diff --git a/crates/curp/src/client/retry.rs b/crates/curp/src/client/retry.rs index 346248c0e..e5cb550b5 100644 --- a/crates/curp/src/client/retry.rs +++ b/crates/curp/src/client/retry.rs @@ -143,30 +143,30 @@ where match err { // some errors that should not retry - CurpError::Duplicated(_) - | CurpError::ShuttingDown(_) - | CurpError::InvalidConfig(_) - | CurpError::NodeNotExists(_) - | CurpError::NodeAlreadyExists(_) - | CurpError::LearnerNotCatchUp(_) => { + CurpError::Duplicated(()) + | CurpError::ShuttingDown(()) + | CurpError::InvalidConfig(()) + | CurpError::NodeNotExists(()) + | CurpError::NodeAlreadyExists(()) + | CurpError::LearnerNotCatchUp(()) => { return Err(tonic::Status::from(err)); } // some errors that could have a retry - CurpError::ExpiredClientId(_) - | CurpError::KeyConflict(_) + CurpError::ExpiredClientId(()) + | CurpError::KeyConflict(()) | CurpError::Internal(_) | CurpError::LeaderTransfer(_) => {} // update leader state if we got a rpc transport error - CurpError::RpcTransport(_) => { + CurpError::RpcTransport(()) => { if let Err(e) = self.inner.fetch_leader_id(true).await { warn!("fetch leader failed, error {e:?}"); } } // update the cluster state if got WrongClusterVersion - CurpError::WrongClusterVersion(_) => { + CurpError::WrongClusterVersion(()) => { // the inner client should automatically update cluster state when fetch_cluster if let Err(e) = self.inner.fetch_cluster(true).await { warn!("fetch cluster failed, error {e:?}"); diff --git a/crates/curp/src/client/stream.rs b/crates/curp/src/client/stream.rs index 86d9e6b7f..30dca8f88 100644 --- a/crates/curp/src/client/stream.rs +++ b/crates/curp/src/client/stream.rs @@ -63,7 +63,7 @@ impl Streaming { pub(super) async fn keep_heartbeat(&self) { /// Prevent lock contention when leader crashed or some unknown errors const RETRY_DELAY: Duration = Duration::from_millis(100); - + #[allow(clippy::ignored_unit_patterns)] // tokio select internal triggered loop { let heartbeat = self.map_remote_leader::<(), _>(|conn| async move { loop { @@ -78,13 +78,13 @@ impl Streaming { CurpError::Redirect(Redirect { leader_id, term }) => { let _ig = self.state.check_and_update_leader(leader_id, term).await; } - CurpError::WrongClusterVersion(_) => { + CurpError::WrongClusterVersion(()) => { warn!( "cannot find the leader in connects, wait for leadership update" ); self.state.leader_notifier().listen().await; } - CurpError::ShuttingDown(_) => { + CurpError::ShuttingDown(()) => { debug!("shutting down stream client background task"); break Err(err); } diff --git a/crates/curp/src/client/tests.rs b/crates/curp/src/client/tests.rs index a29104aec..9f94e17cb 100644 --- a/crates/curp/src/client/tests.rs +++ b/crates/curp/src/client/tests.rs @@ -353,7 +353,7 @@ async fn test_unary_fast_round_less_quorum() { /// TODO: fix in subsequence PR #[traced_test] #[tokio::test] -#[should_panic] +#[should_panic(expected = "should not set exe result twice")] async fn test_unary_fast_round_with_two_leader() { let connects = init_mocked_connects(5, |id, conn| { conn.expect_propose() @@ -928,6 +928,7 @@ async fn test_stream_client_keep_alive_hang_up_on_bypassed() { #[traced_test] #[tokio::test] +#[allow(clippy::ignored_unit_patterns)] // tokio select internal triggered async fn test_stream_client_keep_alive_resume_on_leadership_changed() { let connects = init_mocked_stream_connects(5, 1, 2, move |client_id| { Box::pin(async move { diff --git a/crates/curp/src/lib.rs b/crates/curp/src/lib.rs index 1918b0298..a6a337218 100644 --- a/crates/curp/src/lib.rs +++ b/crates/curp/src/lib.rs @@ -50,7 +50,6 @@ clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, - // clippy::default_numeric_fallback, too verbose when dealing with numbers clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::exhaustive_enums, @@ -62,7 +61,6 @@ clippy::float_cmp_const, clippy::get_unwrap, clippy::if_then_some_else_none, - // clippy::implicit_return, it's idiomatic Rust code. clippy::indexing_slicing, // clippy::inline_asm_x86_att_syntax, stick to intel syntax clippy::inline_asm_x86_intel_syntax, @@ -114,7 +112,6 @@ clippy::iter_on_empty_collections, clippy::iter_on_single_items, clippy::large_include_file, - clippy::manual_clamp, clippy::suspicious_xor_used_as_pow, clippy::unnecessary_safety_comment, clippy::unnecessary_safety_doc, @@ -126,20 +123,27 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, )] #![allow( clippy::multiple_crate_versions, // caused by the dependency, can't be fixed + clippy::missing_fields_in_debug )] #![cfg_attr( test, diff --git a/crates/curp/src/rpc/mod.rs b/crates/curp/src/rpc/mod.rs index 30de9673d..16a7c77ea 100644 --- a/crates/curp/src/rpc/mod.rs +++ b/crates/curp/src/rpc/mod.rs @@ -683,13 +683,13 @@ impl CurpError { pub(crate) fn should_abort_fast_round(&self) -> bool { matches!( *self, - CurpError::Duplicated(_) - | CurpError::ShuttingDown(_) - | CurpError::InvalidConfig(_) - | CurpError::NodeAlreadyExists(_) - | CurpError::NodeNotExists(_) - | CurpError::LearnerNotCatchUp(_) - | CurpError::ExpiredClientId(_) + CurpError::Duplicated(()) + | CurpError::ShuttingDown(()) + | CurpError::InvalidConfig(()) + | CurpError::NodeAlreadyExists(()) + | CurpError::NodeNotExists(()) + | CurpError::LearnerNotCatchUp(()) + | CurpError::ExpiredClientId(()) | CurpError::Redirect(_) ) } @@ -698,32 +698,32 @@ impl CurpError { pub(crate) fn should_abort_slow_round(&self) -> bool { matches!( *self, - CurpError::ShuttingDown(_) - | CurpError::InvalidConfig(_) - | CurpError::NodeAlreadyExists(_) - | CurpError::NodeNotExists(_) - | CurpError::LearnerNotCatchUp(_) - | CurpError::ExpiredClientId(_) + CurpError::ShuttingDown(()) + | CurpError::InvalidConfig(()) + | CurpError::NodeAlreadyExists(()) + | CurpError::NodeNotExists(()) + | CurpError::LearnerNotCatchUp(()) + | CurpError::ExpiredClientId(()) | CurpError::Redirect(_) - | CurpError::WrongClusterVersion(_) + | CurpError::WrongClusterVersion(()) ) } /// Get the priority of the error pub(crate) fn priority(&self) -> CurpErrorPriority { match *self { - CurpError::Duplicated(_) - | CurpError::ShuttingDown(_) - | CurpError::InvalidConfig(_) - | CurpError::NodeAlreadyExists(_) - | CurpError::NodeNotExists(_) - | CurpError::LearnerNotCatchUp(_) - | CurpError::ExpiredClientId(_) + CurpError::Duplicated(()) + | CurpError::ShuttingDown(()) + | CurpError::InvalidConfig(()) + | CurpError::NodeAlreadyExists(()) + | CurpError::NodeNotExists(()) + | CurpError::LearnerNotCatchUp(()) + | CurpError::ExpiredClientId(()) | CurpError::Redirect(_) - | CurpError::WrongClusterVersion(_) => CurpErrorPriority::High, - CurpError::RpcTransport(_) + | CurpError::WrongClusterVersion(()) => CurpErrorPriority::High, + CurpError::RpcTransport(()) | CurpError::Internal(_) - | CurpError::KeyConflict(_) + | CurpError::KeyConflict(()) | CurpError::LeaderTransfer(_) => CurpErrorPriority::Low, } } @@ -774,39 +774,39 @@ impl From for tonic::Status { #[inline] fn from(err: CurpError) -> Self { let (code, msg) = match err { - CurpError::KeyConflict(_) => ( + CurpError::KeyConflict(()) => ( tonic::Code::AlreadyExists, "Key conflict error: A key conflict occurred.", ), - CurpError::Duplicated(_) => ( + CurpError::Duplicated(()) => ( tonic::Code::AlreadyExists, "Duplicated error: The request already sent.", ), - CurpError::ExpiredClientId(_) => ( + CurpError::ExpiredClientId(()) => ( tonic::Code::FailedPrecondition, "Expired client ID error: The client ID has expired, we cannot tell if this request is duplicated.", ), - CurpError::InvalidConfig(_) => ( + CurpError::InvalidConfig(()) => ( tonic::Code::InvalidArgument, "Invalid config error: The provided configuration is invalid.", ), - CurpError::NodeNotExists(_) => ( + CurpError::NodeNotExists(()) => ( tonic::Code::NotFound, "Node not found error: The specified node does not exist.", ), - CurpError::NodeAlreadyExists(_) => ( + CurpError::NodeAlreadyExists(()) => ( tonic::Code::AlreadyExists, "Node already exists error: The node already exists.", ), - CurpError::LearnerNotCatchUp(_) => ( + CurpError::LearnerNotCatchUp(()) => ( tonic::Code::FailedPrecondition, "Learner not caught up error: The learner has not caught up.", ), - CurpError::ShuttingDown(_) => ( + CurpError::ShuttingDown(()) => ( tonic::Code::FailedPrecondition, "Shutting down error: The service is currently shutting down.", ), - CurpError::WrongClusterVersion(_) => ( + CurpError::WrongClusterVersion(()) => ( tonic::Code::FailedPrecondition, "Wrong cluster version error: The cluster version is incorrect.", ), @@ -818,7 +818,7 @@ impl From for tonic::Status { tonic::Code::Internal, "Internal error: An internal error occurred.", ), - CurpError::RpcTransport(_) => (tonic::Code::Cancelled, "Rpc error: Request cancelled"), + CurpError::RpcTransport(()) => (tonic::Code::Cancelled, "Rpc error: Request cancelled"), CurpError::LeaderTransfer(_) => ( tonic::Code::FailedPrecondition, "Leader transfer error: A leader transfer error occurred.", diff --git a/crates/curp/src/server/cmd_board.rs b/crates/curp/src/server/cmd_board.rs index f41d7237e..77b78fcd3 100644 --- a/crates/curp/src/server/cmd_board.rs +++ b/crates/curp/src/server/cmd_board.rs @@ -101,7 +101,7 @@ impl CommandBoard { /// Get a listener for execution result fn er_listener(&mut self, id: ProposeId) -> EventListener { - let event = self.er_notifiers.entry(id).or_insert_with(Event::new); + let event = self.er_notifiers.entry(id).or_default(); let listener = event.listen(); if self.er_buffer.contains_key(&id) { event.notify(usize::MAX); @@ -116,7 +116,7 @@ impl CommandBoard { /// Get a listener for after sync result fn asr_listener(&mut self, id: ProposeId) -> EventListener { - let event = self.asr_notifiers.entry(id).or_insert_with(Event::new); + let event = self.asr_notifiers.entry(id).or_default(); let listener = event.listen(); if self.asr_buffer.contains_key(&id) { event.notify(usize::MAX); @@ -126,7 +126,7 @@ impl CommandBoard { /// Get a listener for conf change result fn conf_listener(&mut self, id: ProposeId) -> EventListener { - let event = self.conf_notifier.entry(id).or_insert_with(Event::new); + let event = self.conf_notifier.entry(id).or_default(); let listener = event.listen(); if self.conf_buffer.contains(&id) { event.notify(usize::MAX); diff --git a/crates/curp/src/server/cmd_worker/mod.rs b/crates/curp/src/server/cmd_worker/mod.rs index 47a79ba1a..e46c218e6 100644 --- a/crates/curp/src/server/cmd_worker/mod.rs +++ b/crates/curp/src/server/cmd_worker/mod.rs @@ -62,7 +62,8 @@ async fn cmd_worker, RC: RoleChange>( ce: Arc, shutdown_listener: Listener, ) { - #[allow(clippy::arithmetic_side_effects)] // introduced by tokio select + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] + // introduced by tokio select loop { tokio::select! { task = dispatch_rx.recv() => { diff --git a/crates/curp/src/server/curp_node.rs b/crates/curp/src/server/curp_node.rs index 00ee0a0b1..83e4eba2b 100644 --- a/crates/curp/src/server/curp_node.rs +++ b/crates/curp/src/server/curp_node.rs @@ -396,7 +396,7 @@ impl CurpNode { /// Spawned tasks impl CurpNode { /// Tick periodically - #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] async fn election_task(curp: Arc>, shutdown_listener: Listener) { let heartbeat_interval = curp.cfg().heartbeat_interval; // wait for some random time before tick starts to minimize vote split possibility @@ -439,7 +439,8 @@ impl CurpNode { ) { let task_manager = curp.task_manager(); let change_rx = curp.change_rx(); - #[allow(clippy::arithmetic_side_effects)] // introduced by tokio select + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] + // introduced by tokio select loop { let change: ConfChange = tokio::select! { _ = shutdown_listener.wait() => break, @@ -506,6 +507,7 @@ impl CurpNode { /// This task will keep a follower up-to-data when current node is leader, /// and it will wait for `leader_event` if current node is not leader + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // tokio select internal triggered async fn sync_follower_task( curp: Arc>, connect: InnerConnectApiWrapper, @@ -521,53 +523,50 @@ impl CurpNode { let batch_timeout = curp.cfg().batch_timeout; let leader_event = curp.leader_event(); - #[allow(clippy::arithmetic_side_effects)] // tokio select internal triggered - 'outer: loop { - if !curp.is_leader() { - tokio::select! { - _ = shutdown_listener.wait_state() => return, - _ = remove_event.listen() => return, - _ = leader_event.listen() => {} - } + if !curp.is_leader() { + tokio::select! { + _ = shutdown_listener.wait_state() => return, + _ = remove_event.listen() => return, + _ = leader_event.listen() => {} } - let mut hb_opt = false; - let mut is_shutdown_state = false; - let mut ae_fail_count = 0; - loop { - // a sync is either triggered by an heartbeat timeout event or when new log entries arrive - tokio::select! { - state = shutdown_listener.wait_state(), if !is_shutdown_state => { - match state { - State::Running => unreachable!("wait state should not return Run"), - State::Shutdown => return, - State::ClusterShutdown => is_shutdown_state = true, - } - }, - _ = remove_event.listen() => return, - _now = ticker.tick() => hb_opt = false, - res = tokio::time::timeout(batch_timeout, sync_event.listen()) => { - if let Err(_e) = res { - hb_opt = true; - } + } + let mut hb_opt = false; + let mut is_shutdown_state = false; + let mut ae_fail_count = 0; + loop { + // a sync is either triggered by an heartbeat timeout event or when new log entries arrive + tokio::select! { + state = shutdown_listener.wait_state(), if !is_shutdown_state => { + match state { + State::Running => unreachable!("wait state should not return Run"), + State::Shutdown => return, + State::ClusterShutdown => is_shutdown_state = true, + } + }, + _ = remove_event.listen() => return, + _now = ticker.tick() => hb_opt = false, + res = tokio::time::timeout(batch_timeout, sync_event.listen()) => { + if let Err(_e) = res { + hb_opt = true; } } - - let Some(sync_action) = curp.sync(connect_id) else { - break 'outer; - }; - if Self::handle_sync_action( - sync_action, - &mut hb_opt, - is_shutdown_state, - &mut ae_fail_count, - connect.as_ref(), - curp.as_ref(), - ) - .await - { - break 'outer; - }; } + + let Some(sync_action) = curp.sync(connect_id) else { + break; + }; + if Self::handle_sync_action( + sync_action, + &mut hb_opt, + is_shutdown_state, + &mut ae_fail_count, + connect.as_ref(), + curp.as_ref(), + ) + .await + { + break; + }; } debug!("{} to {} sync follower task exits", curp.id(), connect.id()); } @@ -578,7 +577,8 @@ impl CurpNode { storage: Arc>, shutdown_listener: Listener, ) { - #[allow(clippy::arithmetic_side_effects)] // introduced by tokio select + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] + // introduced by tokio select loop { tokio::select! { e = log_rx.recv() => { @@ -700,7 +700,7 @@ impl CurpNode { }); let mut remove_events = HashMap::new(); - for c in curp.connects().iter() { + for c in curp.connects() { let sync_event = curp.sync_event(c.id()); let remove_event = Arc::new(Event::new()); diff --git a/crates/curp/src/server/gc.rs b/crates/curp/src/server/gc.rs index 1349b3c1c..d624f6fbd 100644 --- a/crates/curp/src/server/gc.rs +++ b/crates/curp/src/server/gc.rs @@ -13,7 +13,8 @@ pub(super) async fn gc_spec_pool( ) { let mut last_check: HashSet = sp.map_lock(|sp_l| sp_l.pool.keys().copied().collect()); - #[allow(clippy::arithmetic_side_effects)] // introduced by tokio select + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] + // introduced by tokio select loop { tokio::select! { _ = tokio::time::sleep(interval) => {} @@ -36,7 +37,8 @@ pub(super) async fn gc_cmd_board( let mut last_check_len_asr = 0; let mut last_check_len_sync = 0; let mut last_check_len_conf = 0; - #[allow(clippy::arithmetic_side_effects)] // introduced by tokio select + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] + // introduced by tokio select loop { tokio::select! { _ = tokio::time::sleep(interval) => {} diff --git a/crates/curp/src/server/raw_curp/mod.rs b/crates/curp/src/server/raw_curp/mod.rs index 11f2411bd..730d85ef4 100644 --- a/crates/curp/src/server/raw_curp/mod.rs +++ b/crates/curp/src/server/raw_curp/mod.rs @@ -942,8 +942,8 @@ impl RawCurp { // TODO: Generate client id in the same way as client let propose_id = ProposeId(rand::random(), 0); let _ignore = log_w.push(st_w.term, propose_id, EntryData::Empty); - self.recover_from_spec_pools(&mut st_w, &mut log_w, spec_pools); - self.recover_ucp_from_log(&mut log_w); + self.recover_from_spec_pools(&st_w, &mut log_w, spec_pools); + self.recover_ucp_from_log(&log_w); let last_log_index = log_w.last_log_index(); self.become_leader(&mut st_w); @@ -1593,7 +1593,7 @@ impl RawCurp { let spec_pools = cst.sps.drain().collect(); let mut log_w = RwLockUpgradableReadGuard::upgrade(log); self.recover_from_spec_pools(st, &mut log_w, spec_pools); - self.recover_ucp_from_log(&mut log_w); + self.recover_ucp_from_log(&log_w); self.become_leader(st); None } else { @@ -1673,7 +1673,7 @@ impl RawCurp { /// Recover from all voter's spec pools fn recover_from_spec_pools( &self, - st: &mut State, + st: &State, log: &mut Log, spec_pools: HashMap>>, ) { @@ -1733,7 +1733,7 @@ impl RawCurp { } /// Recover the ucp from uncommitted log entries - fn recover_ucp_from_log(&self, log: &mut Log) { + fn recover_ucp_from_log(&self, log: &Log) { let mut ucp_l = self.ctx.ucp.lock(); for i in log.commit_index + 1..=log.last_log_index() { diff --git a/crates/curp/src/server/raw_curp/tests.rs b/crates/curp/src/server/raw_curp/tests.rs index 827213497..8331ad794 100644 --- a/crates/curp/src/server/raw_curp/tests.rs +++ b/crates/curp/src/server/raw_curp/tests.rs @@ -38,6 +38,7 @@ impl RawCurp { && self.cst.lock().config.contains(id) } + #[allow(clippy::mem_forget)] // we should prevent the channel from being dropped pub(crate) fn new_test>( n: u64, exe_tx: Tx, @@ -163,12 +164,12 @@ fn leader_handle_propose_will_reject_conflicted() { let cmd2 = Arc::new(TestCommand::new_put(vec![1, 2], 1)); let res = curp.handle_propose(ProposeId(TEST_CLIENT_ID, 1), cmd2); - assert!(matches!(res, Err(CurpError::KeyConflict(_)))); + assert!(matches!(res, Err(CurpError::KeyConflict(())))); // leader will also reject cmds that conflict un-synced cmds let cmd3 = Arc::new(TestCommand::new_put(vec![2], 1)); let res = curp.handle_propose(ProposeId(TEST_CLIENT_ID, 2), cmd3); - assert!(matches!(res, Err(CurpError::KeyConflict(_)))); + assert!(matches!(res, Err(CurpError::KeyConflict(())))); } #[traced_test] @@ -186,7 +187,7 @@ fn leader_handle_propose_will_reject_duplicated() { .unwrap()); let res = curp.handle_propose(ProposeId(TEST_CLIENT_ID, 0), cmd); - assert!(matches!(res, Err(CurpError::Duplicated(_)))); + assert!(matches!(res, Err(CurpError::Duplicated(())))); } #[traced_test] @@ -237,7 +238,7 @@ fn follower_handle_propose_will_reject_conflicted() { let cmd2 = Arc::new(TestCommand::new_get(vec![1])); let res = curp.handle_propose(ProposeId(TEST_CLIENT_ID, 1), cmd2); - assert!(matches!(res, Err(CurpError::KeyConflict(_)))); + assert!(matches!(res, Err(CurpError::KeyConflict(())))); } /*************** tests for append_entries(heartbeat) **************/ diff --git a/crates/curp/src/server/storage/db.rs b/crates/curp/src/server/storage/db.rs index 1e96ccf81..0c8433080 100644 --- a/crates/curp/src/server/storage/db.rs +++ b/crates/curp/src/server/storage/db.rs @@ -53,7 +53,7 @@ impl StorageApi for DB { #[inline] async fn put_log_entry(&self, entry: &LogEntry) -> Result<(), StorageError> { let bytes = bincode::serialize(entry)?; - let op = WriteOperation::new_put(LOGS_CF, entry.index.to_be_bytes().to_vec(), bytes); + let op = WriteOperation::new_put(LOGS_CF, entry.index.to_le_bytes().to_vec(), bytes); self.db.write_batch(vec![op], false)?; Ok(()) @@ -63,14 +63,14 @@ impl StorageApi for DB { fn put_member(&self, member: &Member) -> Result<(), StorageError> { let id = member.id; let data = member.encode_to_vec(); - let op = WriteOperation::new_put(MEMBERS_CF, id.to_be_bytes().to_vec(), data); + let op = WriteOperation::new_put(MEMBERS_CF, id.to_le_bytes().to_vec(), data); self.db.write_batch(vec![op], true)?; Ok(()) } #[inline] fn remove_member(&self, id: ServerId) -> Result<(), StorageError> { - let id_bytes = id.to_be_bytes(); + let id_bytes = id.to_le_bytes(); let op = WriteOperation::new_delete(MEMBERS_CF, &id_bytes); self.db.write_batch(vec![op], true)?; Ok(()) @@ -82,17 +82,17 @@ impl StorageApi for DB { ops.push(WriteOperation::new_put( CF, CLUSTER_ID.to_vec(), - cluster_info.cluster_id().to_be_bytes().to_vec(), + cluster_info.cluster_id().to_le_bytes().to_vec(), )); ops.push(WriteOperation::new_put( CF, MEMBER_ID.to_vec(), - cluster_info.self_id().to_be_bytes().to_vec(), + cluster_info.self_id().to_le_bytes().to_vec(), )); for m in cluster_info.all_members_vec() { ops.push(WriteOperation::new_put( MEMBERS_CF, - m.id.to_be_bytes().to_vec(), + m.id.to_le_bytes().to_vec(), m.encode_to_vec(), )); } @@ -103,7 +103,7 @@ impl StorageApi for DB { #[inline] fn recover_cluster_info(&self) -> Result, StorageError> { let cluster_id = self.db.get(CF, CLUSTER_ID)?.map(|bytes| { - u64::from_be_bytes( + u64::from_le_bytes( bytes .as_slice() .try_into() @@ -111,7 +111,7 @@ impl StorageApi for DB { ) }); let member_id = self.db.get(CF, MEMBER_ID)?.map(|bytes| { - u64::from_be_bytes( + u64::from_le_bytes( bytes .as_slice() .try_into() diff --git a/crates/curp/src/server/storage/mod.rs b/crates/curp/src/server/storage/mod.rs index e5e935ba1..029a09415 100644 --- a/crates/curp/src/server/storage/mod.rs +++ b/crates/curp/src/server/storage/mod.rs @@ -44,25 +44,45 @@ pub trait StorageApi: Send + Sync { type Command: Command; /// Put `voted_for` into storage, must be flushed on disk before returning + /// + /// # Errors + /// Return `StorageError` when it failed to store the `voted_for` info to underlying database. async fn flush_voted_for(&self, term: u64, voted_for: ServerId) -> Result<(), StorageError>; /// Put `Member` into storage + /// + /// # Errors + /// Return `StorageError` when it failed to store the member info to underlying database. fn put_member(&self, member: &Member) -> Result<(), StorageError>; /// Remove `Member` from storage + /// + /// # Errors + /// Return `StorageError` when it failed to remove the member info from underlying database. fn remove_member(&self, id: ServerId) -> Result<(), StorageError>; /// Put `ClusterInfo` into storage + /// + /// # Errors + /// Return `StorageError` when it failed to store the cluster info to underlying database. fn put_cluster_info(&self, cluster_info: &ClusterInfo) -> Result<(), StorageError>; /// Recover `ClusterInfo` from storage + /// + /// # Errors + /// Return `StorageError` when it failed to recover the cluster info from underlying database. fn recover_cluster_info(&self) -> Result, StorageError>; /// Put log entries in storage + /// + /// # Errors + /// Return `StorageError` when it failed to store the given log entry info to underlying database. async fn put_log_entry(&self, entry: &LogEntry) -> Result<(), StorageError>; /// Recover from persisted storage - /// Return `voted_for` and all log entries + /// + /// # Errors + /// Return `StorageError` when it failed to recover from underlying database. Otherwise, return recovered `voted_for` and all log entries async fn recover( &self, ) -> Result<(Option<(u64, ServerId)>, Vec>), StorageError>; diff --git a/crates/curp/src/server/storage/wal/codec.rs b/crates/curp/src/server/storage/wal/codec.rs index d3edda801..4083cb4b4 100644 --- a/crates/curp/src/server/storage/wal/codec.rs +++ b/crates/curp/src/server/storage/wal/codec.rs @@ -301,7 +301,7 @@ impl FrameType for CommitFrame { impl FrameEncoder for CommitFrame { fn encode(&self) -> Vec { - let header = std::iter::once(self.frame_type()).chain([0u8; 7].into_iter()); + let header = std::iter::once(self.frame_type()).chain([0u8; 7]); header.chain(self.checksum.clone()).collect() } } diff --git a/crates/curp/src/server/storage/wal/segment.rs b/crates/curp/src/server/storage/wal/segment.rs index 525ef3aa5..3a7035c4b 100644 --- a/crates/curp/src/server/storage/wal/segment.rs +++ b/crates/curp/src/server/storage/wal/segment.rs @@ -347,7 +347,7 @@ impl Eq for WALSegment {} impl PartialOrd for WALSegment { fn partial_cmp(&self, other: &Self) -> Option { - self.segment_id.partial_cmp(&other.segment_id) + Some(self.cmp(other)) } } diff --git a/crates/engine/src/api/engine_api.rs b/crates/engine/src/api/engine_api.rs index 71f34fde1..626377f65 100644 --- a/crates/engine/src/api/engine_api.rs +++ b/crates/engine/src/api/engine_api.rs @@ -72,5 +72,8 @@ pub trait StorageEngine: Send + Sync + 'static + std::fmt::Debug { fn estimated_file_size(&self) -> u64; /// Get the file size of the engine (Measured in bytes) + /// + /// # Errors + /// Return `EngineError` if met some errors when get file size fn file_size(&self) -> Result; } diff --git a/crates/engine/src/api/snapshot_api.rs b/crates/engine/src/api/snapshot_api.rs index b4f72f6d8..71d4a421c 100644 --- a/crates/engine/src/api/snapshot_api.rs +++ b/crates/engine/src/api/snapshot_api.rs @@ -11,6 +11,9 @@ pub trait SnapshotApi: Send + Sync + std::fmt::Debug { fn size(&self) -> u64; /// Rewind the snapshot to the beginning + /// + /// # Errors + /// Return `IO::Error` when `rewind` went wrong fn rewind(&mut self) -> io::Result<()>; /// Pull some bytes of the snapshot to the given uninitialized buffer diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 6367808c7..0c2a5cee2 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -43,6 +43,7 @@ clippy::pedantic, clippy::cargo, + // The followings are selected restriction lints for rust 1.57 clippy::as_conversions, clippy::clone_on_ref_ptr, @@ -125,17 +126,23 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, )] #![allow( clippy::multiple_crate_versions, // caused by the dependency, can't be fixed diff --git a/crates/engine/src/memory_engine/mod.rs b/crates/engine/src/memory_engine/mod.rs index d5d964ac6..7260e9681 100644 --- a/crates/engine/src/memory_engine/mod.rs +++ b/crates/engine/src/memory_engine/mod.rs @@ -38,7 +38,7 @@ impl MemoryEngine { pub(crate) fn new(tables: &[&'static str]) -> Self { let mut inner: HashMap, Vec>> = HashMap::new(); for table in tables { - let _ignore = inner.entry((*table).to_owned()).or_insert(HashMap::new()); + let _ignore = inner.entry((*table).to_owned()).or_default(); } Self { inner: Arc::new(RwLock::new(inner)), diff --git a/crates/simulation/tests/it/curp/server_recovery.rs b/crates/simulation/tests/it/curp/server_recovery.rs index df251a939..d62508d4b 100644 --- a/crates/simulation/tests/it/curp/server_recovery.rs +++ b/crates/simulation/tests/it/curp/server_recovery.rs @@ -330,7 +330,7 @@ async fn old_leader_will_keep_original_states() { .unwrap(); assert_eq!( res, - vec![(0u32.to_be_bytes().to_vec(), 0u32.to_be_bytes().to_vec())] + vec![(0u32.to_le_bytes().to_vec(), 0u32.to_le_bytes().to_vec())] ); // 5: the client should also get the original state @@ -460,7 +460,7 @@ async fn recovery_after_compaction() { { let node = group.nodes.get_mut(&node_id).unwrap(); for i in 0..50_u32 { - let kv = i.to_be_bytes().to_vec(); + let kv = i.to_le_bytes().to_vec(); let val = node .store .lock() diff --git a/crates/utils/src/config.rs b/crates/utils/src/config.rs index e6c484672..c98af4e74 100644 --- a/crates/utils/src/config.rs +++ b/crates/utils/src/config.rs @@ -1386,7 +1386,7 @@ mod tests { #[test] fn test_xline_server_default_config_should_be_loaded() { let config: XlineServerConfig = toml::from_str( - r#"[cluster] + "[cluster] name = 'node1' is_leader = true peer_listen_urls = ['127.0.0.1:2380'] @@ -1418,7 +1418,7 @@ mod tests { [auth] [tls] - "#, + ", ) .unwrap(); @@ -1475,7 +1475,7 @@ mod tests { #[test] fn test_auto_revision_compactor_config_should_be_loaded() { let config: XlineServerConfig = toml::from_str( - r#"[cluster] + "[cluster] name = 'node1' is_leader = true peer_listen_urls = ['127.0.0.1:2380'] @@ -1511,7 +1511,7 @@ mod tests { [auth] [tls] - "#, + ", ) .unwrap(); diff --git a/crates/utils/src/interval_map/tests.rs b/crates/utils/src/interval_map/tests.rs index 0e864076b..ca63a5c51 100644 --- a/crates/utils/src/interval_map/tests.rs +++ b/crates/utils/src/interval_map/tests.rs @@ -124,7 +124,7 @@ fn red_black_tree_properties_is_satisfied() { } #[test] -#[should_panic] +#[should_panic(expected = "invalid range")] fn invalid_range_should_panic() { let _interval = Interval::new(3, 1); } diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 5434aaed3..b3296b9cd 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -44,6 +44,7 @@ clippy::pedantic, clippy::cargo, + // The followings are selected restriction lints for rust 1.57 clippy::as_conversions, clippy::clone_on_ref_ptr, @@ -126,17 +127,24 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, + )] #![allow( clippy::multiple_crate_versions, // caused by the dependency, can't be fixed diff --git a/crates/xline-client/src/lease_gen.rs b/crates/xline-client/src/lease_gen.rs index b59a5d547..88050492a 100644 --- a/crates/xline-client/src/lease_gen.rs +++ b/crates/xline-client/src/lease_gen.rs @@ -24,7 +24,7 @@ impl LeaseIdGenerator { getrandom::getrandom(&mut buf).unwrap_or_else(|err| { panic!("Failed to generate random bytes for lease id generator: {err}"); }); - let id = AtomicU64::new(u64::from_be_bytes(buf)); + let id = AtomicU64::new(u64::from_le_bytes(buf)); Self { id } } diff --git a/crates/xline-client/src/lib.rs b/crates/xline-client/src/lib.rs index edb6ad244..11f780cdc 100644 --- a/crates/xline-client/src/lib.rs +++ b/crates/xline-client/src/lib.rs @@ -44,6 +44,7 @@ clippy::pedantic, clippy::cargo, + // The followings are selected restriction lints for rust 1.57 clippy::as_conversions, clippy::clone_on_ref_ptr, @@ -126,21 +127,27 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, )] #![allow( clippy::multiple_crate_versions, // caused by the dependency, can't be fixed clippy::module_name_repetitions, // It will be more easy to use for the type name prefixed by module name + clippy::missing_fields_in_debug, )] #![cfg_attr( test, diff --git a/crates/xline/src/lib.rs b/crates/xline/src/lib.rs index 16ee9d5cc..b8d10db51 100644 --- a/crates/xline/src/lib.rs +++ b/crates/xline/src/lib.rs @@ -126,22 +126,29 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, )] #![allow( clippy::panic, // allow debug_assert, panic in production code clippy::multiple_crate_versions, // caused by the dependency, can't be fixed clippy::module_name_repetitions, // TODO: refactor module to remove this + clippy::missing_fields_in_debug, // we don't need to print all fields in some data structures )] #![cfg_attr( test, diff --git a/crates/xline/src/main.rs b/crates/xline/src/main.rs index f4294071d..c9ac06ac1 100644 --- a/crates/xline/src/main.rs +++ b/crates/xline/src/main.rs @@ -126,7 +126,6 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, @@ -153,7 +152,7 @@ use xline::{ }; #[tokio::main] -#[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! +#[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! async fn main() -> Result<()> { global::set_text_map_propagator(TraceContextPropagator::new()); let config = parse_config().await?; diff --git a/crates/xline/src/metrics.rs b/crates/xline/src/metrics.rs index 3bacc729c..3abc0fc62 100644 --- a/crates/xline/src/metrics.rs +++ b/crates/xline/src/metrics.rs @@ -75,8 +75,8 @@ impl Metrics { _ = meter.register_callback( &[current_version.as_any(), current_rust_version.as_any()], move |observer| { - let crate_version: &str = env!("CARGO_PKG_VERSION"); - let rust_version: &str = env!("CARGO_PKG_RUST_VERSION"); + let crate_version = env!("CARGO_PKG_VERSION"); + let rust_version = env!("CARGO_PKG_RUST_VERSION"); observer.observe_u64( ¤t_version, 1, diff --git a/crates/xline/src/server/barriers.rs b/crates/xline/src/server/barriers.rs index 2a22a2a5b..a6dce1c58 100644 --- a/crates/xline/src/server/barriers.rs +++ b/crates/xline/src/server/barriers.rs @@ -30,11 +30,7 @@ impl IndexBarrier { if inner_l.last_trigger_index >= index { return; } - inner_l - .barriers - .entry(index) - .or_insert_with(Event::new) - .listen() + inner_l.barriers.entry(index).or_default().listen() }; listener.await; } @@ -79,12 +75,7 @@ impl IdBarrier { /// Wait for the id until it is triggered. pub(crate) async fn wait(&self, id: InflightId) { - let listener = self - .barriers - .lock() - .entry(id) - .or_insert_with(Event::new) - .listen(); + let listener = self.barriers.lock().entry(id).or_default().listen(); listener.await; } diff --git a/crates/xline/src/server/lease_server.rs b/crates/xline/src/server/lease_server.rs index 5b46a1627..f59a4a914 100644 --- a/crates/xline/src/server/lease_server.rs +++ b/crates/xline/src/server/lease_server.rs @@ -85,7 +85,7 @@ where } /// Task of revoke expired leases - #[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! async fn revoke_expired_leases_task( lease_server: Arc>, shutdown_listener: Listener, @@ -149,8 +149,8 @@ where } /// Handle keep alive at leader - #[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! - async fn leader_keep_alive( + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! + fn leader_keep_alive( &self, mut request_stream: tonic::Streaming, ) -> Pin> + Send>> { @@ -198,7 +198,7 @@ where } /// Handle keep alive at follower - #[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! async fn follower_keep_alive( &self, mut request_stream: tonic::Streaming, @@ -325,7 +325,7 @@ where let request_stream = request.into_inner(); let stream = loop { if self.lease_storage.is_primary() { - break self.leader_keep_alive(request_stream).await; + break self.leader_keep_alive(request_stream); } let leader_id = self.client.fetch_leader_id(false).await?; // Given that a candidate server may become a leader when it won the election or diff --git a/crates/xline/src/server/watch_server.rs b/crates/xline/src/server/watch_server.rs index 2b071aa62..67a6d50a7 100644 --- a/crates/xline/src/server/watch_server.rs +++ b/crates/xline/src/server/watch_server.rs @@ -65,7 +65,7 @@ where } /// bg task for handle watch connection - #[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! async fn task( next_id_gen: Arc, kv_watcher: Arc, diff --git a/crates/xline/src/server/xline_server.rs b/crates/xline/src/server/xline_server.rs index 65c694505..c43684800 100644 --- a/crates/xline/src/server/xline_server.rs +++ b/crates/xline/src/server/xline_server.rs @@ -716,5 +716,5 @@ fn bind_addrs( .map_err(|e| anyhow::anyhow!("Failed to bind to {}, err: {e}", addr)) }) .collect::>>()?; - Ok(futures::stream::select_all(incoming.into_iter())) + Ok(futures::stream::select_all(incoming)) } diff --git a/crates/xline/src/storage/alarm_store.rs b/crates/xline/src/storage/alarm_store.rs index cacff460e..eccc9a10a 100644 --- a/crates/xline/src/storage/alarm_store.rs +++ b/crates/xline/src/storage/alarm_store.rs @@ -197,7 +197,7 @@ where /// Sync alarm activate request fn sync_alarm_activate(&self, member_id: ServerId, alarm: AlarmType) -> Vec { - let new_alarm: AlarmMember = AlarmMember::new(member_id, alarm); + let new_alarm = AlarmMember::new(member_id, alarm); let mut types_w = self.types.write(); let e = types_w.entry(alarm).or_default(); let mut ops = vec![]; diff --git a/crates/xline/src/storage/auth_store/store.rs b/crates/xline/src/storage/auth_store/store.rs index 700b1f093..e91c23776 100644 --- a/crates/xline/src/storage/auth_store/store.rs +++ b/crates/xline/src/storage/auth_store/store.rs @@ -80,7 +80,7 @@ where S: StorageApi, { /// New `AuthStore` - #[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! pub(crate) fn new( lease_collection: Arc, key_pair: Option<(EncodingKey, DecodingKey)>, @@ -164,7 +164,7 @@ where permission_cache .role_to_users_map .entry(role) - .or_insert_with(Vec::new) + .or_default() .push(username.clone()); } let _ignore = permission_cache @@ -712,17 +712,14 @@ where if let Ok(role) = role { let perms = role.key_permission; self.permission_cache.map_write(|mut cache| { - let entry = cache - .user_permissions - .entry(req.user.clone()) - .or_insert_with(UserPermissions::new); + let entry = cache.user_permissions.entry(req.user.clone()).or_default(); for perm in perms { entry.insert(perm); } cache .role_to_users_map .entry(req.role.clone()) - .or_insert_with(Vec::new) + .or_default() .push(req.user.clone()); }); } @@ -795,7 +792,7 @@ where } } self.permission_cache.map_write(|mut cache| { - cache.user_permissions.extend(new_perms.into_iter()); + cache.user_permissions.extend(new_perms); let _ignore = cache.role_to_users_map.remove(&req.role); }); Ok(ops) @@ -833,10 +830,7 @@ where .cloned() .unwrap_or_default(); for user in users { - let entry = cache - .user_permissions - .entry(user) - .or_insert_with(UserPermissions::new); + let entry = cache.user_permissions.entry(user).or_default(); entry.insert(permission.clone()); } }); @@ -993,7 +987,7 @@ where Err(e) } }, - |_| Ok(()), + |()| Ok(()), )?; } RequestWrapper::AuthRoleGetRequest(ref role_get_req) => { @@ -1006,7 +1000,7 @@ where Err(e) } }, - |_| Ok(()), + |()| Ok(()), )?; } _ => {} diff --git a/crates/xline/src/storage/compact/mod.rs b/crates/xline/src/storage/compact/mod.rs index 772a76088..ec2594d28 100644 --- a/crates/xline/src/storage/compact/mod.rs +++ b/crates/xline/src/storage/compact/mod.rs @@ -96,7 +96,7 @@ pub(crate) async fn auto_compactor( } /// background compact executor -#[allow(clippy::arithmetic_side_effects)] // introduced bt tokio::select! macro +#[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // introduced bt tokio::select! macro pub(crate) async fn compact_bg_task( kv_store: Arc>, index: Arc, diff --git a/crates/xline/src/storage/compact/periodic_compactor.rs b/crates/xline/src/storage/compact/periodic_compactor.rs index f7206e4fb..1dd502c84 100644 --- a/crates/xline/src/storage/compact/periodic_compactor.rs +++ b/crates/xline/src/storage/compact/periodic_compactor.rs @@ -153,7 +153,7 @@ fn sample_config(period: Duration) -> (Duration, usize) { #[async_trait::async_trait] impl Compactor for PeriodicCompactor { - #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] async fn run(&self, shutdown_listener: Listener) { let mut last_revision: Option = None; let (sample_frequency, sample_total) = sample_config(self.period); diff --git a/crates/xline/src/storage/compact/revision_compactor.rs b/crates/xline/src/storage/compact/revision_compactor.rs index 48916ceef..149830a39 100644 --- a/crates/xline/src/storage/compact/revision_compactor.rs +++ b/crates/xline/src/storage/compact/revision_compactor.rs @@ -98,7 +98,7 @@ impl Compactor for RevisionCompactor { self.is_leader.store(true, Relaxed); } - #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] async fn run(&self, shutdown_listener: Listener) { let mut last_revision = None; let mut ticker = tokio::time::interval(CHECK_INTERVAL); diff --git a/crates/xline/src/storage/index.rs b/crates/xline/src/storage/index.rs index 3f34166d4..e6d903abd 100644 --- a/crates/xline/src/storage/index.rs +++ b/crates/xline/src/storage/index.rs @@ -334,7 +334,7 @@ impl IndexOperate for Index { } else { revisions.drain(..compacted_last_idx) }; - revs.extend(compact_revs.into_iter()); + revs.extend(compact_revs); if revisions.is_empty() { del_keys.push(entry.key().clone()); diff --git a/crates/xline/src/storage/kvwatcher.rs b/crates/xline/src/storage/kvwatcher.rs index 803ac3c59..bdb65737c 100644 --- a/crates/xline/src/storage/kvwatcher.rs +++ b/crates/xline/src/storage/kvwatcher.rs @@ -148,7 +148,7 @@ impl Watcher { }; match self.event_tx.try_send(watch_event) { - Ok(_) => { + Ok(()) => { let _ignore = self.notified_set.insert(revision); Ok(()) } @@ -210,10 +210,7 @@ impl WatcherMap { "can't insert a watcher to watchers twice" ); assert!( - self.index - .entry(key_range) - .or_insert_with(HashSet::new) - .insert(watch_id), + self.index.entry(key_range).or_default().insert(watch_id), "can't insert a watcher to index twice" ); } @@ -414,7 +411,7 @@ where } /// Background task to handle KV updates - #[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! async fn kv_updates_task( kv_watcher: Arc>, mut kv_update_rx: mpsc::Receiver<(i64, Vec)>, @@ -438,7 +435,7 @@ where } /// Background task to sync victims - #[allow(clippy::arithmetic_side_effects)] // Introduced by tokio::select! + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] // Introduced by tokio::select! async fn sync_victims_task( kv_watcher: Arc>, sync_victims_interval: Duration, diff --git a/crates/xlineapi/src/lib.rs b/crates/xlineapi/src/lib.rs index 5497a7651..f8669f7ff 100644 --- a/crates/xlineapi/src/lib.rs +++ b/crates/xlineapi/src/lib.rs @@ -130,13 +130,20 @@ clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, - // 1.71.0 - clippy::default_constructed_unit_structs, - clippy::items_after_test_module, - clippy::manual_next_back, - clippy::manual_while_let_some, - clippy::needless_bool_assign, - clippy::non_minimal_cfg, + + // The followings are selected lints from 1.71.0 to 1.74.0 + clippy::large_stack_frames, + clippy::tuple_array_conversions, + clippy::pub_without_shorthand, + clippy::needless_raw_strings, + clippy::redundant_type_annotations, + clippy::host_endian_bytes, + clippy::big_endian_bytes, + clippy::error_impl_error, + clippy::string_lit_chars_any, + clippy::needless_pass_by_ref_mut, + clippy::redundant_as_str, + clippy::missing_asserts_for_indexing, )] // Skip for generated code #![allow( diff --git a/crates/xlinectl/src/command/lease/keep_alive.rs b/crates/xlinectl/src/command/lease/keep_alive.rs index a34884be9..7e65c0339 100644 --- a/crates/xlinectl/src/command/lease/keep_alive.rs +++ b/crates/xlinectl/src/command/lease/keep_alive.rs @@ -34,7 +34,8 @@ pub(super) async fn execute(client: &mut Client, matches: &ArgMatches) -> Result let (mut keeper, mut stream) = client.lease_client().keep_alive(req).await?; - #[allow(clippy::arithmetic_side_effects)] // introduced by tokio::select + #[allow(clippy::arithmetic_side_effects, clippy::ignored_unit_patterns)] + // introduced by tokio::select if once { keeper.keep_alive()?; if let Some(resp) = stream.message().await? { diff --git a/crates/xlinectl/src/command/txn.rs b/crates/xlinectl/src/command/txn.rs index 2dae556cb..d96798baa 100644 --- a/crates/xlinectl/src/command/txn.rs +++ b/crates/xlinectl/src/command/txn.rs @@ -190,11 +190,11 @@ mod tests { TxnOp::put(PutRequest::new("key1", "created-key1")) ); assert_eq!( - parse_op_line(r#"get key1 key11"#).unwrap(), + parse_op_line(r"get key1 key11").unwrap(), TxnOp::range(RangeRequest::new("key1").with_range_end("key11")) ); assert_eq!( - parse_op_line(r#"get key1 --from_key"#).unwrap(), + parse_op_line(r"get key1 --from_key").unwrap(), TxnOp::range(RangeRequest::new("key1").with_from_key()) ); } diff --git a/crates/xlinectl/src/main.rs b/crates/xlinectl/src/main.rs index e6f37b0c0..42fbd82b3 100644 --- a/crates/xlinectl/src/main.rs +++ b/crates/xlinectl/src/main.rs @@ -126,7 +126,6 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module, diff --git a/crates/xlineutl/src/main.rs b/crates/xlineutl/src/main.rs index d8f62fa90..a706d865b 100644 --- a/crates/xlineutl/src/main.rs +++ b/crates/xlineutl/src/main.rs @@ -126,7 +126,6 @@ clippy::impl_trait_in_params, clippy::let_underscore_untyped, clippy::missing_assert_message, - clippy::multiple_unsafe_ops_per_block, clippy::semicolon_inside_block, // clippy::semicolon_outside_block, already used `semicolon_inside_block` clippy::tests_outside_test_module,