使用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还是挺感兴趣的,如果文章中哪里有问题欢迎及时指正。

相关推荐
Autumn_ing6 小时前
Design.md生成UI怎么验收?举例运营后台的颜色、状态和数据核对
前端·ui·ai·设计系统·paico·ai生成ui·design.md
凤山老林6 小时前
Spring Boot 启动冲刺:耗时剖析、懒加载策略与事件驱动初始化优化
spring boot·后端·python
远离UE47 小时前
UE5 Substrate Thin Film 源码拆析
开发语言·javascript·ue5
keyipatience7 小时前
JavaScript学习(1)书写位置,变量、数据类型、运算符
开发语言·前端·javascript·css·学习
朱涛的自习室7 小时前
我给 Gemini 4 和 DeepSeek 搞了套「末位淘汰」,AI 干活会更猛吗?(Day 3)
android·前端·后端
java1234_小锋9 小时前
【技术专题】HTML5 网页技术 - HTML5简介 & HTML5 文档结构
前端·html·html5
woniu_maggie10 小时前
SAP MDG主数据治理实战:从架构原理到项目实施全解析
后端
xiaoqiMikko10 小时前
Redis 实战(一):内存满了 —— 拒写、淘汰、被系统杀掉,以及删了 key 内存为什么不降(6.2.4 实测)
redis·后端
鶴哥只手遮天10 小时前
Vue 3 核心源码深度剖析系列(v3.5.44)-第 1 章 项目全景:monorepo 架构与工程化体系
前端·vue.js·开源