业务模块
用 Module 组织业务入口
Module 是应用业务层的入口。用户、订单、支付、后台管理、数据同步,都可以各自做成一个 Module。
它和 Install(Provider) 很像:都会进入 Runa 的生命周期,也都能注册命令、Host、路由和读取 DI。区别是职责不同:Install 装框架能力,Module 装你的业务。
Module 和 Install 有什么区别
| 入口 | 主要用途 | 常见内容 |
|---|---|---|
app.Install(...) |
安装框架能力 | route、cache、queue、database、storage |
app.Module(...) |
装载业务模块 | user、order、billing、admin |
业务模块通常不创建新的框架能力,而是组合已经安装的能力:注册路由、命令、队列任务、事件监听器或定时任务。
先定义一个业务模块
package user
import (
"context"
"github.com/duxweb/runa/provider"
"github.com/duxweb/runa/route"
)
type Module struct {
provider.ModuleBase
}
func (Module) Name() string { return "user" }
func (Module) Register(ctx context.Context, app provider.Context) error {
route.Default().Get("/users", listUsers)
return app.RegisterCommand(UserSyncCommand{})
}
provider.ModuleBase 提供空生命周期方法。你只需要实现当前模块用到的阶段。
上面这个模块做了两件事:注册 /users 路由,注册 UserSyncCommand 命令。
把模块注册进应用
app := runa.New()
app.Install(
route.Provider(route.Addr(":8080")),
cache.Provider(),
)
app.Module(UserModule{})
if err := app.Run(context.Background()); err != nil {
panic(err)
}
根门面也提供同级入口:
runa.Install(route.Provider(route.Addr(":8080")))
runa.Module(UserModule{})
Module 里可以注册什么
Module 拿到框架上下文后,可以注册业务侧需要的内容:
RegisterCommand(...)注册业务命令RegisterHost(...)注册业务后台 Hostprovider.MustInvoke[T](app)读取已经注册到 DI 的能力route.Default().Get(...)注册 HTTP 路由
命令、路由、队列任务这类“声明式注册”建议放在 Register 阶段。
Module 也有 Shutdown
如果你的业务模块打开了连接、启动了后台协程,或者持有需要释放的资源,可以实现 Shutdown:
func (Module) Shutdown(ctx context.Context, app provider.Context) error {
return nil
}
普通业务模块通常不需要自己管理资源。数据库、缓存、队列这类能力应该交给对应能力包和 DI 管理生命周期。
模块依赖顺序
Module 可以声明依赖,让业务模块按依赖顺序执行生命周期:
func (Module) Depends() []string {
return []string{"auth"}
}
如果依赖缺失或出现循环依赖,应用启动会失败。
什么时候用 Module
- 业务域需要自己的路由、命令、任务和事件监听
- 一个业务域需要拆成独立目录维护
- 希望业务注册逻辑走统一生命周期,而不是散落在
main.go - 希望业务模块之间能声明依赖关系
当前应用自己的业务入口,优先写 Module。可复用框架能力或第三方扩展,才需要写 Provider。
常见错误
把框架能力写成 Module
当前应用自己的业务入口用 Module。可复用的框架能力、驱动和第三方扩展才写 Provider。
Module 里直接创建全局连接
数据库、缓存、队列等通用能力应通过对应 Provider 管理。业务自己的资源如果必须创建,也要在 Shutdown 中释放。
Depends 名称写错
Depends() 返回的是模块 Name(),不是 Go 包名或目录名。
一个实用建议
Module 不一定要很大。一个后台项目可以只有 admin.Module,一个复杂系统可以拆成 user.Module、order.Module、payment.Module。按业务边界拆,不按技术层强行拆。