向宁 11315fd00b feat: wire Watermill CQRS — EventBus in usecases, event handlers, router lifecycle
- Add EventPublisher interface in biz layer for domain event publishing
- Wire EventBusPublisher (Watermill EventBus adapter) into FileUsecase, FolderUsecase, ShareUsecase
- Publish events after UploadFile, DeleteFile, CreateFolder, DeleteFolder, CreateShare
- Implement CQRSHandler with logging event handlers for all 6 event types
- Register event handlers via CQRSBus.RegisterHandlers using Watermill EventProcessor
- Store subscriber and wmLogger in CQRSBus for EventProcessor wiring
- Expose SqlDB() on Data struct for Watermill SQL pub/sub
- Start Watermill router in goroutine alongside Kratos app with graceful close
- Use appContext wrapper struct to pass CQRSBus through Wire DI graph
2026-05-25 13:52:05 +08:00

95 lines
2.5 KiB
Go

//go:build wireinject
package main
import (
"database/sql"
"rag/file-system/internal/biz"
"rag/file-system/internal/conf"
"rag/file-system/internal/data"
"rag/file-system/internal/server"
"rag/file-system/internal/service"
"rag/file-system/internal/watermark"
"github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/transport/grpc"
"github.com/go-kratos/kratos/v2/transport/http"
"github.com/google/wire"
)
// appContext holds the Kratos app and CQRS bus together for Wire.
type appContext struct {
App *kratos.App
CQRSBus *watermark.CQRSBus
}
// newApp creates a new Kratos application with HTTP and gRPC servers.
func newApp(logger log.Logger, hs *http.Server, gs *grpc.Server) *kratos.App {
return kratos.New(
kratos.Name("file-system"),
kratos.Logger(logger),
kratos.Server(hs, gs),
)
}
// newAppContext wraps the app and CQRSBus into an appContext.
func newAppContext(app *kratos.App, bus *watermark.CQRSBus) *appContext {
return &appContext{App: app, CQRSBus: bus}
}
// newConfServer extracts the Server config from Bootstrap.
func newConfServer(bc *conf.Bootstrap) *conf.Server {
return bc.GetServer()
}
// newConfData extracts the Data config from Bootstrap.
func newConfData(bc *conf.Bootstrap) *conf.Data {
return bc.GetData()
}
// newConfAuth extracts the Auth config from Bootstrap.
func newConfAuth(bc *conf.Bootstrap) *conf.Auth {
return bc.GetAuth()
}
// newSQLDB extracts the underlying *sql.DB from Data for Watermill.
func newSQLDB(d *data.Data) (*sql.DB, error) {
return d.SqlDB()
}
// initApp wires up the entire dependency graph.
func initApp(*conf.Bootstrap, log.Logger) (*appContext, func(), error) {
panic(wire.Build(
// Config extraction
newConfServer,
newConfData,
newConfAuth,
// Provider sets from each layer
data.ProviderSet,
biz.ProviderSet,
service.ProviderSet,
server.ProviderSet,
watermark.ProviderSet,
// Extract *sql.DB from Data for Watermill
newSQLDB,
// Interface bindings: biz interfaces -> data implementations
wire.Bind(new(biz.FileRepo), new(*data.FileRepo)),
wire.Bind(new(biz.FolderRepo), new(*data.FolderRepo)),
wire.Bind(new(biz.FileMetaRepo), new(*data.FileMetaRepo)),
wire.Bind(new(biz.FileMetaRepoForShare), new(*data.FileMetaRepo)),
wire.Bind(new(biz.ShareRepo), new(*data.ShareRepo)),
// Interface binding: biz EventPublisher -> watermark EventBusPublisher
wire.Bind(new(biz.EventPublisher), new(*watermark.EventBusPublisher)),
// Wire up app + CQRSBus into appContext
newAppContext,
newApp,
))
}