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

相关推荐
ZZHHWW9 分钟前
RocketMQ vs Kafka01 - 存储架构深度对比
后端
How_doyou_do14 分钟前
模态框的两种管理思路
java·服务器·前端
snow@li38 分钟前
前端:前端/浏览器 可以录屏吗 / 实践 / 录制 Microsoft Edge 标签页、应用窗口、整个屏幕
前端·浏览器录屏·前端录屏·web录屏
依_旧42 分钟前
MySQL下载安装配置(超级超级入门级)
java·后端
李贺梖梖44 分钟前
CSS学习
前端·css
熊小猿1 小时前
RabbitMQ死信交换机与延迟队列:原理、实现与最佳实践
开发语言·后端·ruby
蚂小蚁1 小时前
一文吃透:宏任务、微任务、事件循环、浏览器渲染、Vue 批处理与 Node 差异(含性能优化)
前端·面试·架构
淘源码d1 小时前
什么是医院随访系统?成熟在用的智慧随访系统源码
java·spring boot·后端·开源·源码·随访系统·随访系统框架
武子康1 小时前
大数据-147 Java 访问 Apache Kudu:从建表到 CRUD(含 KuduSession 刷新模式与多 Master 配置)
大数据·后端·nosql