#消息 #处理器 #调度 #调度器 #异步 #消费者 #状态

async_message_dispatcher

一个使将消息调度到异步处理器变得更加容易的库

13 个版本 (7 个主要变更)

7.0.0 2023 年 5 月 12 日
6.0.0 2023 年 5 月 10 日
5.0.0 2023 年 5 月 9 日
4.0.0 2023 年 5 月 9 日
0.2.1 2023 年 5 月 8 日

#900异步

Download history 20/week @ 2024-03-10 3/week @ 2024-03-31

每月 122 次下载

MIT 许可证

11KB
173

此库的目的

通常,当人们想为社交网络编写文本机器人时,他们使用状态作为显式、独立的实体

enum UserState {
    Beginning,
    WaitingForAge,
    WaitingForName { age: String },
    WaitingForBio { age: String, name: String },
}

impl Handler {
    pub fn handle_message(&mut self, message: Message) -> &'static str {
        let state = self.states.entry(message.user_id).or_insert(UserState::Beginning);
        let (response, new_state) = match state {
            UserState::Beginning => ("Please, enter your age.", UserState::WaitingForAge),
            UserState::WaitingForAge => ("Now, enter your name.", UserState::WaitingForName { age: message.text }),
            UserState::WaitingForName { age } => ("Now, enter your bio.", UserState::WaitingForBio { age, name: message.text }),
            UserState::WaitingForBio { age, name } => {
                self.add_user(age, name, message.text);
                ("You're registered successfully!", UserState::Beginning)
            },
        };
        if let UserState::Beginning = state {
            states.remove(message.user_id);
        } else {
            *state = new_state;
        };
        response
    }
}

即使与专用库一起使用,这也要求用户编写一个 enum 来完成这个,并且枚举必须包含重复,如果需要将数据传输到末尾。这种方法非常嘈杂。

此库允许您编写类似以下内容

let dispatcher = Dispatcher::new(|consumer| tokio::spawn(async move {
    let message = consumer.take().await.unwrap();
    message.respond("Please, enter your age.").await;
    let age = consumer.take().await.unwrap();
    age.respond("Now, enter your name.").await;
    let name = consumer.take().await.unwrap();
    name.respond("Now, enter your bio.").await;
    let bio = consumer.take().await.unwrap();
    self.add_user(age.text, name.text, bio.text);
    bio.respond("You're registered successfully!.").await;
}));

// Then, somewhere after that...

dispatcher.dispatch(key, message); // And the message will go to the handler!

这种方法使代码的可读性大大提高,尤其是在存在许多状态时。此外,如果您愿意,添加消息过滤也很容易

async fn get_number<K: Key, M>(consumer: &mut Consumer<K, M>) -> i64 {
    loop {
        let message = consumer.take().await.unwrap();
        let number: Ok(i64) = message.text.parse() else {
            message.respond("Please, enter a number.").await;
            continue;
        };
    }
}

用法

如果您想以相同的方式调度每条消息,请使用 Dispatcher;如果您想自己管理 Consumer,请使用 Storage

无运行时依赖