expire_map
expire_map
: High concurrency dictionary supporting a maximum of 256 cycles timeout (internally implemented using dashmap).
Also, I implement RetryMap based on ExpireMap and can be used for network request timeouts and retries.
```rust use std::{ net::{Ipv4Addr, SocketAddrV4, UdpSocket}, time::Duration, };
use anyhow::Result; use asyncstd::task::{blockon, sleep, spawn}; use expire_map::{Caller, RetryMap};
struct Msg { msg: Box<[u8]>, }
struct Task { addr: SocketAddrV4, id: u16, }
impl Caller
fn call(&mut self, udp: &UdpSocket, task: &Task) { let cmd = format!("{} {}#{} {:?}", "call", task.addr, task.id, &self.msg); if let Err(err) = udp.sendto( &[&task.id.tole_bytes()[..], &self.msg[..]].concat(), task.addr, ) { dbg!(err); } dbg!(cmd); }
fn fail(&mut self, _: &UdpSocket, task: &Task) { let cmd = format!("{} {}#{} {:?}", "fail", task.addr, task.id, &self.msg); dbg!(cmd); } }
fn main() -> Result<()> { let udp = UdpSocket::bind(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0))?;
let retry_map = RetryMap::new(udp);
let msg = Msg { msg: Box::from(&[1, 2, 3][..]), };
let task = Task { id: 12345, addr: "223.5.5.5:53".parse()?, };
let retry_times = 3; // 重试次数是3次
let expireer = retry_map.clone();
let handle = spawn(async move { let mut doexpire = 0; loop { sleep(Duration::fromsecs(1)).await; expireer.doexpire(); doexpire += 1; let exist = expireer.get(&task).issome(); println!("{} {}", doexpire, exist); } });
// will run call() when insert retrymap.insert(task, msg, retrytimes);
retrymap.renew(task, 5); //dbg!(retrymap.get(&task).unwrap().value()); //dbg!(retrymap.getmut(&task).unwrap().key()); //retry_map.remove(task);
block_on(handle); Ok(()) } ```
Output
txt
+ ./sh/run.sh --example main
+ exec cargo run --example main
Finished dev [unoptimized + debuginfo] target(s) in 0.08s
Running `/Users/z/rmw/expire_map/target/debug/examples/main`
[examples/main.rs:24] cmd = "call 223.5.5.5:53#12345 [1, 2, 3]"
1 true
2 true
3 true
4 true
5 true
[examples/main.rs:24] cmd = "call 223.5.5.5:53#12345 [1, 2, 3]"
6 true
7 true
[examples/main.rs:24] cmd = "call 223.5.5.5:53#12345 [1, 2, 3]"
8 true
9 true
[examples/main.rs:29] cmd = "fail 223.5.5.5:53#12345 [1, 2, 3]"
10 false
11 false
12 false
13 false
The use of ExpireMap can be seen in the RetryMap implementation
```rust use std::{default::Default, ops::Deref};
use crate::{expire_map::Key, ExpireMap, OnExpire};
/* btree 超时时间 id 重试函数 重试次数 失败
*/
pub trait Caller
pub struct Retry
impl
pub trait Task
pub struct RetryMap
impl
impl
pub fn insert(&self, key: K, mut caller: C, retry: u8) { caller.call(&self.ctx, &key); self .expire .insert(key, Retry { n: retry, caller }, C::ttl()); } }
impl
This project is part of rmw.link Code Project
expire_map
: 最大支持 256 个周期超时的高并发字典(内部使用 dashmap 实现)。
同时,基于 ExpireMap 实现了 RetryMap,可以用于网络请求超时和重试。
```rust use std::{ net::{Ipv4Addr, SocketAddrV4, UdpSocket}, time::Duration, };
use anyhow::Result; use asyncstd::task::{blockon, sleep, spawn}; use expire_map::{Caller, RetryMap};
struct Msg { msg: Box<[u8]>, }
struct Task { addr: SocketAddrV4, id: u16, }
impl Caller
fn call(&mut self, udp: &UdpSocket, task: &Task) { let cmd = format!("{} {}#{} {:?}", "call", task.addr, task.id, &self.msg); if let Err(err) = udp.sendto( &[&task.id.tole_bytes()[..], &self.msg[..]].concat(), task.addr, ) { dbg!(err); } dbg!(cmd); }
fn fail(&mut self, _: &UdpSocket, task: &Task) { let cmd = format!("{} {}#{} {:?}", "fail", task.addr, task.id, &self.msg); dbg!(cmd); } }
fn main() -> Result<()> { let udp = UdpSocket::bind(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0))?;
let retry_map = RetryMap::new(udp);
let msg = Msg { msg: Box::from(&[1, 2, 3][..]), };
let task = Task { id: 12345, addr: "223.5.5.5:53".parse()?, };
let retry_times = 3; // 重试次数是3次
let expireer = retry_map.clone();
let handle = spawn(async move { let mut doexpire = 0; loop { sleep(Duration::fromsecs(1)).await; expireer.doexpire(); doexpire += 1; let exist = expireer.get(&task).issome(); println!("{} {}", doexpire, exist); } });
// will run call() when insert retrymap.insert(task, msg, retrytimes);
retrymap.renew(task, 5); //dbg!(retrymap.get(&task).unwrap().value()); //dbg!(retrymap.getmut(&task).unwrap().key()); //retry_map.remove(task);
block_on(handle); Ok(()) } ```
运行输出
txt
+ ./sh/run.sh --example main
+ exec cargo run --example main
Finished dev [unoptimized + debuginfo] target(s) in 0.08s
Running `/Users/z/rmw/expire_map/target/debug/examples/main`
[examples/main.rs:24] cmd = "call 223.5.5.5:53#12345 [1, 2, 3]"
1 true
2 true
3 true
4 true
5 true
[examples/main.rs:24] cmd = "call 223.5.5.5:53#12345 [1, 2, 3]"
6 true
7 true
[examples/main.rs:24] cmd = "call 223.5.5.5:53#12345 [1, 2, 3]"
8 true
9 true
[examples/main.rs:29] cmd = "fail 223.5.5.5:53#12345 [1, 2, 3]"
10 false
11 false
12 false
13 false
ExpireMap 的使用可以参见 RetryMap 的实现
```rust use std::{default::Default, ops::Deref};
use crate::{expire_map::Key, ExpireMap, OnExpire};
/* btree 超时时间 id 重试函数 重试次数 失败
*/
pub trait Caller
pub struct Retry
impl
pub trait Task
pub struct RetryMap
impl
impl
pub fn insert(&self, key: K, mut caller: C, retry: u8) { caller.call(&self.ctx, &key); self .expire .insert(key, Retry { n: retry, caller }, C::ttl()); } }
impl
本项目隶属于 人民网络 (rmw.link) 代码计划。