diff --git a/aerospike-core/Cargo.toml b/aerospike-core/Cargo.toml index c34737da..5fa83405 100644 --- a/aerospike-core/Cargo.toml +++ b/aerospike-core/Cargo.toml @@ -13,7 +13,8 @@ base64 = "0.11" crossbeam-queue = "0.2" rand = "0.7" lazy_static = "1.4" -error-chain = "0.12" +# error-chain = "0.12" +thiserror = "1.0.40" pwhash = "0.3" serde = { version = "1.0", features = ["derive"], optional = true } aerospike-rt = {path = "../aerospike-rt"} diff --git a/aerospike-core/src/client.rs b/aerospike-core/src/client.rs index f9e0751d..04527db8 100644 --- a/aerospike-core/src/client.rs +++ b/aerospike-core/src/client.rs @@ -24,7 +24,7 @@ use crate::commands::{ DeleteCommand, ExecuteUDFCommand, ExistsCommand, OperateCommand, QueryCommand, ReadCommand, ScanCommand, TouchCommand, WriteCommand, }; -use crate::errors::{ErrorKind, Result, ResultExt}; +use crate::errors::{Error, Result}; use crate::net::ToHosts; use crate::operations::{Operation, OperationType}; use crate::policy::{BatchPolicy, ClientPolicy, QueryPolicy, ReadPolicy, ScanPolicy, WritePolicy}; @@ -148,7 +148,7 @@ impl Client { /// match client.get(&ReadPolicy::default(), &key, ["a", "b"]).await { /// Ok(record) /// => println!("a={:?}", record.bins.get("a")), - /// Err(Error(ErrorKind::ServerError(ResultCode::KeyNotFoundError), _)) + /// Err(Error::ServerError(ResultCode::KeyNotFoundError)) /// => println!("No such record: {}", key), /// Err(err) /// => println!("Error fetching record: {}", err), @@ -170,7 +170,7 @@ impl Client { /// Some(duration) => println!("ttl: {} secs", duration.as_secs()), /// } /// }, - /// Err(Error(ErrorKind::ServerError(ResultCode::KeyNotFoundError), _)) + /// Err(Error::ServerError(ResultCode::KeyNotFoundError)) /// => println!("No such record: {}", key), /// Err(err) /// => println!("Error fetching record: {}", err), @@ -495,13 +495,13 @@ impl Client { if let Some(msg) = response.get("error") { let msg = base64::decode(msg)?; let msg = str::from_utf8(&msg)?; - bail!( + return Err(Error::UdfBadResponse(format!( "UDF Registration failed: {}, file: {}, line: {}, message: {}", response.get("error").unwrap_or(&"-".to_string()), response.get("file").unwrap_or(&"-".to_string()), response.get("line").unwrap_or(&"-".to_string()), msg - ); + ))); } Ok(RegisterTask::new( @@ -539,7 +539,12 @@ impl Client { match response.get(&cmd).map(String::as_str) { Some("ok") => Ok(()), - _ => bail!("UDF Remove failed: {:?}", response), + _ => { + return Err(Error::UdfBadResponse(format!( + "UDF Remove failed: {:?}", + response + ))) + } } } @@ -578,11 +583,11 @@ impl Client { if key.contains("SUCCESS") { return Ok(Some(value.clone())); } else if key.contains("FAILURE") { - bail!("{:?}", value); + return Err(Error::UdfBadResponse(value.to_string())); } } - Err("Invalid UDF return value".into()) + Err(Error::UdfBadResponse("Invalid UDF return value".into())) } /// Read all records in the specified namespace and set and return a record iterator. The scan @@ -808,7 +813,7 @@ impl Client { self.send_info_cmd(&cmd) .await - .chain_err(|| "Error truncating ns/set") + .map_err(|e| e.chain_error("Error truncating ns/set")) } /// Create a secondary index on a bin containing scalar values. This asynchronous server call @@ -879,7 +884,7 @@ impl Client { ); self.send_info_cmd(&cmd) .await - .chain_err(|| "Error creating index") + .map_err(|e| e.chain_error("Error creating index")) } /// Delete secondary index. @@ -900,7 +905,7 @@ impl Client { ); self.send_info_cmd(&cmd) .await - .chain_err(|| "Error dropping index") + .map_err(|e| e.chain_error("Error dropping index")) } async fn send_info_cmd(&self, cmd: &str) -> Result<()> { @@ -912,12 +917,12 @@ impl Client { return Ok(()); } else if v.starts_with("FAIL:") { let result = v.split(':').nth(1).unwrap().parse::()?; - bail!(ErrorKind::ServerError(ResultCode::from(result))); + return Err(Error::ServerError(ResultCode::from(result))); } } - bail!(ErrorKind::BadResponse( - "Unexpected sindex info command response".to_string() - )) + return Err(Error::BadResponse( + "Unexpected sindex info command response".to_string(), + )); } } diff --git a/aerospike-core/src/cluster/mod.rs b/aerospike-core/src/cluster/mod.rs index a3127649..83c2e9c0 100644 --- a/aerospike-core/src/cluster/mod.rs +++ b/aerospike-core/src/cluster/mod.rs @@ -30,7 +30,7 @@ use self::node_validator::NodeValidator; use self::partition::Partition; use self::partition_tokenizer::PartitionTokenizer; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Host; use crate::policy::ClientPolicy; use aerospike_rt::RwLock; @@ -84,11 +84,11 @@ impl Cluster { // apply policy rules if cluster.client_policy.fail_if_not_connected && !cluster.is_connected().await { - bail!(ErrorKind::Connection( + return Err(Error::Connection( "Failed to connect to host(s). The network \ connection(s) to cluster nodes may have timed out, or \ the cluster may be in a state of flux." - .to_string() + .to_string(), )); } @@ -201,9 +201,9 @@ impl Cluster { }); #[cfg(all(feature = "rt-tokio", not(feature = "rt-async-std")))] - return handle - .await - .map_err(|err| format!("Error during initial cluster tend: {:?}", err).into()); + return handle.await.map_err(|err| { + Error::InvalidArgument(format!("Error during initial cluster tend: {:?}", err).into()) + }); #[cfg(all(feature = "rt-async-std", not(feature = "rt-tokio")))] return { handle.await; @@ -518,7 +518,7 @@ impl Cluster { } } - bail!("No active node") + return Err(Error::Connection("No active node".into())); } pub async fn get_node_by_name(&self, node_name: &str) -> Result> { @@ -530,7 +530,9 @@ impl Cluster { } } - bail!("Requested node `{}` not found.", node_name) + return Err(Error::InvalidNode(format!( + "Requested node `{node_name}` not found." + ))); } pub async fn close(&self) -> Result<()> { diff --git a/aerospike-core/src/cluster/node.rs b/aerospike-core/src/cluster/node.rs index b2f4b602..6df456fd 100644 --- a/aerospike-core/src/cluster/node.rs +++ b/aerospike-core/src/cluster/node.rs @@ -23,7 +23,7 @@ use std::sync::Arc; use crate::cluster::node_validator::NodeValidator; use crate::commands::Message; -use crate::errors::{ErrorKind, Result, ResultExt}; +use crate::errors::{Error, Result}; use crate::net::{ConnectionPool, Host, PooledConnection}; use crate::policy::ClientPolicy; use aerospike_rt::RwLock; @@ -129,15 +129,15 @@ impl Node { let info_map = self .info(&commands) .await - .chain_err(|| "Info command failed")?; + .map_err(|e| e.chain_error("Info command failed"))?; self.validate_node(&info_map) - .chain_err(|| "Failed to validate node")?; + .map_err(|e| e.chain_error("Failed to validate node"))?; self.responded.store(true, Ordering::Relaxed); let friends = self .add_friends(current_aliases, &info_map) - .chain_err(|| "Failed to add friends")?; + .map_err(|e| e.chain_error("Failed to add friends"))?; self.update_partitions(&info_map) - .chain_err(|| "Failed to update partitions")?; + .map_err(|e| e.chain_error("Failed to update partitions"))?; self.reset_failures(); Ok(friends) } @@ -159,11 +159,11 @@ impl Node { fn verify_node_name(&self, info_map: &HashMap) -> Result<()> { match info_map.get("node") { - None => Err(ErrorKind::InvalidNode("Missing node name".to_string()).into()), + None => Err(Error::InvalidNode("Missing node name".to_string()).into()), Some(info_name) if info_name == &self.name => Ok(()), Some(info_name) => { self.inactivate(); - Err(ErrorKind::InvalidNode(format!( + Err(Error::InvalidNode(format!( "Node name has changed: '{}' => '{}'", self.name, info_name )) @@ -176,11 +176,11 @@ impl Node { match self.client_policy.cluster_name { None => Ok(()), Some(ref expected) => match info_map.get("cluster-name") { - None => Err(ErrorKind::InvalidNode("Missing cluster name".to_string()).into()), + None => Err(Error::InvalidNode("Missing cluster name".to_string()).into()), Some(info_name) if info_name == expected => Ok(()), Some(info_name) => { self.inactivate(); - Err(ErrorKind::InvalidNode(format!( + Err(Error::InvalidNode(format!( "Cluster name mismatch: expected={}, got={}", expected, info_name @@ -199,7 +199,7 @@ impl Node { let mut friends: Vec = vec![]; let friend_string = match info_map.get(self.services_name()) { - None => bail!(ErrorKind::BadResponse("Missing services list".to_string())), + None => return Err(Error::BadResponse("Missing services list".to_string())), Some(friend_string) if friend_string.is_empty() => return Ok(friends), Some(friend_string) => friend_string, }; @@ -237,9 +237,11 @@ impl Node { fn update_partitions(&self, info_map: &HashMap) -> Result<()> { match info_map.get("partition-generation") { - None => bail!(ErrorKind::BadResponse( - "Missing partition generation".to_string() - )), + None => { + return Err(Error::BadResponse( + "Missing partition generation".to_string(), + )) + } Some(gen_string) => { let gen = gen_string.parse::()?; self.partition_generation.store(gen, Ordering::Relaxed); diff --git a/aerospike-core/src/cluster/node_validator.rs b/aerospike-core/src/cluster/node_validator.rs index 6739c4f6..83e73556 100644 --- a/aerospike-core/src/cluster/node_validator.rs +++ b/aerospike-core/src/cluster/node_validator.rs @@ -18,7 +18,7 @@ use std::vec::Vec; use crate::cluster::Cluster; use crate::commands::Message; -use crate::errors::{ErrorKind, Result, ResultExt}; +use crate::errors::{Error, Result}; use crate::net::{Connection, Host}; use crate::policy::ClientPolicy; @@ -55,7 +55,7 @@ impl NodeValidator { pub async fn validate_node(&mut self, cluster: &Cluster, host: &Host) -> Result<()> { self.resolve_aliases(host) - .chain_err(|| "Failed to resolve host aliases")?; + .map_err(|e| e.chain_error("Failed to resolve host aliases"))?; let mut last_err = None; for alias in &self.aliases() { @@ -84,7 +84,7 @@ impl NodeValidator { .collect(); debug!("Resolved aliases for host {}: {:?}", host, self.aliases); if self.aliases.is_empty() { - Err(ErrorKind::Connection(format!("Failed to find addresses for {}", host)).into()) + Err(Error::Connection(format!("Failed to find addresses for {}", host)).into()) } else { Ok(()) } @@ -95,19 +95,21 @@ impl NodeValidator { let info_map = Message::info(&mut conn, &["node", "cluster-name", "features"]).await?; match info_map.get("node") { - None => bail!(ErrorKind::InvalidNode(String::from("Missing node name"))), + None => return Err(Error::InvalidNode(String::from("Missing node name"))), Some(node_name) => self.name = node_name.clone(), } if let Some(ref cluster_name) = *cluster.cluster_name() { match info_map.get("cluster-name") { - None => bail!(ErrorKind::InvalidNode(String::from("Missing cluster name"))), + None => return Err(Error::InvalidNode(String::from("Missing cluster name"))), Some(info_name) if info_name == cluster_name => {} - Some(info_name) => bail!(ErrorKind::InvalidNode(format!( - "Cluster name mismatch: expected={}, + Some(info_name) => { + return Err(Error::InvalidNode(format!( + "Cluster name mismatch: expected={}, got={}", - cluster_name, info_name - ))), + cluster_name, info_name + ))) + } } } diff --git a/aerospike-core/src/cluster/partition_tokenizer.rs b/aerospike-core/src/cluster/partition_tokenizer.rs index ae0b57f1..686ab054 100644 --- a/aerospike-core/src/cluster/partition_tokenizer.rs +++ b/aerospike-core/src/cluster/partition_tokenizer.rs @@ -21,7 +21,7 @@ use std::vec::Vec; use crate::cluster::node; use crate::cluster::Node; use crate::commands::Message; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use aerospike_rt::RwLock; @@ -45,7 +45,7 @@ impl PartitionTokenizer { offset: 0, }); } - bail!(ErrorKind::BadResponse("Missing replicas info".to_string())) + return Err(Error::BadResponse("Missing replicas info".to_string())) } pub async fn update_partition( @@ -76,7 +76,7 @@ impl PartitionTokenizer { } } (None, None) => break, - _ => bail!(ErrorKind::BadResponse( + _ => return Err(Error::BadResponse( "Error parsing partition info".to_string() )), } diff --git a/aerospike-core/src/commands/admin_command.rs b/aerospike-core/src/commands/admin_command.rs index 19d60788..b0b90288 100644 --- a/aerospike-core/src/commands/admin_command.rs +++ b/aerospike-core/src/commands/admin_command.rs @@ -19,7 +19,7 @@ use std::str; use pwhash::bcrypt::{self, BcryptSetup, BcryptVariant}; use crate::cluster::Cluster; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::net::PooledConnection; use crate::ResultCode; @@ -81,7 +81,7 @@ impl AdminCommand { let result_code = conn.buffer.read_u8(Some(RESULT_CODE)); let result_code = ResultCode::from(result_code); if result_code != ResultCode::Ok { - bail!(ErrorKind::ServerError(result_code)); + return Err(Error::ServerError(result_code)); } Ok(()) @@ -103,7 +103,7 @@ impl AdminCommand { let result_code = conn.buffer.read_u8(Some(RESULT_CODE)); let result_code = ResultCode::from(result_code); if ResultCode::SecurityNotEnabled != result_code && ResultCode::Ok != result_code { - bail!(ErrorKind::ServerError(result_code)); + return Err(Error::ServerError(result_code)); } // consume the rest of the buffer diff --git a/aerospike-core/src/commands/batch_read_command.rs b/aerospike-core/src/commands/batch_read_command.rs index d6487bbd..e3cd371e 100644 --- a/aerospike-core/src/commands/batch_read_command.rs +++ b/aerospike-core/src/commands/batch_read_command.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use crate::cluster::Node; use crate::commands::{self, Command}; -use crate::errors::{ErrorKind, Result, ResultExt}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::policy::{BatchPolicy, Policy, PolicyLike}; use crate::{value, BatchRead, Record, ResultCode, Value}; @@ -59,7 +59,7 @@ impl BatchReadCommand { // too many retries if let Some(max_retries) = base_policy.max_retries() { if iterations > max_retries + 1 { - bail!(ErrorKind::Connection(format!( + return Err(Error::Connection(format!( "Timeout after {} tries", iterations ))); @@ -95,10 +95,10 @@ impl BatchReadCommand { }; self.prepare_buffer(&mut conn) - .chain_err(|| "Failed to prepare send buffer")?; + .map_err(|e| e.chain_error("Failed to prepare send buffer"))?; self.write_timeout(&mut conn, base_policy.timeout()) .await - .chain_err(|| "Failed to set timeout for send buffer")?; + .map_err(|e| e.chain_error("Failed to set timeout for send buffer"))?; // Send command. if let Err(err) = self.write_buffer(&mut conn).await { @@ -125,7 +125,7 @@ impl BatchReadCommand { return Ok(()); } - bail!(ErrorKind::Connection("Timeout".to_string())) + return Err(Error::Connection("Timeout".to_string())); } async fn parse_group(&mut self, conn: &mut Connection, size: usize) -> Result { @@ -150,7 +150,7 @@ impl BatchReadCommand { let found_key = match ResultCode::from(conn.buffer.read_u8(Some(5))) { ResultCode::Ok => true, ResultCode::KeyNotFoundError => false, - rc => bail!(ErrorKind::ServerError(rc)), + rc => return Err(Error::ServerError(rc)), }; // if cmd is the end marker of the response, do not proceed further diff --git a/aerospike-core/src/commands/buffer.rs b/aerospike-core/src/commands/buffer.rs index 02f087e7..b29278e5 100644 --- a/aerospike-core/src/commands/buffer.rs +++ b/aerospike-core/src/commands/buffer.rs @@ -18,7 +18,7 @@ use std::time::Duration; use byteorder::{ByteOrder, LittleEndian, NetworkEndian}; use crate::commands::field_type::FieldType; -use crate::errors::Result; +use crate::errors::{Result, Error}; use crate::expressions::FilterExpression; use crate::msgpack::encoder; use crate::operations::{Operation, OperationBin, OperationData, OperationType}; @@ -125,7 +125,7 @@ impl Buffer { // Corrupted data streams can result in a huge length. // Do a sanity check here. if size > MAX_BUFFER_SIZE { - bail!("Invalid size for buffer: {}", size); + return Err(Error::InvalidArgument(format!("Invalid size for buffer: {size}"))); } let mem_size = self.data_buffer.capacity(); diff --git a/aerospike-core/src/commands/delete_command.rs b/aerospike-core/src/commands/delete_command.rs index f8ab5594..b1708a20 100644 --- a/aerospike-core/src/commands/delete_command.rs +++ b/aerospike-core/src/commands/delete_command.rs @@ -17,7 +17,7 @@ use std::time::Duration; use crate::cluster::{Cluster, Node}; use crate::commands::{buffer, Command, SingleCommand}; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::policy::WritePolicy; use crate::{Key, ResultCode}; @@ -82,7 +82,7 @@ impl<'a> Command for DeleteCommand<'a> { let result_code = ResultCode::from(conn.buffer.read_u8(Some(13))); if result_code != ResultCode::Ok && result_code != ResultCode::KeyNotFoundError { - bail!(ErrorKind::ServerError(result_code)); + return Err(Error::ServerError(result_code)); } self.existed = result_code == ResultCode::Ok; diff --git a/aerospike-core/src/commands/exists_command.rs b/aerospike-core/src/commands/exists_command.rs index 38083d8a..d99cb3ea 100644 --- a/aerospike-core/src/commands/exists_command.rs +++ b/aerospike-core/src/commands/exists_command.rs @@ -17,7 +17,7 @@ use std::time::Duration; use crate::cluster::{Cluster, Node}; use crate::commands::{buffer, Command, SingleCommand}; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::policy::WritePolicy; use crate::{Key, ResultCode}; @@ -82,7 +82,7 @@ impl<'a> Command for ExistsCommand<'a> { let result_code = ResultCode::from(conn.buffer.read_u8(Some(13))); if result_code != ResultCode::Ok && result_code != ResultCode::KeyNotFoundError { - bail!(ErrorKind::ServerError(result_code)); + return Err(Error::ServerError(result_code)); } self.exists = result_code == ResultCode::Ok; diff --git a/aerospike-core/src/commands/info_command.rs b/aerospike-core/src/commands/info_command.rs index e169b223..0ec694c6 100644 --- a/aerospike-core/src/commands/info_command.rs +++ b/aerospike-core/src/commands/info_command.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; use std::io::{Cursor, Write}; use std::str; -use crate::errors::Result; +use crate::errors::{Result, Error}; use crate::net::Connection; // MAX_BUFFER_SIZE protects against allocating massive memory blocks @@ -71,7 +71,7 @@ impl Message { // Corrupted data streams can result in a huge length. // Do a sanity check here. if data_len > MAX_BUFFER_SIZE { - bail!("Invalid size for info command buffer: {}", data_len); + return Err(Error::InvalidArgument(format!("Invalid size for info command buffer: {data_len}"))); } self.buf.resize(data_len, 0); @@ -96,7 +96,7 @@ impl Message { match (key, val) { (Some(key), Some(val)) => result.insert(key.to_string(), val.to_string()), (Some(key), None) => result.insert(key.to_string(), "".to_string()), - _ => bail!("Parsing Info command failed"), + _ => return Err(Error::InvalidArgument("Parsing Info command failed".into())), }; } diff --git a/aerospike-core/src/commands/mod.rs b/aerospike-core/src/commands/mod.rs index 915664c3..d9f0c30d 100644 --- a/aerospike-core/src/commands/mod.rs +++ b/aerospike-core/src/commands/mod.rs @@ -50,7 +50,7 @@ pub use self::touch_command::TouchCommand; pub use self::write_command::WriteCommand; use crate::cluster::Node; -use crate::errors::{Error, ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::ResultCode; @@ -71,6 +71,6 @@ pub trait Command { pub const fn keep_connection(err: &Error) -> bool { matches!( err, - Error(ErrorKind::ServerError(ResultCode::KeyNotFoundError), _) + Error::ServerError(ResultCode::KeyNotFoundError) ) } diff --git a/aerospike-core/src/commands/read_command.rs b/aerospike-core/src/commands/read_command.rs index be79be1b..9398407e 100644 --- a/aerospike-core/src/commands/read_command.rs +++ b/aerospike-core/src/commands/read_command.rs @@ -20,7 +20,7 @@ use std::time::Duration; use crate::cluster::{Cluster, Node}; use crate::commands::buffer; use crate::commands::{Command, SingleCommand}; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::policy::ReadPolicy; use crate::value::bytes_to_particle; @@ -125,7 +125,7 @@ impl<'a> Command for ReadCommand<'a> { .await { warn!("Parse result error: {}", err); - bail!(err); + return Err(err); } conn.buffer.reset_offset(); @@ -142,7 +142,7 @@ impl<'a> Command for ReadCommand<'a> { if receive_size > 0 { if let Err(err) = conn.read_buffer(receive_size).await { warn!("Parse result error: {}", err); - bail!(err); + return Err(err); } } @@ -164,9 +164,9 @@ impl<'a> Command for ReadCommand<'a> { .bins .get("FAILURE") .map_or(String::from("UDF Error"), ToString::to_string); - Err(ErrorKind::UdfBadResponse(reason).into()) + Err(Error::UdfBadResponse(reason).into()) } - rc => Err(ErrorKind::ServerError(rc).into()), + rc => Err(Error::ServerError(rc).into()), } } } diff --git a/aerospike-core/src/commands/single_command.rs b/aerospike-core/src/commands/single_command.rs index 2eec7783..5ff01ecd 100644 --- a/aerospike-core/src/commands/single_command.rs +++ b/aerospike-core/src/commands/single_command.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use crate::cluster::partition::Partition; use crate::cluster::{Cluster, Node}; use crate::commands::{self}; -use crate::errors::{ErrorKind, Result, ResultExt}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::policy::Policy; use crate::Key; @@ -109,10 +109,10 @@ impl<'a> SingleCommand<'a> { }; cmd.prepare_buffer(&mut conn) - .chain_err(|| "Failed to prepare send buffer")?; + .map_err(|e| e.chain_error("Failed to prepare send buffer"))?; cmd.write_timeout(&mut conn, policy.timeout()) .await - .chain_err(|| "Failed to set timeout for send buffer")?; + .map_err(|e| e.chain_error("Failed to set timeout for send buffer"))?; // Send command. if let Err(err) = cmd.write_buffer(&mut conn).await { @@ -139,6 +139,6 @@ impl<'a> SingleCommand<'a> { return Ok(()); } - bail!(ErrorKind::Connection("Timeout".to_string())) + return Err(Error::Connection("Timeout".to_string())); } } diff --git a/aerospike-core/src/commands/stream_command.rs b/aerospike-core/src/commands/stream_command.rs index 05989f34..e76778e4 100644 --- a/aerospike-core/src/commands/stream_command.rs +++ b/aerospike-core/src/commands/stream_command.rs @@ -21,7 +21,7 @@ use crate::cluster::Node; use crate::commands::buffer; use crate::commands::field_type::FieldType; use crate::commands::Command; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::query::Recordset; use crate::value::bytes_to_particle; @@ -54,7 +54,7 @@ impl StreamCommand { match result_code { ResultCode::KeyNotFoundError => return Ok((None, false)), - _ => bail!(ErrorKind::ServerError(result_code)), + _ => return Err(Error::ServerError(result_code)), } } diff --git a/aerospike-core/src/commands/touch_command.rs b/aerospike-core/src/commands/touch_command.rs index 18868b31..139e9cc3 100644 --- a/aerospike-core/src/commands/touch_command.rs +++ b/aerospike-core/src/commands/touch_command.rs @@ -18,7 +18,7 @@ use std::time::Duration; use crate::cluster::{Cluster, Node}; use crate::commands::buffer; use crate::commands::{Command, SingleCommand}; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::policy::WritePolicy; use crate::{Key, ResultCode}; @@ -78,7 +78,7 @@ impl<'a> Command for TouchCommand<'a> { let result_code = ResultCode::from(conn.buffer.read_u8(Some(13))); if result_code != ResultCode::Ok { - bail!(ErrorKind::ServerError(result_code)); + return Err(Error::ServerError(result_code)); } SingleCommand::empty_socket(conn).await diff --git a/aerospike-core/src/commands/write_command.rs b/aerospike-core/src/commands/write_command.rs index e92695d1..9bbbe750 100644 --- a/aerospike-core/src/commands/write_command.rs +++ b/aerospike-core/src/commands/write_command.rs @@ -18,7 +18,7 @@ use std::time::Duration; use crate::cluster::{Cluster, Node}; use crate::commands::buffer; use crate::commands::{Command, SingleCommand}; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::Connection; use crate::operations::OperationType; use crate::policy::WritePolicy; @@ -93,7 +93,7 @@ impl<'a> Command for WriteCommand<'a> { conn.buffer.reset_offset(); let result_code = ResultCode::from(conn.buffer.read_u8(Some(13))); if result_code != ResultCode::Ok { - bail!(ErrorKind::ServerError(result_code)); + return Err(Error::ServerError(result_code)); } let res = SingleCommand::empty_socket(conn).await; res diff --git a/aerospike-core/src/errors.rs b/aerospike-core/src/errors.rs index f4344920..f798315d 100644 --- a/aerospike-core/src/errors.rs +++ b/aerospike-core/src/errors.rs @@ -33,7 +33,7 @@ //! Some(duration) => println!("ttl: {} secs", duration.as_secs()), //! } //! }, -//! Err(Error(ErrorKind::ServerError(ResultCode::KeyNotFoundError), _)) => { +//! Err(Error::ServerError(ResultCode::KeyNotFoundError)) => { //! println!("No such record: {}", key); //! }, //! Err(err) => { @@ -54,90 +54,78 @@ use crate::ResultCode; -error_chain! { +#[derive(Error, Debug)] +pub enum Error { + #[error("Error decoding Base64 encoded value")] + Base64(#[from] ::base64::DecodeError), + #[error("Error interpreting a sequence of u8 as a UTF-8 encoded string.")] + InvalidUtf8(#[from] ::std::str::Utf8Error), + #[error("Error during an I/O operation")] + Io(#[from] ::std::io::Error), + #[error("Error returned from the `recv` function on an MPSC `Receiver`")] + MpscRecv(#[from] ::std::sync::mpsc::RecvError), + #[error("Error parsing an IP or socket address")] + ParseAddr(#[from] ::std::net::AddrParseError), + #[error("Error parsing an integer")] + ParseInt(#[from] ::std::num::ParseIntError), + #[error("Error returned while hashing a password for user authentication")] + PwHash(#[from] ::pwhash::error::Error), + /// The client received a server response that it was not able to process. + #[error("Bad Server Response: {0}")] + BadResponse(String), + /// The client was not able to communicate with the cluster due to some issue with the + /// network connection. + #[error("Unable to communicate with server cluster: {0}")] + Connection(String), + /// One or more of the arguments passed to the client are invalid. + #[error("Invalid argument: {0}")] + InvalidArgument(String), + /// Cluster node is invalid. + #[error("Invalid cluster node: {0}")] + InvalidNode(String), + /// Exceeded max. number of connections per node. + #[error("Too many connections")] + NoMoreConnections, + /// Server responded with a response code indicating an error condition. + #[error("Server error: {0:?}")] + ServerError(ResultCode), + /// Error returned when executing a User-Defined Function (UDF) resulted in an error. + #[error("UDF Bad Response: {0}")] + UdfBadResponse(String), + /// Error returned when a task times out before it could be completed. + #[error("Timeout: {0}")] + Timeout(String), -// Automatic conversions between this error chain and other error types not defined by the -// `error_chain!`. - foreign_links { - Base64(::base64::DecodeError) - #[doc = "Error decoding Base64 encoded value"]; - InvalidUtf8(::std::str::Utf8Error) - #[doc = "Error interpreting a sequence of u8 as a UTF-8 encoded string."]; - Io(::std::io::Error) - #[doc = "Error during an I/O operation"]; - MpscRecv(::std::sync::mpsc::RecvError) - #[doc = "Error returned from the `recv` function on an MPSC `Receiver`"]; - ParseAddr(::std::net::AddrParseError) - #[doc = "Error parsing an IP or socket address"]; - ParseInt(::std::num::ParseIntError) - #[doc = "Error parsing an integer"]; - PwHash(::pwhash::error::Error) - #[doc = "Error returned while hashing a password for user authentication"]; - } - -// Additional `ErrorKind` variants. - errors { - -/// The client received a server response that it was not able to process. - BadResponse(details: String) { - description("Bad Server Response") - display("Bad Server Response: {}", details) - } - -/// The client was not able to communicate with the cluster due to some issue with the -/// network connection. - Connection(details: String) { - description("Network Connection Issue") - display("Unable to communicate with server cluster: {}", details) - } - -/// One or more of the arguments passed to the client are invalid. - InvalidArgument(details: String) { - description("Invalid Argument") - display("Invalid argument: {}", details) - } + /// ClientError is an untyped Error happening on client-side + #[error("{0}")] + ClientError(String), -/// Cluster node is invalid. - InvalidNode(details: String) { - description("Invalid cluster node") - display("Invalid cluster node: {}", details) - } - -/// Exceeded max. number of connections per node. - NoMoreConnections { - description("Too many connections") - display("Too many connections") - } - -/// Server responded with a response code indicating an error condition. - ServerError(rc: ResultCode) { - description("Server Error") - display("Server error: {}", rc.into_string()) - } + /// Error returned when a tasked timeed out before it could be completed. + #[error("{0}\n\t{1}")] + Wrapped(Box, Box), +} -/// Error returned when executing a User-Defined Function (UDF) resulted in an error. - UdfBadResponse(details: String) { - description("UDF Bad Response") - display("UDF Bad Response: {}", details) - } +impl Error { + pub fn chain_error(self, e: &str) -> Error { + Error::Wrapped(Box::new(Error::ClientError(e.into())), Box::new(self)) + } -/// Error returned when a tasked timeed out before it could be completed. - Timeout(details: String) { - description("Timeout") - display("Timeout: {}", details) - } + pub fn wrap(self, e: Error) -> Error { + Error::Wrapped(Box::new(e), Box::new(self)) } } +pub type Result = ::std::result::Result; + macro_rules! log_error_chain { ($err:expr, $($arg:tt)*) => { error!($($arg)*); error!("Error: {}", $err); - for e in $err.iter().skip(1) { - error!("caused by: {}", e); - } - if let Some(backtrace) = $err.backtrace() { - error!("backtrace: {:?}", backtrace); - } + // for e in $err.iter().skip(1) { + // error!("caused by: {}", e); + // } + // if let Some(backtrace) = $err.provide() { + // error!("backtrace: {:?}", backtrace); + // } }; } diff --git a/aerospike-core/src/lib.rs b/aerospike-core/src/lib.rs index 1a98c3f7..eea02556 100644 --- a/aerospike-core/src/lib.rs +++ b/aerospike-core/src/lib.rs @@ -140,7 +140,7 @@ extern crate byteorder; extern crate crossbeam_queue; extern crate ripemd160; #[macro_use] -extern crate error_chain; +extern crate thiserror; #[macro_use] extern crate lazy_static; #[macro_use] @@ -153,7 +153,7 @@ pub use bin::{Bin, Bins}; pub use client::Client; pub use cluster::Node; pub use commands::particle_type::ParticleType; -pub use errors::{Error, ErrorKind, Result}; +pub use errors::{Error, Result}; pub use expressions::regex_flag::RegexFlag; pub use key::Key; pub use net::Host; diff --git a/aerospike-core/src/msgpack/decoder.rs b/aerospike-core/src/msgpack/decoder.rs index a9ff80bb..68081a89 100644 --- a/aerospike-core/src/msgpack/decoder.rs +++ b/aerospike-core/src/msgpack/decoder.rs @@ -18,7 +18,7 @@ use std::vec::Vec; use crate::commands::buffer::Buffer; use crate::commands::ParticleType; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::value::Value; pub fn unpack_value_list(buf: &mut Buffer) -> Result { @@ -104,10 +104,10 @@ fn unpack_blob(buf: &mut Buffer, count: usize) -> Result { Ok(Value::GeoJSON(val)) } - _ => bail!( + _ => return Err(Error::BadResponse(format!( "Error while unpacking BLOB. Type-header with code `{}` not recognized.", vtype - ), + ))), } } @@ -213,7 +213,7 @@ fn unpack_value(buf: &mut Buffer) -> Result { Ok(Value::from(value)) } _ => Err( - ErrorKind::BadResponse(format!("Error unpacking value of type '{:x}'", obj_type)) + Error::BadResponse(format!("Error unpacking value of type '{:x}'", obj_type)) .into(), ), } diff --git a/aerospike-core/src/net/connection.rs b/aerospike-core/src/net/connection.rs index d17f220c..9e2d8557 100644 --- a/aerospike-core/src/net/connection.rs +++ b/aerospike-core/src/net/connection.rs @@ -15,7 +15,7 @@ use crate::commands::admin_command::AdminCommand; use crate::commands::buffer::Buffer; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::policy::ClientPolicy; #[cfg(all(any(feature = "rt-async-std"), not(feature = "rt-tokio")))] use aerospike_rt::async_std::net::Shutdown; @@ -47,7 +47,7 @@ impl Connection { pub async fn new(addr: &str, policy: &ClientPolicy) -> Result { let stream = aerospike_rt::timeout(Duration::from_secs(10), TcpStream::connect(addr)).await; if stream.is_err() { - bail!(ErrorKind::Connection( + return Err(Error::Connection( "Could not open network connection".to_string() )); } diff --git a/aerospike-core/src/net/connection_pool.rs b/aerospike-core/src/net/connection_pool.rs index 95575dd1..aa0b9307 100644 --- a/aerospike-core/src/net/connection_pool.rs +++ b/aerospike-core/src/net/connection_pool.rs @@ -17,7 +17,7 @@ use std::ops::{Deref, DerefMut, Drop}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; -use crate::errors::{Error, ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::net::{Connection, Host}; use crate::policy::ClientPolicy; use futures::executor::block_on; @@ -75,7 +75,7 @@ impl Queue { } if internals.num_conns >= self.0.capacity { - bail!(ErrorKind::NoMoreConnections); + return Err(Error::NoMoreConnections); } internals.num_conns += 1; @@ -93,7 +93,7 @@ impl Queue { let mut internals = self.0.internals.lock().await; internals.num_conns -= 1; drop(internals); - bail!(ErrorKind::Connection( + return Err(Error::Connection( "Could not open network connection".to_string() )); } @@ -190,7 +190,7 @@ impl ConnectionPool { loop { let i = self.queue_counter.fetch_add(1, Ordering::Relaxed); let connection = self.queues[i % self.num_queues].get().await; - if let Err(Error(ErrorKind::NoMoreConnections, _)) = connection { + if let Err(Error::NoMoreConnections) = connection { attempts -= 1; if attempts > 0 { continue; diff --git a/aerospike-core/src/net/host.rs b/aerospike-core/src/net/host.rs index 8bd52a33..7ad8ca1d 100644 --- a/aerospike-core/src/net/host.rs +++ b/aerospike-core/src/net/host.rs @@ -18,7 +18,7 @@ use std::io; use std::net::{SocketAddr, ToSocketAddrs}; use std::vec::IntoIter; -use crate::errors::{ErrorKind, Result, ResultExt}; +use crate::errors::{Error, Result}; use crate::net::parser::Parser; /// Host name/port of database server. @@ -78,9 +78,12 @@ impl ToHosts for Vec { impl ToHosts for String { fn to_hosts(&self) -> Result> { let mut parser = Parser::new(self, 3000); - parser - .read_hosts() - .chain_err(|| ErrorKind::InvalidArgument(format!("Invalid hosts list: '{}'", self))) + parser.read_hosts().map_err(|e| { + e.wrap(Error::InvalidArgument(format!( + "Invalid hosts list: '{}'", + self + ))) + }) } } diff --git a/aerospike-core/src/net/parser.rs b/aerospike-core/src/net/parser.rs index 69a84fe8..83f2b6fe 100644 --- a/aerospike-core/src/net/parser.rs +++ b/aerospike-core/src/net/parser.rs @@ -13,7 +13,7 @@ // License for the specific language governing permissions and limitations under // the License. -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::Host; use std::iter::Peekable; use std::str::Chars; @@ -45,7 +45,7 @@ impl<'a> Parser<'a> { } } 1 => (addr[0].clone(), None, self.default_port), - _ => bail!(ErrorKind::InvalidArgument( + _ => return Err(Error::InvalidArgument( "Invalid address string".to_string() )), }; @@ -84,7 +84,7 @@ impl<'a> Parser<'a> { } _ => { return if substr.is_empty() { - bail!(ErrorKind::InvalidArgument( + return Err(Error::InvalidArgument( "Invalid address string".to_string() )) } else { diff --git a/aerospike-core/src/query/statement.rs b/aerospike-core/src/query/statement.rs index 1b640317..19ebbdda 100644 --- a/aerospike-core/src/query/statement.rs +++ b/aerospike-core/src/query/statement.rs @@ -13,7 +13,7 @@ // License for the specific language governing permissions and limitations under // the License. -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::query::Filter; use crate::Bins; use crate::Value; @@ -122,31 +122,31 @@ impl Statement { pub fn validate(&self) -> Result<()> { if let Some(ref filters) = self.filters { if filters.len() > 1 { - bail!(ErrorKind::InvalidArgument( + return Err(Error::InvalidArgument( "Too many filter expressions".to_string() )); } } if self.set_name.is_empty() { - bail!(ErrorKind::InvalidArgument("Empty set name".to_string())); + return Err(Error::InvalidArgument("Empty set name".to_string())); } if let Some(ref index_name) = self.index_name { if index_name.is_empty() { - bail!(ErrorKind::InvalidArgument("Empty index name".to_string())); + return Err(Error::InvalidArgument("Empty index name".to_string())); } } if let Some(ref agg) = self.aggregation { if agg.package_name.is_empty() { - bail!(ErrorKind::InvalidArgument( + return Err(Error::InvalidArgument( "Empty UDF package name".to_string() )); } if agg.function_name.is_empty() { - bail!(ErrorKind::InvalidArgument( + return Err(Error::InvalidArgument( "Empty UDF function name".to_string() )); } diff --git a/aerospike-core/src/task/index_task.rs b/aerospike-core/src/task/index_task.rs index 1b975b6a..cad361ad 100644 --- a/aerospike-core/src/task/index_task.rs +++ b/aerospike-core/src/task/index_task.rs @@ -14,7 +14,7 @@ // the License. use crate::cluster::Cluster; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::task::{Status, Task}; use std::sync::Arc; @@ -51,7 +51,7 @@ impl IndexTask { if response.contains(FAIL_PATTERN_201) || response.contains(FAIL_PATTERN_203) { Ok(Status::NotFound) } else { - bail!(ErrorKind::BadResponse(format!( + return Err(Error::BadResponse(format!( "Code 201 and 203 missing. Response: {}", response ))); @@ -61,7 +61,7 @@ impl IndexTask { let percent_begin = pattern_index + SUCCESS_PATTERN.len(); let percent_end = match response[percent_begin..].find(DELMITER) { - None => bail!(ErrorKind::BadResponse(format!( + None => return Err(Error::BadResponse(format!( "delimiter missing in response. Response: {}", response ))), @@ -71,7 +71,7 @@ impl IndexTask { match percent_str.parse::() { Ok(100) => Ok(Status::Complete), Ok(_) => Ok(Status::InProgress), - Err(_) => bail!(ErrorKind::BadResponse( + Err(_) => return Err(Error::BadResponse( "Unexpected load_pct value from server".to_string() )), } @@ -87,7 +87,7 @@ impl Task for IndexTask { let nodes = self.cluster.nodes().await; if nodes.is_empty() { - bail!(ErrorKind::Connection("No connected node".to_string())) + return Err(Error::Connection("No connected node".to_string())) } for node in &nodes { diff --git a/aerospike-core/src/task/register_task.rs b/aerospike-core/src/task/register_task.rs index ad17e1ec..40800aa8 100644 --- a/aerospike-core/src/task/register_task.rs +++ b/aerospike-core/src/task/register_task.rs @@ -14,7 +14,7 @@ // the License. use crate::cluster::Cluster; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use crate::task::{Status, Task}; use std::sync::Arc; @@ -45,7 +45,7 @@ impl Task for RegisterTask { let nodes = self.cluster.nodes().await; if nodes.is_empty() { - bail!(ErrorKind::Connection("No connected node".to_string())) + return Err(Error::Connection("No connected node".to_string())) } for node in &nodes { diff --git a/aerospike-core/src/task/task.rs b/aerospike-core/src/task/task.rs index aa67ab06..d82dd6fb 100644 --- a/aerospike-core/src/task/task.rs +++ b/aerospike-core/src/task/task.rs @@ -13,7 +13,7 @@ // License for the specific language governing permissions and limitations under // the License. -use crate::errors::{ErrorKind, Result}; +use crate::errors::{Error, Result}; use aerospike_rt::sleep; use aerospike_rt::time::{Duration, Instant}; @@ -48,14 +48,14 @@ pub trait Task { match self.query_status().await { Ok(Status::NotFound) => { - bail!(ErrorKind::BadResponse("task status not found".to_string())) + return Err(Error::BadResponse("task status not found".to_string())) } Ok(Status::InProgress) => {} // do nothing and wait error_or_complete => return error_or_complete, } if timeout.map_or(false, timeout_elapsed) { - bail!(ErrorKind::Timeout("Task timeout reached".to_string())) + return Err(Error::Timeout("Task timeout reached".to_string())) } } } diff --git a/aerospike-core/src/value.rs b/aerospike-core/src/value.rs index 3aca7e1d..d5d88f7b 100644 --- a/aerospike-core/src/value.rs +++ b/aerospike-core/src/value.rs @@ -563,7 +563,7 @@ impl TryFrom for String { match val { Value::String(v) => Ok(v), Value::GeoJSON(v) => Ok(v), - _ => bail!(format!( + _ => return Err(format!( "Invalid type conversion from Value::{} to {}", val.particle_type(), std::any::type_name::() @@ -578,7 +578,7 @@ impl TryFrom for Vec { match val { Value::Blob(v) => Ok(v), Value::HLL(v) => Ok(v), - _ => bail!(format!( + _ => return Err(format!( "Invalid type conversion from Value::{} to {}", val.particle_type(), std::any::type_name::() @@ -592,7 +592,7 @@ impl TryFrom for Vec { fn try_from(val: Value) -> std::result::Result { match val { Value::List(v) => Ok(v), - _ => bail!(format!( + _ => return Err(format!( "Invalid type conversion from Value::{} to {}", val.particle_type(), std::any::type_name::() @@ -606,7 +606,7 @@ impl TryFrom for HashMap { fn try_from(val: Value) -> std::result::Result { match val { Value::HashMap(v) => Ok(v), - _ => bail!(format!( + _ => return Err(format!( "Invalid type conversion from Value::{} to {}", val.particle_type(), std::any::type_name::() @@ -620,7 +620,7 @@ impl TryFrom for Vec<(Value, Value)> { fn try_from(val: Value) -> std::result::Result { match val { Value::OrderedMap(v) => Ok(v), - _ => bail!(format!( + _ => return Err(format!( "Invalid type conversion from Value::{} to {}", val.particle_type(), std::any::type_name::() @@ -634,7 +634,7 @@ impl TryFrom for f64 { fn try_from(val: Value) -> std::result::Result { match val { Value::Float(v) => Ok(f64::from(v)), - _ => bail!(format!( + _ => return Err(format!( "Invalid type conversion from Value::{} to {}", val.particle_type(), std::any::type_name::() @@ -648,7 +648,7 @@ impl TryFrom for bool { fn try_from(val: Value) -> std::result::Result { match val { Value::Bool(v) => Ok(v), - _ => bail!("Invalid type bool"), + _ => return Err("Invalid type bool".into()), } } } diff --git a/aerospike-sync/src/client.rs b/aerospike-sync/src/client.rs index 90d2cce7..1701e75d 100644 --- a/aerospike-sync/src/client.rs +++ b/aerospike-sync/src/client.rs @@ -130,7 +130,7 @@ impl Client { /// match client.get(&ReadPolicy::default(), &key, ["a", "b"]) { /// Ok(record) /// => println!("a={:?}", record.bins.get("a")), - /// Err(Error(ErrorKind::ServerError(ResultCode::KeyNotFoundError), _)) + /// Err(Error::ServerError(ResultCode::KeyNotFoundError)) /// => println!("No such record: {}", key), /// Err(err) /// => println!("Error fetching record: {}", err), @@ -152,7 +152,7 @@ impl Client { /// Some(duration) => println!("ttl: {} secs", duration.as_secs()), /// } /// }, - /// Err(Error(ErrorKind::ServerError(ResultCode::KeyNotFoundError), _)) + /// Err(Error::ServerError(ResultCode::KeyNotFoundError)) /// => println!("No such record: {}", key), /// Err(err) /// => println!("Error fetching record: {}", err), diff --git a/tests/src/task.rs b/tests/src/task.rs index ec662e4b..3a3d3e3b 100644 --- a/tests/src/task.rs +++ b/tests/src/task.rs @@ -14,7 +14,7 @@ // the License. use crate::common; -use aerospike::errors::ErrorKind; +use aerospike::errors::Error; use aerospike::task::{Status, Task}; use aerospike::*; use std::thread; @@ -57,7 +57,7 @@ async fn register_task_test() { let timeout = Duration::from_millis(100); assert!(matches!( register_task.wait_till_complete(Some(timeout)).await, - Err(Error(ErrorKind::Timeout(_), _)) + Err(Error(Error::Timeout(_), _)) )); client.close().await.unwrap(); diff --git a/tests/src/udf.rs b/tests/src/udf.rs index 02645d75..3194507c 100644 --- a/tests/src/udf.rs +++ b/tests/src/udf.rs @@ -86,7 +86,7 @@ end let res = client .execute_udf(&wpolicy, &key, "test_udf1", "no_such_function", None) .await; - if let Err(Error(ErrorKind::UdfBadResponse(response), _)) = res { + if let Err(Error::UdfBadResponse(response)) = res { assert_eq!(response, "function not found".to_string()); } else { panic!("UDF function did not return the expected error"); diff --git a/tools/benchmark/src/workers.rs b/tools/benchmark/src/workers.rs index 7949e0d7..c7104a8d 100644 --- a/tools/benchmark/src/workers.rs +++ b/tools/benchmark/src/workers.rs @@ -23,7 +23,7 @@ use rand::prelude::*; use aerospike::Error as asError; use aerospike::Result as asResult; -use aerospike::{Client, ErrorKind, Key, ReadPolicy, ResultCode, WritePolicy}; +use aerospike::{Client, Error, Key, ReadPolicy, ResultCode, WritePolicy}; use generator::KeyRange; use percent::Percent; @@ -113,7 +113,7 @@ trait Task: Send { fn status(&self, result: asResult<()>) -> Status { match result { - Err(asError(ErrorKind::ServerError(ResultCode::Timeout), _)) => Status::Timeout, + Err(Error::ServerError(ResultCode::Timeout)) => Status::Timeout, Err(_) => Status::Error, _ => Status::Success, }