Files
core/sdk/README.md
T

60 lines
5.2 KiB
Markdown

# Python、JavaScript 与 Go SDK
SDK 用于把现成的 Python、JavaScript 或 Go 能力接入 Dever。应用先声明 Port,再用外部 Adapter 对接;Dever 会管理 Worker 进程和通信。
开发应用先看 [三种语言的完整例子](../skills/references/external-lib.md)。那里包含同一 Port、三种 Adapter、处理函数和 fake 测试,不需要手写协议或维护另一份接口注册表。
## 处理函数怎么写
函数名与 Port 操作名对应。输入、输出和业务错误的类型由 Dever 编译器生成,SDK 负责验证。
| 语言 | 处理函数 | 加载生成的接口定义 |
| --- | --- | --- |
| Python | 异步函数 | `Worker.from_manifest(manifest, handlers)` |
| JavaScript | 函数接收 `AbortSignal`;支持 ESM 导出或 CommonJS 属性 | `Worker.fromManifest(manifest, handlers)` |
| Go | 函数接收 `context.Context` | `NewFromManifest(manifest)`,再 `RegisterHandlers(handlers)` |
处理函数返回能用 JSON 表达的值,业务失败返回已声明的 `BusinessError`。不要往 stdout 写日志;stdout 用于 Worker 通信,日志写 stderr。
取消请求会产生一次 `dever.cancelled` 错误,已取消调用的结果会被丢弃。如果处理函数一秒内不响应取消,Worker 失败并停止接收新调用。Dever 管理进程与 stdin;自行在 Go 进程内调用 `Serve` 时,调用方负责关闭或解除自己的 `io.Reader` 阻塞。
## SDK 维护与验证
维护 SDK 时,显式指定本机运行环境的绝对路径:
```text
/usr/bin/python3 -B test/external-sdk/check.py --python /usr/bin/python3 --node /absolute/path/to/node --go /absolute/path/to/go
```
未指定的语言报告 `unavailable`,不会通过 PATH 猜测。Go 夹具在临时离线缓存中构建。这项检查验证本机 SDK 和类型协议;不能代替发行包或“机器未安装 Python/Node/Go”的运行验收。普通应用测试使用 Port fake,不启动真实 Worker。
编译器通过 `ExternalWorkerContract::sdk_manifest()` 生成唯一接口定义,包括身份、配置、输入、输出和业务错误。SDK 在 `hello` 时核对身份,不接受 supervisor 临时指定的 schema。配置在 `ready` 前解码,只读取 `hello.setting`。
本目录的三个 `example` 展示底层 `Contract`/`Worker` 注册 API,用于协议夹具。`fixture-schema-v1` 和 `test/external-sdk/typed_contract.json` 都是测试数据,不能复制成生产 Port hash。通信帧由 4 字节大端长度和 UTF-8 JSON 组成。
SDK 不依赖第三方包,也不读取环境变量或 PATH。托管 Worker 只读取已打包的 manifest。Python 固定使用 `-I -S -B`,先加载打包的 SDK,再把 Adapter 与依赖加入 `sys.path`。
## 依赖与跨平台构建
`dever lib install <project>` 按现有锁恢复依赖,不重新选版本、不修改配置或锁。`dever-lock-v6` 记录 Python extras/wheel METADATA、npm 嵌套依赖及 peers/optional/bundled 依赖、Go 模块校验证据。原始包保留来源与文件名,构建记录保留完整输入,包括 npm 剪除可选构建依赖前的依赖图。
丢失的构建结果由同一沙箱重建,必须与记录的摘要一致。Python 原生 wheel 安装到配套解释器中,必须满足签名声明的标签、扩展 ABI 和动态库依赖要求。
生成 ARM64 应用时,先运行 `dever lib update <project> --target linux-aarch64`,再运行 `dever build <project> --target linux-aarch64 --output <new-file>`。Port 和 Worker 源码无需改写;锁、解释器、原生依赖和沙箱资源必须匹配目标平台。缺少目标资源时失败,不借用宿主运行环境。`run/test` 仍在本机执行。
Go pack 的 `build.host` 描述编译器、链接器与分析器的运行平台;`build.goos/goarch` 和标准库对象头描述输出平台。工具在清空的环境中执行,目标必须预先正确配置。
## 第三方源码构建限制
只有显式准备 Lib 时才构建 Python sdist 或运行 npm 安装钩子。构建使用签名工具包和 Linux 沙箱,输入只读、网络关闭,写入仅限本次临时目录。缺少工具时不回退宿主 PATH。
Python PEP 517 的构建依赖单独锁定,每个 hook 使用新进程,最终 wheel 按保留的元数据核对。npm 的配套运行器处理 `preinstall/install/postinstall`、依赖 bin 和 node-gyp。
构建记录绑定源码、目标运行环境、工具、构建前端、依赖图和输出摘要。Worker 准备阶段离线恢复结果,不重跑安装钩子。npm `.node` 产物须通过目标检查、动态加载检查和独立 Node 加载探测,才能进入只读 Worker 目录;线程和子进程也受此限制。不匹配平台或 ABI 的其他变体保留在锁定原始包中,不加入运行目录。运行时原生依赖只能来自 Worker 目录或签名 OS 库,不能借用编译器 sysroot。
生成的原生 addon 验证失败,整个构建就失败;使用纯 JS 备用路径不能证明原生构建成功。当前限制:
- 构建进程最多 5 分钟,stdout/stderr 各最多 16 MiB。
- 每 250 毫秒检查临时目录,限制 512 MiB、65,536 个条目;这是定期检查,检查间隔内可能短暂超出。
- 最终 Worker 最多 256 MiB、65,536 个条目。失败时清理本次拥有的进程。