6 个版本 (3 个破坏性更新)
0.8.0 | 2022年4月18日 |
---|---|
0.7.0 | 2022年4月15日 |
0.6.0 | 2022年4月12日 |
0.5.2 | 2022年4月11日 |
#652 in 并发
37KB
720 行
Rust Node Workers
这允许您使用工作进程池从 Rust 代码调用 node 二进制文件。这对于大多数代码用 Rust 编写但需要利用 Node 包执行某些任务(如使用 TypeScript 的 API 或使用 JS 框架进行 SSR)的项目很有用。
使用工作进程池是避免在多次调用中启动 node 二进制文件成本的基本方法。中等或大型 Node 二进制文件可能需要约一秒(或更长时间)来启动(或更多),使用一组长生存期进程可以在后续运行中节省您的时间。如果在您的程序使用过程中需要多次与 node 二进制文件交互,可重用和长生存期进程将为您节省大量时间。
此解决方案与在 Node 中调用 rust(如使用 napi-rs
等解决方案)的方式不同。如果您的代码大部分是用 Rust 编写的,那么创建和维护 node 插件的额外开销将不值得。
该池会启动一个长生存期 node 进程,并通过 stdin/stdout 与其通信,这使得此解决方案跨平台。
要与其通信,node-workers
提供了一个桥接器,需要在创建要与之交互的 node 二进制文件时使用。
// worker.js
const { bridge } = require('rust-node-workers');
bridge({
ping: (payload) => {
console.log(`pong at ${new Date()}`);
return payload * 2;
}
});
然后,您可以从 Rust 代码分配任务给这个工作进程
use node_workers::{WorkerPool};
let mut pool = WorkerPool::setup("worker", 4); // 4 max workers
let result = pool.perform::<u32, _>("ping", vec![100]).unwrap();
println!("result: {:?}", result);
安装
需要安装 npm 包来设置桥接器
yarn add rust-node-workers
在您的 rust 项目中
[dependencies]
node-workers = "0.8.0"
用法
此 crate 暴露了一个 WorkerPool
,您可以用池的长度实例化它。当需要执行任务时,如果需要,将创建一个新的工作进程,直到达到最大数量。
let pool = WorkerPool::setup("examples/worker", 4); // 4 max workers
然后,您可以使用 run_worker
或 perform
从您的工人调用任务。
run_worker
在新线程上的工作进程中执行任务。在线程上使用 get_result
将等待工作进程完成并反序列化结果(如果有)。
let mut pool = WorkerPool::setup("examples/worker", 2);
pool.run_worker("fib", 80u32); // on a separate thread
let thread = pool.run_worker("fib2", 40u32);
// join the thread's handle
let result = thread.get_result::<u32>().unwrap();
println!("run_worker result: {:?}", result);
perform
接收要处理的数据数组,并为每个值运行一个工作进程。
let files = /* vector of TypeScript files */;
// execute the command "getInterfaces" on every file
// each executed worker will return an array of interfaces (Vec<Interface>)
let interfaces = pool
.perform::<Vec<Interface>, _>("getInterfaces", files)
.unwrap();
// it may be benefic to send multiple files to each worker instead of just one
let file_chunks = files.chunks(30);
let interfaces = pool
.perform::<Vec<Interface>, _>("getInterfacesBulk", file_chunks)
.unwrap();
对于不需要任何有效负载的任务,可以使用 EmptyPayload
。
pool.run_worker("ping", EmptyPayload::new());
开发
构建
yarn build
运行示例
cargo run --example
发布
版本-请更新
- 调整 package.json 版本
git提交 -m "chore: 发布" && gittag vx.y.z && git推送 --跟踪标签
npm发布--访问=公开
依赖项
~0.8–1.5MB
~34K SLoC