RRuna

应用入口

创建应用、安装能力和注册业务模块

Runa 应用入口只需要关心三件事:创建应用、安装需要的能力、注册自己的业务模块。

能力包会提供 Provider(),应用把它交给 Install。业务代码放进 Module,由应用统一启动和关闭。

先创建应用

app := runa.New()

这会创建一个应用对象,并默认安装配置能力和内置命令。

常用路径选项:

app := runa.New(
    runa.BasePath("."),
    runa.ConfigPath("config"),
    runa.DataPath("data"),
    runa.PublicPath("public"),
    runa.Env("production"),
)

这些路径会被配置、静态资源、上传文件、缓存文件等能力使用。

用 Install 安装框架能力

app.Install(
    route.Provider(route.Addr(":8080")),
    cache.Provider(),
    queue.Provider(),
)

这里的 Provider() 来自各个能力包。安装后,这些能力会进入应用的 DI、配置、命令和生命周期。

普通应用开发时,你不需要自己实现 Provider,只需要安装能力包提供的 Provider。

用 Module 注册业务域

app.Module(
    user.Module{},
    order.Module{},
)

业务模块负责注册当前应用自己的路由、命令、任务和事件监听。

写什么 用哪个入口
框架能力 Install
业务模块 Module
单个命令 Command
单个 Host Host

启动应用

if err := app.Run(context.Background()); err != nil {
    panic(err)
}

Run 会读取终端参数。没有传参数时,默认执行 serve 命令。serve 只启动已经注册到应用里的 Host。

route.Provider(route.Addr(...)) 会自动把 HTTP 服务注册成 Host,所以普通 HTTP 应用直接 Run 就能启动。

queue.Provider(...) 会注册队列、worker 和 queue:work 命令,但不会自动把 worker 注册成 Host。默认推荐用独立进程启动 worker:

go run . queue:work default

如果你希望 Run 同时启动 HTTP 和队列 worker,可以在业务 Module 里显式注册 worker Host:

func (Module) Register(ctx context.Context, app provider.Context) error {
    queues, err := provider.Invoke[*queue.Registry](app)
    if err != nil {
        return err
    }
    return app.RegisterHost(queue.NewUnit(queues, "default"))
}

小项目或开发环境可以把 HTTP 和 worker 放在同一个进程。生产环境如果要独立扩缩容,通常拆成 servequeue:work 两个进程更清晰。

如果你只想执行指定命令,可以用 Execute

if err := app.Execute(context.Background(), []string{"config:show"}); err != nil {
    panic(err)
}

使用全局默认应用

小项目也可以使用根门面:

runa.Install(route.Provider(route.Addr(":8080")))
runa.Module(user.Module{})

if err := runa.Run(context.Background()); err != nil {
    panic(err)
}

这种写法和 app := runa.New() 后调用方法是同一个模型,只是更短。

常见错误

把业务逻辑都写进 main.go

main.go 应该只做装配。业务路由、命令、任务建议放进 Module。

忘记安装能力

如果你调用 route.Default(),必须先安装 route.Provider(...)。如果你调用 cache.Default(),必须先安装 cache.Provider()

太早读取 Default

Default() 依赖应用生命周期。不要在包级全局变量里写 var store = cache.Default(),应该在 handler、命令或生命周期方法里读取。

编辑此页