gpt4 book ai didi

multithreading - 我如何将 discord-rs 事件与来自 Twitter 或计时器的其他事件结合起来?

转载 作者:行者123 更新时间:2023-11-29 08:23:47 25 4
gpt4 key购买 nike

我使用 discord-rs 为 Discord 聊天服务编写了一个机器人图书馆。当事件出现在主循环的单个线程中时,这个库会向我提供事件:

fn start() {
// ...
loop {
let event = match connection.recv_event() {
Ok(event) => event,
Err(err) => { ... },
}
}
}

我想添加一些计时器和其他在它们自己的线程中计算的东西,它们必须通知我在主循环的线程中做一些事情。我还想添加 Twitter 支持。所以它可能看起来像这样:

(Discord's network connection, Twitter network connection, some timer in another thread) -> main loop

这看起来像这样:

fn start() {
// ...
loop {
let event = match recv_events() {
// 1. if Discord - do something with discord
// 2. if timer - handle timer's notification
// 3. if Twitter network connection - handle twitter
}
}
}

在原始的 C 和 C 套接字中,它可以通过(e)轮询它们来完成,但在这里我不知道如何在 Rust 中做到这一点,或者它是否可能。我想我想要类似 poll 的一些不同来源的东西,它会为我提供不同类型的对象。

我想如果我为 mio 的 Evented 特性提供一个包装器并按照 Deadline 中的描述使用 mio 的轮询,这就可以实现。示例。

有什么办法可以将这些事件结合起来吗?

最佳答案

This library gives me events when they arise in a single thread in a main loop

“单线程”只适用于小型机器人。一旦您到达 2500 guilds limit ,Discord 将拒绝以正常方式连接您的机器人。你必须使用分片。我猜想您不会为您的机器人分片提供新的虚拟服务器。机会是,您将生成新的线程,每个分片一个事件循环。

顺便说一句,我是这样做的:

fn event_loop(shard_id: u8, total_shards: u8){
loop {
let bot = Discord::from_bot_token("...").expect("!from_bot_token");
let (mut dc, ready_ev) = bot.connect_sharded(shard_id, total_shards).expect("!connect");
// ...
}
}

fn main() {
let total_shards = 10;
for shard_id in 0..total_shards {
sleep(Duration::from_secs(6)); // There must be a five-second pause between connections from one IP.
ThreadBuilder::new().name (fomat! ("shard " (shard_id)))
.spawn (move || {
loop {
if let Err (err) = catch_unwind (move || event_loop (shard_id, total_shards)) {
log! ("shard " (shard_id) " panic: " (gstuff::any_to_str (&*err) .unwrap_or ("")));
sleep (Duration::from_secs (10));
continue} // Panic restarts the shard.
break}
}) .expect ("!spawn");
}
}

I want to add some timers and other things which are calculated in their own threads and which must notify me to do something in the main loop's thread

选项 1。不要。

很有可能,您真的不需要回到 Discord 事件循环!假设您想发布回复、更新嵌入等。您不需要 Discord 事件循环来执行此操作!

Discord API 分为两部分:
1)Websocket API,由Connection表示, 用于从 Discord 中获取事件。
2) REST API,由Discord表示接口(interface),用于发送事件。

您几乎可以从任何地方发送事件。从任何线程。甚至可能来自您的计时器。

DiscordSync .将其包裹在 Arc 中并与您的计时器和线程分享。

选项 2. 捕获机会。

尽管recv_event没有超时,Discord 会不断向您发送新事件。用户正在登录、退出、打字、发布消息、开始视频游戏、编辑内容等等。实际上,如果事件流停止,那么您的 Discord 连接就会出现问题(对于我的机器人,我已经根据该信号实现了高可用性故障转移)。

你可以分享一个deque用你的线程和定时器。一旦计时器结束,它将向双端队列发送一些内容,然后一旦 Discord 用新事件唤醒它,偶数循环将检查双端队列是否有新的事情要做。

选项 3.鸟瞰图。

作为belst已经指出,您可以启动一个通用事件循环,一个“统治所有事件”的循环,然后将 Discord 事件提升到该循环中。这特别有趣,因为通过分片,您将拥有多个事件循环。

因此,Discord 事件循环 -> 简单事件过滤器 -> channel -> 主事件循环。

选项 4. 分片。

如果您希望您的机器人在代码升级和重启期间保持在线,那么您应该提供一种方法来分别重启每个分片(或者以其他方式在分片级别实现高可用性故障转移,就像我所做的那样)。因为您无法在进程重启后立即连接所有分片,所以 Discord 不允许您这样做。

如果您所有的分片都共享同一个进程,那么在该进程重新启动后,您必须等待五秒钟才能附加一个新的分片。如果有 10 个分片,机器人停机时间将近一分钟。

分离分片重启的一种方法是为每个分片分配一个进程。然后,当您需要升级机器人时,您将分别重新启动每个进程。这样一来,仍然需要为每个分片等待五到六秒,但您的用户则不需要。

更好的是,您现在只需要为 discord-rs 升级和类似的维护相关任务重新启动 Discord 事件循环进程。另一方面,您的主事件循环可以立即重新启动,并且可以任意频繁地重新启动。这应该会大大加快编译-运行-测试循环。

因此,Discord 事件循环,在单独的分片进程中 -> 简单事件过滤器 -> RPC 或数据库 -> 主事件循环,在单独的进程中。

关于multithreading - 我如何将 discord-rs 事件与来自 Twitter 或计时器的其他事件结合起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43633148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com