3 个版本
0.0.3 | 2021 年 10 月 26 日 |
---|---|
0.0.2 | 2020 年 11 月 22 日 |
0.0.1 | 2020 年 11 月 11 日 |
#3 在 #received
每月 22 次下载
20KB
264 行
Fish
基于事件交互模式进行回调通信通常被认为是最理想的,但,在许多情况下我们发现这会导致复杂性、错误和不需要的工作。 Fish
为基于回调和钩子的 API 提供了命令式非阻塞运行时交互。
让我们设想一个例子来看看它是如何工作的:假设你是某个配送应用插件的开发者。
应用会通过钩子通知你 (... 通过钩子) 当一个新的配送区域开放时。有一个端点允许你为该区域的新的订单注册一个钩子。
每当收到一个订单时,你可以发送一个请求来接受它。如果请求被批准,配送应用将向你发送一个回调。哦,我忘了提,你是一名经纪人,所以,每当收到订单时,你需要将其传递给你的履行客户,他们将同样在希望履行订单的情况下发送回调。
在每个步骤中,你都有特定于领域的逻辑和状态,这些通常在整个生命周期中被使用。
在 Fish
中,这种交互看起来像这样
// Step 1: Register webhook for new delivery regions
let orders = server.spawn();
app.send("region", RegisterRegion {
webhook_url: orders.url(),
region_id
}).await;
// orders is a Stream. You could concatenate multiple regions' orders together,
// or maybe handle them separately
while let Ok(order) = orders.next().await {
// Step 2: Let's see if our fulfillment partner is interested in the order
let fulfillment = server.spawn();
partner.send("order", NotifyOrder {
callback: fulfillment.url(),
..order
}).await;
// The partner will send us back a POST request if they want to fulfill the order,
// and do-nothing otherwise. We have a time limit to adhere to, so we'll give them
// 5 seconds to respond
if let Ok(_) = timeout(Duration::from_secs(5), fulfillment.next().await) {
// Step 3: OK, we're set, lets let the app know we are interested!
let granted = server.spawn();
app.send("order", AcceptOrder {
callback_url: url,
..
}).await;
// granted.next() and so on!
}
}
好的,我们可以进一步展开这个示例。而且严重缺失的是在编排过程中发生的特定于领域的逻辑、状态更新、缓存等等。我们发现以基于事件处理器的方式做这项工作需要巨大的努力。
那么你呢?你是否觉得这很具挑战性?有什么建议吗?
许可证:MIT OR Apache-2.0
考虑一下
这种模式如何与 CI/CD、硬件故障等相结合?例如,假设有 10 个挂起的回调。如果服务器重启,接收器将停止。在一个“基于事件”的系统,服务器将重新启动,一切都会顺利,第三方可能会在服务器宕机时看到 504 错误并重试。
存在不可恢复的状态。
依赖项
~9–19MB
~271K SLoC