server: publish code

This commit is contained in:
Nugraha 2022-12-04 04:35:58 +07:00
parent 01c974d595
commit 35221ee1a8
Signed by: ii64
GPG key ID: E41C08AD390E7C49
2 changed files with 188 additions and 1 deletions

1
.gitignore vendored
View file

@ -2,7 +2,6 @@
docs/
app.db
docker/server
server
__debug_bin
# Editor directories and files

188
cmd/server/main.go Normal file
View 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()
}
}
}