如何在Substrate中实现后台线程?
假设我想设计一个类似于众筹或拍卖的系统。此类事件运行有一段固定的时间。我可以启动一个后台线程,它会定期检查是否已到达事件的结束时间并随后关闭该事件?我正在查看futures板条箱(和其他一些板条箱),但它可以在 Substrate 中使用吗?是否有关于如何处理此类场景的最佳实践?
回答
我相信答案futures是否定的。这里有更多解释:
我认为最好考虑在 Substrate 运行时中可用的编程原语,而不是尝试使用通用编程中的概念(future)并尝试将其重新用于 Substrate 运行时(自上而下与底部 -向上的观点)。
所以,让我们考虑一下运行时的生命周期,看看那里有什么意义:
在运行时内,您有点被困在一个盒子里。每当有新块要导入(或编写,但我们假设现在只导入)时,(总是本机的)客户端就会生成和执行(wasm)运行时代码,然后将其杀死并放在一边(至少从运行时的视角——客户端有运行时缓存)。我的观点是,在每个块的执行结束时,您未提交状态(即写入存储)的任何内容都将丢失。这包括所有局部变量、堆栈、堆和其他任何东西。因此,即使您要使用 future 来生成任务,这也并不真正适合 Substrate 运行时的编程模型,因为即使该 future 存在于运行时中,一旦块完成,wasm 实例就是死了,未来也是。
这完全忽略了一个事实,即您只能使用no_std在运行时支持的 crate ,因此无论如何并非每个异步库都可用。
主要的解决方案,正如我所暗示的,可能是使用状态存储来记录拍卖的起点,以便在 x 块之后你仍然可以知道你是什么时候开始的,如果超过了某个阈值,那么你就可以完成你的拍卖。您可以在拍卖期间使用时间戳或多个区块。类似的东西:
trait Config: frame_system::Config {
// duration in time or block number
type AuctionDuration<T::BlockNumber>;
}
// inside your on_initialize
fn on_initialize(n: T::BlockNumber) {
if n % T::AuctionDuration::get() == 0 {
// ^^^^^ note: ensure this is non-zero, else panic in runtime might happen.
// time to close the auction.
}
}