跳转到正文

编写 Go Worker ​

Go Worker 是由 Host 管理的独立进程:安装、配置、权限、事件和更新走同一套插件管理入口。使用 Go 1.23+ 编译,运行二进制不需要 Python;管理工具使用的 Python 环境另行配置。需要 Host API 1.9、Worker wire 1.0。

从工具包取得 sdk/go 与 examples/go-worker。SDK 的 module 名为 github.com/OmineDev/neomega-sdk-go,只依赖标准库。示例的 go.mod 使用 replace ... => ../../sdk/go,保留这两个目录的相对位置即可构建,不需要私有 Host 源码,也无需先从 module 代理下载 SDK。

1.1.0 还提供资源会话、远程 EP和可恢复投影。这些新能力需要 Host API 1.10,与基础 Worker 的 1.9 门槛区分。

1. 阅读状态服务示例 ​

examples/go-worker/main.go 是可修改的完整入口。它订阅 chat.received,把聊天计数和 durable ACK 放在同一个 CAS 提交中;同时导出原生 Bus go_state.count(候选可读 read)和 go_state.inspect(活动 service),两者为 EmptyRequest → u64。另保留在线服务 plugin.<manifest.id>.count 返回 label 与 count,major 为 1、参数为 {}。它不发送游戏动作。

回调示例行为
Validate加载配置,检查已有计数能否解码;不开始后台工作
Activate接受激活;该示例无需额外后台任务
Event读取 revision,以原 delivery token 派生 commit ID,原子提交计数和 ACK
Bus / ServiceBus 返回 tagged u64 计数;manifest exports 在线服务返回 label 与 count
Drain由 SDK 完成受管调用排空后返回

config.example.json 是配置模板,不会自动写入安装配置。LoadConfig 读取 Host 选择的配置;先给 Go struct 设置默认值。配置字段同时维护 config.schema.json。

Python 消费者在 permissions.services 声明 go_state.inspect 并取得对应授权后,可在激活阶段调用:

python
from neomega_runtime import u64

count = await ctx.bus.call("go_state.inspect", result_type=u64,
                           kind="service", major=1, timeout=5)

bus-contract.json 固定 EmptyRequest → u64 的结构和摘要,并通过 Go embed 编译进二进制;自行改变入参或结果时须同步更新合同、manifest 和回调。

2. 为目标平台构建 ​

在 examples/go-worker 内执行对应命令,每个 ZIP 只放一个目标平台的产物:

平台构建命令
Linux x64CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOWORK=off go build -trimpath -o worker .
Linux ARM64CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOWORK=off go build -trimpath -o worker .
Windows x64CGO_ENABLED=0 GOOS=windows GOARCH=amd64 GOWORK=off go build -trimpath -o worker.exe .
macOS IntelCGO_ENABLED=0 GOOS=darwin GOARCH=amd64 GOWORK=off go build -trimpath -o worker .
macOS Apple SiliconCGO_ENABLED=0 GOOS=darwin GOARCH=arm64 GOWORK=off go build -trimpath -o worker .

表中是 POSIX shell 命令,可交叉编译 Windows 产物。原生 PowerShell 使用 $env:GOOS="windows"、$env:GOARCH="amd64"、$env:CGO_ENABLED="0"、$env:GOWORK="off" 设置相同变量后执行 go build。

同步修改 manifest 的 target_os、target_arch 与 entrypoint。源码模板的 manifest 是 Linux amd64;下载的五平台发行包会将示例 manifest 与二进制一并设置为该包目标平台。以手中包内的 target_os/target_arch 为准;自行交叉编译时同步修改这两项。Windows 入口为 worker.exe。入口必须是包内安全相对路径,Host 直接执行它,不经 shell。平台不匹配会报告 worker_platform_mismatch。

json
{
  "runtime": "go",
  "target_os": "linux",
  "target_arch": "amd64",
  "entrypoint": "worker",
  "host_api": {"major": 1, "min_minor": 9},
  "worker_protocol": {"major": 1, "min_minor": 0}
}

这是需核对的字段片段;完整包继续保留示例 manifest 中的身份、订阅、权限、状态版本与 exports。发布时给自己的插件设置唯一 ID。Host 发行包内的预构建示例使用 example.go-state-<os>-<arch>,不要混用不同平台的 manifest 与二进制。

3. 打包并安装 ​

新建单独目录 plugins/go-state,放入目标二进制、完整 manifest.json、config.schema.json 与 config.example.json,再创建 package.files.json:

json
["worker", "manifest.json", "config.schema.json", "config.example.json"]

Windows 将清单中的 worker 改为 worker.exe。pack 必须读取这份显式清单,只收录清单中的文件;清单本身无需加入 ZIP。bus-contract.json 已编译进二进制,无需作为运行文件收录。不要收录配置实值、数据目录或凭据。

从工具包目录执行:

sh
python3 runtime-plugins.py pack plugins/go-state go-state.zip

ZIP 保存在插件目录外。安装沿用第一个插件的管理员控制台流程:安装包、配置、核对并授予申请权限、启用和启动。该示例需要活动游戏 session 才能接收聊天事件。Go 二进制随目标平台分发,不能把源码包当作可执行插件安装。

4. 接入自己的业务 ​

需要多个动作共用资源时,使用 scopes.New(neomega.NewManagedBus(peer)) 接入同一 Worker 连接,再按资源会话示例申请和关闭;需要连续观察时,将同一个适配器交给 busview.OpenProjection。插件停止前先关闭这些资源,最后结束 Worker。

入口使用 Open(ctx),把 Peer 交给 NewWorker(peer, callbacks).Run(ctx)。Validate、Activate、Drain、Event 都必须提供;可选 Service、Bus 和 Maintenance。日志写 stderr,stdout 留给协议。后台协作任务通过 worker.Spawn 注册并响应 context 取消;自行创建的 goroutine 不会自动变成受管工作。

事件成功返回不等于 ACK。需要状态与 ACK 一起推进时使用 PrepareCommit(..., &event);只提交 ACK 时使用 Storage.Ack。revision 冲突与回执不确定都应保留原 commit ID,查询 Storage.Receipt 后对账,不自动重试。

Bus 的 read/service 调用、导出合同和游戏操作回执见 Go SDK 行为参考。runtime-task 继续使用 Python;需要 Go 进程内 Frame 模块时走原生 Go 模块。Go Worker SDK 不提供 View/Publish 流提供者接口。

Neomega · 使用、开发与参考文档