server: publish code
This commit is contained in:
parent
01c974d595
commit
35221ee1a8
2 changed files with 188 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,7 +2,6 @@
|
|||
docs/
|
||||
app.db
|
||||
docker/server
|
||||
server
|
||||
__debug_bin
|
||||
|
||||
# Editor directories and files
|
||||
|
|
|
|||
188
cmd/server/main.go
Normal file
188
cmd/server/main.go
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
"wpw-common/internal"
|
||||
"wpw-common/pkg/gen/biz/core"
|
||||
|
||||
"context"
|
||||
|
||||
coresvc "wpw-common/internal/biz/core"
|
||||
"wpw-common/internal/http"
|
||||
"wpw-common/internal/system"
|
||||
"wpw-common/pkg/gormlog"
|
||||
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
_ "gorm.io/driver/mysql"
|
||||
"gorm.io/driver/sqlite"
|
||||
_ "gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
appCtx = (internal.AppContext{}).Init()
|
||||
ctx context.Context
|
||||
|
||||
appSecret string
|
||||
taskWaitDuration = time.Second * 10
|
||||
serverListenAddr = "0.0.0.0:8000"
|
||||
dataSourceType = "sqlite"
|
||||
dsn = "./app.db"
|
||||
fallabackFlagValue func()
|
||||
)
|
||||
|
||||
func osEnvFallback(s string, key string) string {
|
||||
if s != "" {
|
||||
return s
|
||||
}
|
||||
return os.Getenv(key)
|
||||
}
|
||||
|
||||
func gormSetup(driver string, dsn string, config *gorm.Config) (*gorm.DB, error) {
|
||||
if driver == "" {
|
||||
driver = "sqlite"
|
||||
if dsn == "" {
|
||||
dsn = "./app.db"
|
||||
}
|
||||
}
|
||||
switch driver {
|
||||
case "sqlite":
|
||||
return gorm.Open(sqlite.Open(dsn), config)
|
||||
case "mysql":
|
||||
return gorm.Open(mysql.Open(dsn), config)
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown driver %s", driver))
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
// flags
|
||||
flag.DurationVar(&taskWaitDuration, "grace-duration",
|
||||
taskWaitDuration, "graceful wait duration")
|
||||
flag.StringVar(&appSecret, "secret", appSecret, "Application secret")
|
||||
flag.StringVar(&serverListenAddr, "addr",
|
||||
serverListenAddr, "Server listen address")
|
||||
flag.StringVar(&dataSourceType, "dst", dataSourceType, "Data source")
|
||||
flag.StringVar(&dsn, "dsn", dsn, "DSN")
|
||||
fallabackFlagValue = func() {
|
||||
appSecret = osEnvFallback(appSecret, "SECRET")
|
||||
serverListenAddr = osEnvFallback(serverListenAddr, "ADDR")
|
||||
dataSourceType = osEnvFallback(dataSourceType, "DRIVER")
|
||||
dsn = osEnvFallback(dsn, "DSN")
|
||||
}
|
||||
|
||||
appCtx.Logger, err = zap.NewDevelopment()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// initalize application context
|
||||
ctx, appCtx.Cancel = context.WithCancel(context.Background())
|
||||
ctx = internal.WithAppContext(ctx, &appCtx)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
flag.Parse()
|
||||
fallabackFlagValue()
|
||||
|
||||
defer appCtx.Logger.Sync()
|
||||
sugar := appCtx.Logger.Sugar().Named("main")
|
||||
sugar.Info("starting app")
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, os.Interrupt)
|
||||
|
||||
// push secret to context
|
||||
if appSecret == "" {
|
||||
sugar.Fatal("application secret is empty")
|
||||
}
|
||||
appCtx.Data["secret"] = appSecret
|
||||
|
||||
// initialize db
|
||||
if appCtx.Data["db"], err = gormSetup(dataSourceType, dsn, &gorm.Config{
|
||||
Logger: gormlog.New(gormlog.GormLogParams{
|
||||
LogLevel: logger.Info,
|
||||
SlowThreshold: time.Second * 2,
|
||||
IgnoreRecordNotFoundError: true,
|
||||
Logger: appCtx.Logger,
|
||||
}),
|
||||
}); err != nil {
|
||||
sugar.Fatalw("db error",
|
||||
"driver", dataSourceType,
|
||||
"err", err)
|
||||
}
|
||||
|
||||
// system init
|
||||
system.Init(&appCtx)
|
||||
|
||||
// register services
|
||||
http.RegisterService("/api/core/v1", core.NewCoreServiceProcessor(
|
||||
coresvc.NewCoreServiceFromAppContext(&appCtx)))
|
||||
|
||||
//
|
||||
|
||||
appCtx.DoTask(func(ctx context.Context) {
|
||||
sugar.Info("task start")
|
||||
defer sugar.Info("task done")
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 40):
|
||||
return
|
||||
case <-ctx.Done():
|
||||
sugar.Info("task notify cancel")
|
||||
<-time.After(time.Second * 5)
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// start server
|
||||
appCtx.DoTask(func(ctx context.Context) {
|
||||
errChan := make(chan error, 1)
|
||||
go func() { errChan <- http.Run(&appCtx, serverListenAddr) }()
|
||||
if err := <-errChan; err != nil {
|
||||
sugar.Errorw("server error",
|
||||
"err", err)
|
||||
}
|
||||
})
|
||||
|
||||
spin:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
sugar.Info("waiting task done",
|
||||
"cnt", appCtx.TaskCount())
|
||||
done := make(chan struct{}, 1)
|
||||
go func() { appCtx.WaitTask(); done <- struct{}{} }()
|
||||
select {
|
||||
case <-done:
|
||||
break spin
|
||||
case sig := <-sig:
|
||||
// cancel the wait
|
||||
sugar.Fatalw("waiting task cancelled",
|
||||
"sig", sig,
|
||||
"remaining", appCtx.TaskRemaining(),
|
||||
)
|
||||
case <-time.After(taskWaitDuration):
|
||||
sugar.Fatalw("timeout waiting task done",
|
||||
"remaining", appCtx.TaskRemaining())
|
||||
}
|
||||
case sig := <-sig:
|
||||
sugar.Infow("received signal",
|
||||
"sig", sig,
|
||||
)
|
||||
appCtx.Cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue