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/
|
docs/
|
||||||
app.db
|
app.db
|
||||||
docker/server
|
docker/server
|
||||||
server
|
|
||||||
__debug_bin
|
__debug_bin
|
||||||
|
|
||||||
# Editor directories and files
|
# 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