update: readme.md; feat: add flag

This commit is contained in:
loveuer 2025-01-01 21:01:05 -08:00
parent 25b36157c7
commit a9039115d8
13 changed files with 192 additions and 75 deletions

View File

@ -3,5 +3,6 @@ package upp
import "context"
type Config struct {
Ctx context.Context
Ctx context.Context
Debug bool
}

24
flag.go Normal file
View File

@ -0,0 +1,24 @@
package upp
import (
"flag"
"time"
)
type __flag struct {
debug bool
listen struct {
http string
}
}
var _flag = &__flag{}
func init() {
time.Local = time.FixedZone("CST", 8*3600)
flag.BoolVar(&_flag.debug, "debug", false, "debug mode")
flag.StringVar(&_flag.listen.http, "listen.http", "localhost:8080", "")
flag.Parse()
}

3
go.mod
View File

@ -14,6 +14,7 @@ require (
github.com/loveuer/nf v0.3.1
github.com/samber/lo v1.47.0
github.com/spf13/cast v1.7.1
github.com/spf13/cobra v1.8.1
golang.org/x/crypto v0.25.0
gorm.io/driver/mysql v1.5.7
gorm.io/driver/postgres v1.5.11
@ -27,6 +28,7 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
@ -38,6 +40,7 @@ require (
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.21.0 // indirect

9
go.sum
View File

@ -4,6 +4,7 @@ gitea.com/loveuer/gredis v1.0.0 h1:fbRS8YZObcp1KV1KGj8pDpIj1WrI0W8pwU9Ny/2fJys=
gitea.com/loveuer/gredis v1.0.0/go.mod h1:TQlubgDiyNTRXqASd/XIUrqPBLj9NZRR2DmV3V2ZyMY=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
@ -31,6 +32,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
@ -67,10 +70,15 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -91,6 +99,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=

1
pkg/cache/cache.go vendored
View File

@ -19,6 +19,7 @@ type Cache interface {
// SetEx value 会被序列化, 优先使用 MarshalBinary 方法, 没有则执行 json.Marshal
SetEx(ctx context.Context, key string, value any, duration time.Duration) error
Del(ctx context.Context, keys ...string) error
Close() error
}
type Scanner interface {

View File

@ -134,6 +134,11 @@ func (l *_lru) Del(ctx context.Context, keys ...string) error {
return nil
}
func (l *_lru) Close() error {
l.client = nil
return nil
}
func newLRUCache() (Cache, error) {
client := expirable.NewLRU[string, *_lru_value](1024*1024, nil, 0)

View File

@ -103,3 +103,9 @@ func (m *_mem) Del(ctx context.Context, keys ...string) error {
m.client.Delete(keys...)
return nil
}
func (m *_mem) Close() error {
m.client = nil
return nil
}

View File

@ -104,3 +104,7 @@ func (r *_redis) SetEx(ctx context.Context, key string, value any, duration time
func (r *_redis) Del(ctx context.Context, keys ...string) error {
return r.client.Del(ctx, keys...).Err()
}
func (r *_redis) Close() error {
return r.client.Close()
}

View File

@ -9,6 +9,7 @@ import (
)
type Upp interface {
Debug() bool
UseCtx() context.Context
UseDB(ctx ...context.Context) *gorm.DB
UseCache() cache.Cache

View File

@ -2,6 +2,7 @@
### Usage
> usage present
```go
app := upp.New()
@ -9,3 +10,34 @@ app.With(db, es, api)
app.Run(ctx)
```
> simple example
```go
type Record struct {
Id uint64 `json:"id" gorm:"primaryKey;column:id"`
CreatedAt int64 `json:"created_at" gorm:"column:created_at;autoCreateTime:milli"`
Name string `json:"name" gorm:"column:name"`
}
func main() {
app := upp.New()
app.With(upp.InitDB("sqlite://data.db", &Record{}))
app.With(upp.InitApi(api.New()))
app.GET("/hello/:name", func(c *api.Ctx) error {
name := c.Param("name")
c.UseLogger().Info("[hello] got name = %s", name)
record := &Record{Name: name}
err := c.UseDB().Create(record).Error
return c.JSON(map[string]any{"record": record, "err": err})
})
app.RunSignal()
}
```
> run with flags
```sh
go run . --debug --listen.http '0.0.0.0:8080'
```

88
run.go Normal file
View File

@ -0,0 +1,88 @@
package upp
import (
"context"
"os/signal"
"syscall"
"github.com/loveuer/upp/pkg/interfaces"
"github.com/loveuer/upp/pkg/tool"
)
func (u *upp) StartAPI(ctx context.Context) {
address := _flag.listen.http
if address == "" {
address = u.api.config.Address
}
u.UseLogger().Info("UPP | run api at %s", address)
go u.api.engine.Run(address)
go func() {
<-ctx.Done()
u.api.engine.Shutdown(tool.Timeout(2))
}()
}
func (u *upp) StartTask(ctx context.Context) {
for _, _ch := range u.taskCh {
go func(ch <-chan func(interfaces.Upp) error) {
var err error
for {
select {
case <-ctx.Done():
case task, ok := <-ch:
if !ok {
return
}
if err = task(u); err != nil {
u.UseLogger(ctx).Error(err.Error())
}
}
}
}(_ch)
}
}
func (u *upp) Run(ctx context.Context) {
u.RunSignal(ctx)
}
func (u *upp) RunInitFns(ctx context.Context) {
for _, fn := range u.initFns {
fn(u)
}
}
func (u *upp) RunSignal(ctxs ...context.Context) {
c := context.Background()
if len(ctxs) > 0 {
c = ctxs[0]
}
ctx, cancel := signal.NotifyContext(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
defer cancel()
u.ctx = ctx
if len(u.initFns) > 0 {
u.RunInitFns(ctx)
}
if u.api != nil {
u.StartAPI(ctx)
}
if len(u.taskCh) > 0 {
u.StartTask(ctx)
}
<-ctx.Done()
u.UseLogger().Warn(" UPP | quit by signal...")
if u.cache != nil {
u.cache.Close()
}
<-tool.Timeout(2).Done()
}

85
upp.go
View File

@ -2,15 +2,13 @@ package upp
import (
"context"
"os/signal"
"sync"
"syscall"
"github.com/elastic/go-elasticsearch/v7"
"github.com/loveuer/upp/pkg/api"
"github.com/loveuer/upp/pkg/cache"
"github.com/loveuer/upp/pkg/interfaces"
"github.com/loveuer/upp/pkg/tool"
"github.com/loveuer/upp/pkg/log"
"gorm.io/gorm"
)
@ -37,79 +35,20 @@ func (u *upp) With(modules ...module) {
}
}
func (u *upp) Run(ctx context.Context) {
u.RunSignal(ctx)
}
func (u *upp) RunInitFns(ctx context.Context) {
for _, fn := range u.initFns {
fn(u)
}
}
func (u *upp) RunSignal(ctxs ...context.Context) {
c := context.Background()
if len(ctxs) > 0 {
c = ctxs[0]
}
ctx, cancel := signal.NotifyContext(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
defer cancel()
u.ctx = ctx
if len(u.initFns) > 0 {
u.RunInitFns(ctx)
}
if u.api != nil {
u.StartAPI(ctx)
}
if len(u.taskCh) > 0 {
u.StartTask(ctx)
}
<-ctx.Done()
u.UseLogger().Warn(" UPP | quit by signal...")
<-tool.Timeout(2).Done()
}
func (u *upp) StartAPI(ctx context.Context) {
u.UseLogger().Info("UPP | run api at %s", u.api.config.Address)
go u.api.engine.Run(u.api.config.Address)
go func() {
<-ctx.Done()
u.api.engine.Shutdown(tool.Timeout(2))
}()
}
func (u *upp) StartTask(ctx context.Context) {
for _, _ch := range u.taskCh {
go func(ch <-chan func(interfaces.Upp) error) {
var err error
for {
select {
case <-ctx.Done():
case task, ok := <-ch:
if !ok {
return
}
if err = task(u); err != nil {
u.UseLogger(ctx).Error(err.Error())
}
}
}
}(_ch)
}
}
func New(configs ...Config) *upp {
config := Config{}
if len(configs) > 0 {
config = configs[0]
}
if config.Debug || _flag.debug {
log.SetLogLevel(log.LogLevelDebug)
}
app := &upp{
logger: upp_logger_pool,
debug: config.Debug,
}
return app

View File

@ -10,6 +10,10 @@ import (
"gorm.io/gorm"
)
func (u *upp) Debug() bool {
return u.debug
}
func (u *upp) UseCtx() context.Context {
return u.ctx
}
@ -27,7 +31,7 @@ func (u *upp) UseDB(ctx ...context.Context) *gorm.DB {
Context: c,
})
if u.debug {
if u.Debug() {
tx = tx.Debug()
}