- rustcheats
- 全局变量
- 定时任务
json
protobuf
thrift
http client
- 常用数据结构
- 字符串
- 泛型
trait
- 错误处理
- 异步
- 智能指针
- 内部可变性
- 宏
- 闭包
- 迭代器
Iterator
- 类型转换
lifetime
- 析构
pin && unpin
- 反射
unsafe
lazy static
once cell
pub fn init() -> reqwest::Client {
reqwest::Client::builder()
.pool_idle_timeout(Duration::from_secs(30))
.pool_max_idle_per_host(32)
.timeout(Duration::from_secs(1))
.proxy(Proxy::http("http://127.0.0.1:1087").unwrap())
.build()
.unwrap()
}
lazy_static::lazy_static! {
static ref CLIENT: reqwest::Client = http_cli::init();
static ref CACHE: ArcSwap<HashMap<String,String>> = ArcSwap::from_pointee(HashMap::new());
}
pub async fn init() {
tokio::spawn(async move {
loop {
CACHE.store(std::sync::Arc::new(
real_get("https://gocn.vip/c/3lQ6GbD5ny/s/Gd7BTB/d/z63pjQHmo3").await,
));
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
let size = CACHE.load().len();
info!("timed run... cache size {}", size);
}
});
}
// cargo add serde_json
// cargo add serde -F derive
#[derive(Debug, Serialize, Deserialize)]
pub struct Animal {
pub name: String,
pub age: u32,
}
#[traced_test]
#[test]
fn struct_to_json() {
let tom = Animal {
name: "tom".to_string(),
age: 20,
};
let jstr = serde_json::to_string(&tom).unwrap();
assert!(jstr.len() > 0);
}
#[test]
#[traced_test]
fn map_to_json() {
let mut db = HashMap::new();
db.insert(
"tom",
Animal {
name: "tom".to_owned(),
age: 10,
},
);
db.insert(
"jerry",
Animal {
name: "jerry".to_owned(),
age: 12,
},
);
let jstr = serde_json::to_string(&db).unwrap();
assert!(jstr.len() > 0);
}
#[test]
#[traced_test]
fn struct_from_json() {
let jstr = "{\"name\":\"tom\",\"age\":20}";
let cat: Animal = serde_json::from_str(jstr).unwrap();
assert_eq!(cat.age, 20);
}
#[test]
#[traced_test]
fn json_to_map() {
let jstr = "{\"name\":\"tom\",\"age\":20}";
let db: HashMap<String, serde_json::Value> = serde_json::from_str(jstr).unwrap();
assert_eq!(db.len(), 2);
}
#[test]
#[traced_test]
fn map_to_json() {
let mut db = HashMap::new();
db.insert(
"tom",
Animal {
name: "tom".to_owned(),
age: 10,
},
);
db.insert(
"jerry",
Animal {
name: "jerry".to_owned(),
age: 12,
},
);
let jstr = serde_json::to_string(&db).unwrap();
assert!(jstr.len() > 0);
}
cargo add tracing-test
cargo add reqwest -F json
pub fn init() -> reqwest::Client {
reqwest::Client::builder()
.pool_idle_timeout(Duration::from_secs(30))
.pool_max_idle_per_host(32)
.timeout(Duration::from_secs(1))
.build()
.unwrap()
}
pub fn init() -> reqwest::Client {
reqwest::Client::builder()
.pool_idle_timeout(Duration::from_secs(30))
.pool_max_idle_per_host(32)
.timeout(Duration::from_secs(1))
.proxy(Proxy::http("http://127.0.0.1:1087").unwrap())
.build()
.unwrap()
}
#[tokio::test]
#[tracing_test::traced_test]
async fn get_with_timeout() {
let cli = crate::http_cli::init();
let resp = cli
.get("https://www.baidu.com/")
.timeout(Duration::from_millis(100))
.send()
.await;
match resp {
Ok(text) => {
assert_eq!(200, text.status());
assert!(text.text().await.unwrap().len() > 0);
}
Err(err) => {
error!("fetch error. {}", err);
}
}
}
#[tokio::test]
#[tracing_test::traced_test]
async fn test_post() {
let cli = crate::http_cli::init();
let resp = cli
.post("https://www.baidu.com/")
.body("hello world")
.send()
.await;
match resp {
Ok(text) => {
info!("status {:?}", text.status());
}
Err(err) => {
error!("fetch error. {}", err);
}
}
}
#[tokio::test]
#[tracing_test::traced_test]
async fn download() {
let url =
"https://inews.gtimg.com/om_bt/O5iwc3sJjyyn6slOb0XefgSSsoJZ5HBFbiPq8I4pdEpKsAA/1000";
let cli = crate::http_cli::init();
let response = cli.get(url).send().await.unwrap();
let mut file = File::create("image.png").unwrap();
let mut content = Cursor::new(response.bytes().await.unwrap());
std::io::copy(&mut content, &mut file).unwrap();
}
lib
中一般使用thiserror
定义错误bin
中使用anyhow
#[derive(thiserror::Error, Debug)]
pub enum RpcError {
#[error("input is invalid")]
InvalidArgs,
#[error("rpc timeout with {0:?}")]
Timeout(Duration),
#[error("request from {0} is not allowed")]
AclError(String),
#[error("load balance fail")]
LoadbalanceError,
#[error("system error: {0:?}")]
SysError(#[from] std::io::Error),
#[error("business error:{0}")]
BizError(u32),
#[error("unknown error:{0}")]
UnknownError(String),
}
pub fn mock_one_way_rpc(mock_arg: i32) -> anyhow::Result<(), RpcError> {
if mock_arg < 0 || mock_arg > 5 {
return Ok(());
}
if mock_arg == 0 {
return Err(InvalidArgs);
}
if mock_arg == 1 {
return Err(Timeout(Duration::seconds(1)));
}
if mock_arg == 2 {
return Err(AclError("unknown".to_owned()));
}
if mock_arg == 3 {
return Err(RpcError::SysError(Error::new(
ErrorKind::ConnectionAborted,
"connect aborted",
)));
}
if mock_arg == 4 {
return Err(BizError(1024));
}
if mock_arg == 5 {
return Err(UnknownError("system error".to_string()));
}
Ok(())
}