使用elysiajs,实现一个ffi运行在worker的a+b计算的接口

elysia 是一个bunjs web框架,通过 Bun 运行时、静态代码分析和动态代码注入增效,成为性能最佳的 TypeScript 框架之一。可与 Go 和 Rust 相媲美,发展了快2年也是出了1.0稳定版本,bun现在也支持windows了,bun听说很快,让我来看看怎么个事。

话不多说直接开始,首先安装一下bunjs

bash 复制代码
# windows
powershell -c "irm bun.sh/install.ps1 | iex"

# mac & linux
curl -fsSL https://bun.sh/install | bash

然后使用bun create elysia app创建一个名为app的elysia项目,我这边同时安装一下prisma和eslint,如果不操作数据库,且不需要eslint那么则跳过当前部分,在bun项目中使用prisma文档,eslint 由于不想配置,直接使用@antfu/eslint-config

bash 复制代码
bun add eslint @antfu/eslint-config

如果安装缓慢,在项目根目录创建bunfig.toml,为当前项目的bun设置淘宝镜像

bash 复制代码
[install]
registry = "https://registry.npmmirror.com/"

项目根目录创建eslint.config.mjs

js 复制代码
// eslint.config.mjs
import antfu from '@antfu/eslint-config'

export default antfu()

安装swagger @elysiajs/swagger

这边我选择使用rust来对接,安装rust直接找个空文件夹创建一个add.rs

rust 复制代码
// add.rs
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

然后终端执行rustc --crate-type cdylib add.rs打包成插件给bun调用 将打包后的libadd文件放入elysia项目根目录新建文件夹libs下,/libs/libadd.dylib。

src下创建worker.ts文件,把下面代码复制进去

ts 复制代码
// /src/worker.ts
/* eslint-disable no-var */

import { FFIType, dlopen, suffix } from 'bun:ffi'

declare var self: Worker

const path = `libs/libadd.${suffix}`
const { symbols: {
  add,
} } = dlopen(path, {
  add: {
    args: [FFIType.int, FFIType.int],
    returns: FFIType.int,
  },
})

self.onmessage = (event: MessageEvent) => {
  const res = add(event.data.a, event.data.b)

  postMessage(res)
}
ts 复制代码
// /src/index
import { Elysia, t } from 'elysia'
import { swagger } from '@elysiajs/swagger'

const app = new Elysia()
app.use(
  swagger({
    provider: 'swagger-ui',
  }),
)

const worker = new Worker(new URL('worker.ts', import.meta.url).href)
function getWorker(a: number, b: number) {
  return new Promise<number>((resolve) => {
    worker.onmessage = (event) => {
      resolve(event.data)
    }
    worker.postMessage({
      a,
      b,
    })
  })
}
app.get('/add', async ({ query }) => {
  return getWorker(Number(query.a), Number(query.b))
}, {
  query: t.Object({
    a: t.Integer(),
    b: t.Integer(),
  }),
  response: t.Number(),
  transform({ query }) {
    query.a = Number(query.a)
    query.b = Number(query.b)
  },
})

app.listen(3000)

执行bun dev 运行项目,浏览器输入http://localhost:3000/swagger,就能看到swagger文档了

也是成功的运行成功了。

相关代码截图

/src/index.ts

/src/worker.ts

写在最后,说一下,本人也是刚学一会,没多久,写个文章想问一下有没有交流群之类的,一起学习一下,对elysia和prisma还是挺感兴趣的,如果文章中哪里有问题欢迎及时指正。

相关推荐
今天不要写bug6 分钟前
基于elementUI实现一个可编辑的表格(简洁版)
前端·javascript·elementui
上优9 分钟前
Vue3纯前端同源跨窗口通信移动AGV小车
前端·vue.js·状态模式
h_k100869 分钟前
Chrome 插件开发入门技术文章大纲
前端·chrome
一只小阿乐9 分钟前
vue-router 的实现原理
前端·javascript·vue.js·路由·vue-router
绝无仅有10 分钟前
面试之MySQL 高级实战& 优化篇经验总结与分享
后端·面试·github
Zz_waiting.10 分钟前
案例开发 - 日程管理 - 第七期
开发语言·前端·javascript·vue.js·html·路由
writeone11 分钟前
9-10关于JS初学产生的问题
开发语言·javascript·ecmascript
绝无仅有12 分钟前
某云大厂面试之Go 实际问题及答案
后端·面试·github
一只小风华~14 分钟前
Vue:事件处理机制详解
前端·javascript·vue.js·typescript·前端框架