69 lines
2.8 KiB
Cheetah
69 lines
2.8 KiB
Cheetah
package servicecontext
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync"
|
|
{{if ne .Storage "none"}}"net/http"
|
|
"git.yuntuo.hk/k2safe/go-omni/storage"{{end}}
|
|
{{if eq .Database "mysql"}}"time"
|
|
"git.yuntuo.hk/k2safe/go-omni/database"
|
|
"github.com/go-sql-driver/mysql"{{end}}
|
|
"git.yuntuo.hk/k2safe/go-omni/health"
|
|
"git.yuntuo.hk/k2safe/go-omni/httpx"
|
|
"git.yuntuo.hk/k2safe/go-omni/logx"
|
|
"git.yuntuo.hk/k2safe/go-omni/lifecycle"
|
|
"{{.Module}}/internal/settings"
|
|
"{{.Module}}/internal/middleware"
|
|
)
|
|
// Context owns infrastructure, while Logger is borrowed from main.
|
|
// Add business repositories here; HTTP contracts do not define database tables.
|
|
type Context struct {
|
|
Lifecycle *lifecycle.Controller
|
|
Config settings.Config
|
|
cleanups []func()error
|
|
Logger *logx.Logger
|
|
Health *health.Checker
|
|
Middlewares map[string]httpx.Middleware
|
|
{{if eq .Database "mysql"}}DB *database.DB{{end}}
|
|
{{if ne .Storage "none"}}
|
|
Files storage.Store
|
|
Uploads *storage.Uploader
|
|
Downloads storage.Presigner
|
|
UploadLinks storage.UploadPresigner
|
|
FileHTTP http.Handler
|
|
storageClose func()error
|
|
{{end}}
|
|
closeMu sync.Mutex
|
|
closed bool
|
|
closeOnce sync.Once
|
|
closeErr error
|
|
}
|
|
// Pass the settings loaded by main. The optional form supports lightweight
|
|
// tests without infrastructure; selected adapters still require valid settings.
|
|
func New(ctx context.Context,logger *logx.Logger,configs ...settings.Config)(result *Context,err error){
|
|
if ctx==nil{ctx=context.Background()}
|
|
if err=ctx.Err();err!=nil{return nil,errors.Join(err,lifecycle.Cause(ctx))}
|
|
if len(configs)>1{return nil,errors.New("expected at most one configuration")}
|
|
cfg:=settings.Default();if len(configs)==1{cfg=configs[0]}
|
|
_=cfg
|
|
checker,err:=health.New();if err!=nil{return nil,err}
|
|
c:=&Context{Config:cfg,Logger:logger,Health:checker,Middlewares:middleware.Defaults(),Lifecycle:lifecycle.New(ctx)}
|
|
ctx=c.Lifecycle.Context()
|
|
defer func(){if err!=nil{err=errors.Join(err,c.Close());if cause:=c.Lifecycle.Err();cause!=nil && !errors.Is(err,cause){err=errors.Join(err,cause)}}}()
|
|
{{if eq .Database "mysql"}}
|
|
if err=cfg.Validate();err!=nil{return nil,err}
|
|
dsn,parseErr:=mysql.ParseDSN(cfg.Database.DSN)
|
|
if parseErr!=nil || dsn.DBName=="" {return nil,errors.New("GO_OMNI_DB_DSN must contain a valid MySQL database name")}
|
|
dsn.ParseTime=true;dsn.Loc=time.UTC
|
|
cfg.Database.DSN=dsn.FormatDSN()
|
|
c.DB,err=database.Open(ctx,cfg.Database);if err!=nil{return nil,err}
|
|
if err=checker.Add(health.Probe{Name:"database",Timeout:cfg.Database.PingTimeout,Check:c.DB.Health});err!=nil{return nil,err}
|
|
{{end}}
|
|
{{if ne .Storage "none"}}if err=c.InitStorage(ctx,cfg.Storage);err!=nil{return nil,err}{{end}}
|
|
return c,nil
|
|
}
|
|
|
|
// RequestShutdown reports a fatal dependency failure, or a normal stop when
|
|
// err is nil. It returns immediately; generated main drains and cleans up.
|
|
func(c *Context)RequestShutdown(err error){c.Lifecycle.RequestShutdown(err)}
|