Compare commits

..

No commits in common. "master" and "dev" have entirely different histories.
master ... dev

40 changed files with 700 additions and 1100 deletions

3
.gitignore vendored
View File

@ -3,5 +3,4 @@ xtest
.idea .idea
*.db *.db
*.sqlite *.sqlite
.DS_Store .DS_Store
etc

41
api.go
View File

@ -1,41 +0,0 @@
package uzone
import (
"net/http"
"github.com/loveuer/uzone/pkg/api"
)
func (u *uzone) API() *api.App { return u.api.engine }
func (u *uzone) GET(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodGet, path, handlers...)
}
func (u *uzone) POST(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodPost, path, handlers...)
}
func (u *uzone) PUT(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodPut, path, handlers...)
}
func (u *uzone) DELETE(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodDelete, path, handlers...)
}
func (u *uzone) PATCH(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodPatch, path, handlers...)
}
func (u *uzone) HEAD(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodHead, path, handlers...)
}
func (u *uzone) OPTIONS(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodOptions, path, handlers...)
}
func (u *uzone) HandleAPI(method, path string, handlers ...api.HandlerFunc) {
u.api.engine.Handle(method, path, handlers...)
}

View File

@ -1,8 +0,0 @@
package uzone
import "context"
type Config struct {
Ctx context.Context
Debug bool
}

View File

@ -1,35 +0,0 @@
package main
import (
"github.com/loveuer/uzone"
"github.com/loveuer/uzone/pkg/api"
"github.com/loveuer/uzone/pkg/interfaces"
)
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 := uzone.New(uzone.Config{Debug: true})
app.With(uzone.InitDB("sqlite://data.db", &Record{}))
app.With(uzone.InitApi(api.New()))
app.With(uzone.InitFn(func(u interfaces.Uzone) {
u.UseLogger().Debug("[init] create init record")
u.UseDB().Create(&Record{Name: "init"})
}))
app.GET("/hello/:name", func(c *api.Ctx) error {
name := c.Param("name")
c.UseLogger().Debug("[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()
}

7
go.mod
View File

@ -1,6 +1,6 @@
module github.com/loveuer/uzone module github.com/loveuer/upp
go 1.20 go 1.23.4
require ( require (
gitea.com/loveuer/gredis v1.0.0 gitea.com/loveuer/gredis v1.0.0
@ -14,9 +14,7 @@ require (
github.com/loveuer/nf v0.3.1 github.com/loveuer/nf v0.3.1
github.com/samber/lo v1.47.0 github.com/samber/lo v1.47.0
github.com/spf13/cast v1.7.1 github.com/spf13/cast v1.7.1
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.25.0 golang.org/x/crypto v0.25.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/mysql v1.5.7 gorm.io/driver/mysql v1.5.7
gorm.io/driver/postgres v1.5.11 gorm.io/driver/postgres v1.5.11
gorm.io/gorm v1.25.12 gorm.io/gorm v1.25.12
@ -40,7 +38,6 @@ require (
github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/sync v0.10.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.25.0 // indirect golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect

21
go.sum
View File

@ -6,6 +6,7 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
@ -15,7 +16,9 @@ github.com/elastic/go-elasticsearch/v7 v7.17.10/go.mod h1:OJ4wdbtDNk5g503kvlHLyE
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
@ -26,7 +29,9 @@ github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 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/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 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
@ -46,7 +51,9 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/loveuer/nf v0.3.1 h1:FTmyAC9LQF06BVGeGwrwaYfbC6MIQMqr+GoZUQQPvXU= github.com/loveuer/nf v0.3.1 h1:FTmyAC9LQF06BVGeGwrwaYfbC6MIQMqr+GoZUQQPvXU=
github.com/loveuer/nf v0.3.1/go.mod h1:aApO+2cSP0ULczkfS4OVw8zfWM3rY8gQrzc5PnVV7lY= github.com/loveuer/nf v0.3.1/go.mod h1:aApO+2cSP0ULczkfS4OVw8zfWM3rY8gQrzc5PnVV7lY=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@ -57,8 +64,11 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
@ -67,6 +77,7 @@ 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 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= 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 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
@ -75,14 +86,11 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -92,9 +100,10 @@ golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

84
log.go
View File

@ -1,84 +0,0 @@
package uzone
import (
"context"
"sync"
"github.com/google/uuid"
"github.com/loveuer/uzone/pkg/api"
"github.com/loveuer/uzone/pkg/log"
"go.uber.org/zap"
)
type uzone_logger struct {
ctx context.Context
caller string
sugar *zap.SugaredLogger
}
func (ul *uzone_logger) WithContext(ctx context.Context) *uzone_logger {
ul.ctx = ctx
return ul
}
// func (ul *uzone_logger) WithCaller(caller string) *uzone_logger {
// ul.caller = caller
// return ul
// }
func (ul *uzone_logger) GC() {
ul.ctx = nil
ul.caller = ""
ul.sugar = nil
log.Logger.Sync()
uzone_logger_pool.Put(ul)
}
var uzone_logger_pool = &sync.Pool{
New: func() any {
s := log.Logger.Sugar()
return &uzone_logger{sugar: s}
},
}
func (ul *uzone_logger) traceId() string {
if ul.ctx == nil {
return uuid.Must(uuid.NewV7()).String()
}
if tid, ok := ul.ctx.Value(api.TraceKey).(string); ok && tid != "" {
return tid
}
return uuid.Must(uuid.NewV7()).String()
}
func (ul *uzone_logger) Debug(msg string, data ...any) {
ul.sugar.With("trace", ul.traceId()).Debugf(msg, data...)
ul.GC()
}
func (ul *uzone_logger) Info(msg string, data ...any) {
ul.sugar.With("trace", ul.traceId()).Infof(msg, data...)
ul.GC()
}
func (ul *uzone_logger) Warn(msg string, data ...any) {
ul.sugar.With("trace", ul.traceId()).Warnf(msg, data...)
ul.GC()
}
func (ul *uzone_logger) Error(msg string, data ...any) {
ul.sugar.With("trace", ul.traceId()).Errorf(msg, data...)
ul.GC()
}
func (ul *uzone_logger) Panic(msg string, data ...any) {
ul.sugar.With("trace", ul.traceId()).Panicf(msg, data...)
ul.GC()
}
func (ul *uzone_logger) Fatal(msg string, data ...any) {
ul.sugar.With("trace", ul.traceId()).Fatalf(msg, data...)
ul.GC()
}

102
module.go
View File

@ -1,102 +0,0 @@
package uzone
import (
"context"
"crypto/tls"
"log"
"github.com/loveuer/uzone/pkg/api"
"github.com/loveuer/uzone/pkg/cache"
"github.com/loveuer/uzone/pkg/db"
"github.com/loveuer/uzone/pkg/es"
"github.com/loveuer/uzone/pkg/interfaces"
)
type module func(u *uzone)
func InitDB(uri string, models ...any) module {
db, err := db.New(uri)
if err != nil {
log.Panic(err.Error())
}
if err = db.AutoMigrate(models...); err != nil {
log.Panic(err.Error())
}
return func(u *uzone) {
u.db = db
}
}
func InitCache(uri string) module {
cache, err := cache.New(uri)
if err != nil {
log.Panic(err.Error())
}
return func(u *uzone) {
u.cache = cache
}
}
func InitES(uri string) module {
client, err := es.New(context.TODO(), uri)
if err != nil {
log.Panic(err.Error())
}
return func(u *uzone) {
u.es = client
}
}
type ApiConfig struct {
Address string
TLSConfig *tls.Config
}
func InitApi(api *api.App, cfgs ...ApiConfig) module {
cfg := ApiConfig{}
if len(cfgs) > 0 {
cfg = cfgs[0]
}
if cfg.Address == "" {
cfg.Address = "localhost:8080"
}
return func(u *uzone) {
api.Uzone = u
u.api = &uzoneApi{
engine: api,
config: cfg,
}
}
}
func InitTaskChan(ch <-chan func(uzone interfaces.Uzone) error) module {
return func(u *uzone) {
if u.taskCh == nil {
u.taskCh = make([]<-chan func(u interfaces.Uzone) error, 0)
}
u.taskCh = append(u.taskCh, ch)
}
}
// sync functions
// 添加 同步执行函数
func InitFn(fns ...func(interfaces.Uzone)) module {
return func(u *uzone) {
u.initFns._sync = append(u.initFns._sync, fns...)
}
}
// async functions
// 添加 异步执行函数
func InitAsyncFn(fns ...func(interfaces.Uzone)) module {
return func(u *uzone) {
u.initFns._async = append(u.initFns._async, fns...)
}
}

View File

@ -12,8 +12,8 @@ import (
"regexp" "regexp"
"sync" "sync"
"github.com/loveuer/uzone/internal/bytesconv" "github.com/loveuer/upp/internal/bytesconv"
"github.com/loveuer/uzone/pkg/interfaces" "github.com/loveuer/upp/pkg/interfaces"
) )
var ( var (
@ -25,7 +25,7 @@ var (
type App struct { type App struct {
RouterGroup RouterGroup
Uzone interfaces.Uzone Upp interfaces.Upp
config *Config config *Config
groups []*RouterGroup groups []*RouterGroup
server *http.Server server *http.Server

View File

@ -14,11 +14,8 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/elastic/go-elasticsearch/v7"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/loveuer/uzone/internal/sse" "github.com/loveuer/upp/internal/sse"
"github.com/loveuer/uzone/pkg/cache"
"github.com/loveuer/uzone/pkg/interfaces"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -42,20 +39,8 @@ type Ctx struct {
fullPath string fullPath string
} }
func (c *Ctx) UseLogger() interfaces.Logger { func (c *Ctx) UseDB() *gorm.DB {
return c.app.Uzone.UseLogger(c.Context()) return c.app.Upp.UseDB()
}
func (c *Ctx) UseDB(ctx ...context.Context) *gorm.DB {
return c.app.Uzone.UseDB(ctx...)
}
func (c *Ctx) UseCache() cache.Cache {
return c.app.Uzone.UseCache()
}
func (c *Ctx) UseES() elasticsearch.Client {
return *c.app.Uzone.UseES()
} }
func (c *Ctx) reset(w http.ResponseWriter, r *http.Request) { func (c *Ctx) reset(w http.ResponseWriter, r *http.Request) {

View File

@ -10,7 +10,7 @@ import (
"github.com/loveuer/nf" "github.com/loveuer/nf"
"github.com/loveuer/nf/nft/log" "github.com/loveuer/nf/nft/log"
"github.com/loveuer/nf/nft/resp" "github.com/loveuer/nf/nft/resp"
"github.com/loveuer/uzone/pkg/tool" "github.com/loveuer/upp/pkg/tool"
) )
func NewRecover(enableStackTrace bool) HandlerFunc { func NewRecover(enableStackTrace bool) HandlerFunc {

View File

@ -7,7 +7,7 @@ import (
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/loveuer/uzone/internal/bytesconv" "github.com/loveuer/upp/internal/bytesconv"
) )
var ( var (

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/loveuer/uzone/internal/schema" "github.com/loveuer/upp/internal/schema"
) )
const ( const (

3
pkg/cache/cache.go vendored
View File

@ -19,7 +19,6 @@ type Cache interface {
// SetEx value 会被序列化, 优先使用 MarshalBinary 方法, 没有则执行 json.Marshal // SetEx value 会被序列化, 优先使用 MarshalBinary 方法, 没有则执行 json.Marshal
SetEx(ctx context.Context, key string, value any, duration time.Duration) error SetEx(ctx context.Context, key string, value any, duration time.Duration) error
Del(ctx context.Context, keys ...string) error Del(ctx context.Context, keys ...string) error
Close() error
} }
type Scanner interface { type Scanner interface {
@ -35,7 +34,7 @@ type decoded_value interface {
} }
const ( const (
Prefix = "zone:" Prefix = "upp:"
) )
var ErrorKeyNotFound = errors.New("key not found") var ErrorKeyNotFound = errors.New("key not found")

View File

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

View File

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

View File

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

2
pkg/cache/new.go vendored
View File

@ -7,7 +7,7 @@ import (
"gitea.com/loveuer/gredis" "gitea.com/loveuer/gredis"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
"github.com/loveuer/uzone/pkg/tool" "github.com/loveuer/upp/pkg/tool"
) )
func New(uri string) (Cache, error) { func New(uri string) (Cache, error) {

View File

@ -6,7 +6,7 @@ import (
"strings" "strings"
"github.com/glebarez/sqlite" "github.com/glebarez/sqlite"
"github.com/loveuer/uzone/pkg/log" "github.com/loveuer/upp/pkg/log"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/driver/postgres" "gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
@ -32,11 +32,11 @@ func New(uri string) (*gorm.DB, error) {
switch ins.Scheme { switch ins.Scheme {
case "sqlite": case "sqlite":
path := strings.TrimPrefix(uri, ins.Scheme+"://") path := strings.TrimPrefix(uri, ins.Scheme+"://")
log.Logger.Sugar().Debugf("db.New: type = %s, path = %s", ins.Scheme, path) log.Debug("db.New: type = %s, path = %s", ins.Scheme, path)
tx, err = gorm.Open(sqlite.Open(path)) tx, err = gorm.Open(sqlite.Open(path))
case "mysql", "mariadb": case "mysql", "mariadb":
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?%s", username, password, ins.Host, ins.Path, ins.RawQuery) dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?%s", username, password, ins.Host, ins.Path, ins.RawQuery)
log.Logger.Sugar().Debugf("db.New: type = %s, dsn = %s", ins.Scheme, dsn) log.Debug("db.New: type = %s, dsn = %s", ins.Scheme, dsn)
tx, err = gorm.Open(mysql.Open(dsn)) tx, err = gorm.Open(mysql.Open(dsn))
case "pg", "postgres", "postgresql": case "pg", "postgres", "postgresql":
opts := make([]string, 0) opts := make([]string, 0)
@ -44,7 +44,7 @@ func New(uri string) (*gorm.DB, error) {
opts = append(opts, fmt.Sprintf("%s=%s", key, val)) opts = append(opts, fmt.Sprintf("%s=%s", key, val))
} }
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s %s", ins.Hostname(), username, password, ins.Path, ins.Port(), strings.Join(opts, " ")) dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s %s", ins.Hostname(), username, password, ins.Path, ins.Port(), strings.Join(opts, " "))
log.Logger.Sugar().Debugf("db.New: type = %s, dsn = %s", ins.Scheme, dsn) log.Debug("db.New: type = %s, dsn = %s", ins.Scheme, dsn)
tx, err = gorm.Open(postgres.Open(dsn)) tx, err = gorm.Open(postgres.Open(dsn))
default: default:
return nil, fmt.Errorf("invalid database type(uri_scheme): %s", ins.Scheme) return nil, fmt.Errorf("invalid database type(uri_scheme): %s", ins.Scheme)

View File

@ -1,77 +0,0 @@
package es
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
"strings"
"time"
elastic "github.com/elastic/go-elasticsearch/v7"
"github.com/elastic/go-elasticsearch/v7/esapi"
"github.com/loveuer/uzone/pkg/tool"
"github.com/samber/lo"
)
// New elasticsearch client v7
// example:
// - uri: http://127.0.0.1:9200
// - uri: https://<username>:<password>@node1:9200,node2:9200,node3:9200
func New(ctx context.Context, uri string) (*elastic.Client, error) {
var (
err error
username string
password string
client *elastic.Client
ins *url.URL
)
if ins, err = url.Parse(uri); err != nil {
return nil, err
}
endpoints := lo.Map(
strings.Split(ins.Host, ","),
func(item string, index int) string {
return fmt.Sprintf("%s://%s", ins.Scheme, item)
},
)
if ins.User != nil {
username = ins.User.Username()
password, _ = ins.User.Password()
}
if client, err = elastic.NewClient(
elastic.Config{
Addresses: endpoints,
Username: username,
Password: password,
CACert: nil,
RetryOnStatus: []int{429},
MaxRetries: 3,
RetryBackoff: nil,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
DialContext: (&net.Dialer{Timeout: 10 * time.Second}).DialContext,
},
},
); err != nil {
return nil, err
}
var res *esapi.Response
if res, err = client.Ping(client.Ping.WithContext(tool.TimeoutCtx(ctx, 5))); err != nil {
return nil, err
}
if res.StatusCode != 200 {
err = fmt.Errorf("ping client response: %s", res.String())
return nil, err
}
return client, nil
}

View File

@ -26,7 +26,7 @@ type ApiEngine interface {
} }
type ApiContext interface { type ApiContext interface {
App() Uzone App() Upp
// parse body, form, json // parse body, form, json
BodyParser(out any) error BodyParser(out any) error
Context() context.Context Context() context.Context

13
pkg/interfaces/upp.go Normal file
View File

@ -0,0 +1,13 @@
package interfaces
import (
"github.com/elastic/go-elasticsearch/v7"
"github.com/loveuer/upp/pkg/cache"
"gorm.io/gorm"
)
type Upp interface {
UseDB() *gorm.DB
UseCache() cache.Cache
UseES() *elasticsearch.Client
}

View File

@ -1,18 +0,0 @@
package interfaces
import (
"context"
"github.com/elastic/go-elasticsearch/v7"
"github.com/loveuer/uzone/pkg/cache"
"gorm.io/gorm"
)
type Uzone interface {
Debug() bool
UseCtx() context.Context
UseDB(ctx ...context.Context) *gorm.DB
UseCache() cache.Cache
UseES() *elasticsearch.Client
UseLogger(ctxs ...context.Context) Logger
}

67
pkg/log/default.go Normal file
View File

@ -0,0 +1,67 @@
package log
import (
"fmt"
"os"
"sync"
)
var (
nilLogger = func(prefix, timestamp, msg string, data ...any) {}
normalLogger = func(prefix, timestamp, msg string, data ...any) {
fmt.Printf(prefix+"| "+timestamp+" | "+msg+"\n", data...)
}
panicLogger = func(prefix, timestamp, msg string, data ...any) {
panic(fmt.Sprintf(prefix+"| "+timestamp+" | "+msg+"\n", data...))
}
fatalLogger = func(prefix, timestamp, msg string, data ...any) {
fmt.Printf(prefix+"| "+timestamp+" | "+msg+"\n", data...)
os.Exit(1)
}
DefaultLogger = &logger{
Mutex: sync.Mutex{},
timeFormat: "2006-01-02T15:04:05",
writer: os.Stdout,
level: LogLevelInfo,
debug: nilLogger,
info: normalLogger,
warn: normalLogger,
error: normalLogger,
panic: panicLogger,
fatal: fatalLogger,
}
)
func SetTimeFormat(format string) {
DefaultLogger.SetTimeFormat(format)
}
func SetLogLevel(level LogLevel) {
DefaultLogger.SetLogLevel(level)
}
func Debug(msg string, data ...any) {
DefaultLogger.Debug(msg, data...)
}
func Info(msg string, data ...any) {
DefaultLogger.Info(msg, data...)
}
func Warn(msg string, data ...any) {
DefaultLogger.Warn(msg, data...)
}
func Error(msg string, data ...any) {
DefaultLogger.Error(msg, data...)
}
func Panic(msg string, data ...any) {
DefaultLogger.Panic(msg, data...)
}
func Fatal(msg string, data ...any) {
DefaultLogger.Fatal(msg, data...)
}

View File

@ -1,36 +1,115 @@
package log package log
import ( import (
"github.com/fatih/color"
"io"
"sync" "sync"
"time"
"go.uber.org/zap"
) )
type LogLevel uint32
const (
LogLevelDebug = iota
LogLevelInfo
LogLevelWarn
LogLevelError
LogLevelPanic
LogLevelFatal
)
type logger struct {
sync.Mutex
timeFormat string
writer io.Writer
level LogLevel
debug func(prefix, timestamp, msg string, data ...any)
info func(prefix, timestamp, msg string, data ...any)
warn func(prefix, timestamp, msg string, data ...any)
error func(prefix, timestamp, msg string, data ...any)
panic func(prefix, timestamp, msg string, data ...any)
fatal func(prefix, timestamp, msg string, data ...any)
}
var ( var (
Logger *zap.Logger red = color.New(color.FgRed)
locker = &sync.Mutex{} hired = color.New(color.FgHiRed)
green = color.New(color.FgGreen)
yellow = color.New(color.FgYellow)
white = color.New(color.FgWhite)
) )
func init() { func (l *logger) SetTimeFormat(format string) {
var err error l.Lock()
config := zap.NewProductionConfig() defer l.Unlock()
Logger, err = config.Build() l.timeFormat = format
if err != nil { }
panic(err)
func (l *logger) SetLogLevel(level LogLevel) {
l.Lock()
defer l.Unlock()
if level > LogLevelDebug {
l.debug = nilLogger
} else {
l.debug = normalLogger
}
if level > LogLevelInfo {
l.info = nilLogger
} else {
l.info = normalLogger
}
if level > LogLevelWarn {
l.warn = nilLogger
} else {
l.warn = normalLogger
}
if level > LogLevelError {
l.error = nilLogger
} else {
l.error = normalLogger
}
if level > LogLevelPanic {
l.panic = nilLogger
} else {
l.panic = panicLogger
}
if level > LogLevelFatal {
l.fatal = nilLogger
} else {
l.fatal = fatalLogger
} }
} }
func Debug() { func (l *logger) Debug(msg string, data ...any) {
var err error l.debug(white.Sprint("Debug "), time.Now().Format(l.timeFormat), msg, data...)
}
config := zap.NewProductionConfig()
config.Level = zap.NewAtomicLevelAt(zap.DebugLevel) func (l *logger) Info(msg string, data ...any) {
l.info(green.Sprint("Info "), time.Now().Format(l.timeFormat), msg, data...)
locker.Lock() }
defer locker.Unlock()
func (l *logger) Warn(msg string, data ...any) {
Logger, err = config.Build() l.warn(yellow.Sprint("Warn "), time.Now().Format(l.timeFormat), msg, data...)
if err != nil { }
panic(err)
} func (l *logger) Error(msg string, data ...any) {
l.error(red.Sprint("Error "), time.Now().Format(l.timeFormat), msg, data...)
}
func (l *logger) Panic(msg string, data ...any) {
l.panic(hired.Sprint("Panic "), time.Now().Format(l.timeFormat), msg, data...)
}
func (l *logger) Fatal(msg string, data ...any) {
l.fatal(hired.Sprint("Fatal "), time.Now().Format(l.timeFormat), msg, data...)
}
type WroteLogger interface {
Info(msg string, data ...any)
} }

21
pkg/log/new.go Normal file
View File

@ -0,0 +1,21 @@
package log
import (
"os"
"sync"
)
func New() *logger {
return &logger{
Mutex: sync.Mutex{},
timeFormat: "2006-01-02T15:04:05",
writer: os.Stdout,
level: LogLevelInfo,
debug: nilLogger,
info: normalLogger,
warn: normalLogger,
error: normalLogger,
panic: panicLogger,
fatal: fatalLogger,
}
}

View File

@ -1,11 +1,11 @@
package tool package tool
import "github.com/loveuer/uzone/pkg/log" import "github.com/loveuer/upp/pkg/log"
func Must(errs ...error) { func Must(errs ...error) {
for _, err := range errs { for _, err := range errs {
if err != nil { if err != nil {
log.Logger.Panic(err.Error()) log.Panic(err.Error())
} }
} }
} }

View File

@ -1,86 +1,85 @@
package tool package tool
import ( import (
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/crypto/pbkdf2" "github.com/loveuer/upp/pkg/log"
) "golang.org/x/crypto/pbkdf2"
)
const (
EncryptHeader string = "pbkdf2:sha256" // 用户密码加密 const (
) EncryptHeader string = "pbkdf2:sha256" // 用户密码加密
)
func NewPassword(password string) string {
return EncryptPassword(password, RandomString(8), int(RandomInt(50000)+100000)) func NewPassword(password string) string {
} return EncryptPassword(password, RandomString(8), int(RandomInt(50000)+100000))
}
// ComparePassword
// if password in and db are same, return nil func ComparePassword(in, db string) bool {
func ComparePassword(in, db string) error { strs := strings.Split(db, "$")
strs := strings.Split(db, "$") if len(strs) != 3 {
if len(strs) != 3 { log.Error("password in db invalid: %s", db)
return fmt.Errorf("password in db invalid: %s", db) return false
} }
encs := strings.Split(strs[0], ":") encs := strings.Split(strs[0], ":")
if len(encs) != 3 { if len(encs) != 3 {
return fmt.Errorf("password in db invalid: %s", db) log.Error("password in db invalid: %s", db)
} return false
}
encIteration, err := strconv.Atoi(encs[2])
if err != nil { encIteration, err := strconv.Atoi(encs[2])
return fmt.Errorf("password in db invalid: %s, convert iter err: %s", db, err) if err != nil {
} log.Error("password in db invalid: %s, convert iter err: %s", db, err)
return false
if EncryptPassword(in, strs[1], encIteration) != db { }
return fmt.Errorf("password input and db not same")
} return EncryptPassword(in, strs[1], encIteration) == db
}
return nil
} func EncryptPassword(password, salt string, iter int) string {
hash := pbkdf2.Key([]byte(password), []byte(salt), iter, 32, sha256.New)
func EncryptPassword(password, salt string, iter int) string { encrypted := hex.EncodeToString(hash)
hash := pbkdf2.Key([]byte(password), []byte(salt), iter, 32, sha256.New) return fmt.Sprintf("%s:%d$%s$%s", EncryptHeader, iter, salt, encrypted)
encrypted := hex.EncodeToString(hash) }
return fmt.Sprintf("%s:%d$%s$%s", EncryptHeader, iter, salt, encrypted)
} func CheckPassword(password string) error {
if len(password) < 8 || len(password) > 32 {
func CheckPassword(password string) error { return errors.New("密码长度不符合")
if len(password) < 8 || len(password) > 32 { }
return errors.New("密码长度不符合")
} var (
err error
var ( match bool
err error patternList = []string{`[0-9]+`, `[a-z]+`, `[A-Z]+`, `[!@#%]+`} //, `[~!@#$%^&*?_-]+`}
match bool matchAccount = 0
patternList = []string{`[0-9]+`, `[a-z]+`, `[A-Z]+`, `[!@#%]+`} //, `[~!@#$%^&*?_-]+`} tips = []string{"缺少数字", "缺少小写字母", "缺少大写字母", "缺少'!@#%'"}
matchAccount = 0 locktips = make([]string, 0)
tips = []string{"缺少数字", "缺少小写字母", "缺少大写字母", "缺少'!@#%'"} )
locktips = make([]string, 0)
) for idx, pattern := range patternList {
match, err = regexp.MatchString(pattern, password)
for idx, pattern := range patternList { if err != nil {
match, err = regexp.MatchString(pattern, password) log.Warn("regex match string err, reg_str: %s, err: %v", pattern, err)
if err != nil { return errors.New("密码强度不够")
return errors.New("密码强度不够") }
}
if match {
if match { matchAccount++
matchAccount++ } else {
} else { locktips = append(locktips, tips[idx])
locktips = append(locktips, tips[idx]) }
} }
}
if matchAccount < 3 {
if matchAccount < 3 { return fmt.Errorf("密码强度不够, 可能 %s", strings.Join(locktips, ", "))
return fmt.Errorf("密码强度不够, 可能 %s", strings.Join(locktips, ", ")) }
}
return nil
return nil }
}

View File

@ -1,124 +1,125 @@
package tool package tool
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"os" "os"
"reflect" "reflect"
"strings" "strings"
"github.com/loveuer/uzone/pkg/log" "github.com/jedib0t/go-pretty/v6/table"
"github.com/loveuer/upp/pkg/log"
"github.com/jedib0t/go-pretty/v6/table" )
)
func TablePrinter(data any, writers ...io.Writer) {
func TablePrinter(data any, writers ...io.Writer) { var w io.Writer = os.Stdout
var w io.Writer = os.Stdout if len(writers) > 0 && writers[0] != nil {
if len(writers) > 0 && writers[0] != nil { w = writers[0]
w = writers[0] }
}
t := table.NewWriter()
t := table.NewWriter() structPrinter(t, "", data)
structPrinter(t, "", data) _, _ = fmt.Fprintln(w, t.Render())
_, _ = fmt.Fprintln(w, t.Render()) }
}
func structPrinter(w table.Writer, prefix string, item any) {
func structPrinter(w table.Writer, prefix string, item any) { Start:
Start: rv := reflect.ValueOf(item)
rv := reflect.ValueOf(item) if rv.IsZero() {
if rv.IsZero() { return
return }
}
for rv.Type().Kind() == reflect.Pointer {
for rv.Type().Kind() == reflect.Pointer { rv = rv.Elem()
rv = rv.Elem() }
}
switch rv.Type().Kind() {
switch rv.Type().Kind() { case reflect.Invalid,
case reflect.Invalid, reflect.Uintptr,
reflect.Uintptr, reflect.Chan,
reflect.Chan, reflect.Func,
reflect.Func, reflect.UnsafePointer:
reflect.UnsafePointer: case reflect.Bool,
case reflect.Bool, reflect.Int,
reflect.Int, reflect.Int8,
reflect.Int8, reflect.Int16,
reflect.Int16, reflect.Int32,
reflect.Int32, reflect.Int64,
reflect.Int64, reflect.Uint,
reflect.Uint, reflect.Uint8,
reflect.Uint8, reflect.Uint16,
reflect.Uint16, reflect.Uint32,
reflect.Uint32, reflect.Uint64,
reflect.Uint64, reflect.Float32,
reflect.Float32, reflect.Float64,
reflect.Float64, reflect.Complex64,
reflect.Complex64, reflect.Complex128,
reflect.Complex128, reflect.Interface:
reflect.Interface: w.AppendRow(table.Row{strings.TrimPrefix(prefix, "."), rv.Interface()})
w.AppendRow(table.Row{strings.TrimPrefix(prefix, "."), rv.Interface()}) case reflect.String:
case reflect.String: val := rv.String()
val := rv.String() if len(val) <= 160 {
if len(val) <= 160 { w.AppendRow(table.Row{strings.TrimPrefix(prefix, "."), val})
w.AppendRow(table.Row{strings.TrimPrefix(prefix, "."), val}) return
return }
}
w.AppendRow(table.Row{strings.TrimPrefix(prefix, "."), val[0:64] + "..." + val[len(val)-64:]})
w.AppendRow(table.Row{strings.TrimPrefix(prefix, "."), val[0:64] + "..." + val[len(val)-64:]}) case reflect.Array, reflect.Slice:
case reflect.Array, reflect.Slice: for i := 0; i < rv.Len(); i++ {
for i := 0; i < rv.Len(); i++ { p := strings.Join([]string{prefix, fmt.Sprintf("[%d]", i)}, ".")
p := strings.Join([]string{prefix, fmt.Sprintf("[%d]", i)}, ".") structPrinter(w, p, rv.Index(i).Interface())
structPrinter(w, p, rv.Index(i).Interface()) }
} case reflect.Map:
case reflect.Map: for _, k := range rv.MapKeys() {
for _, k := range rv.MapKeys() { structPrinter(w, fmt.Sprintf("%s.{%v}", prefix, k), rv.MapIndex(k).Interface())
structPrinter(w, fmt.Sprintf("%s.{%v}", prefix, k), rv.MapIndex(k).Interface()) }
} case reflect.Pointer:
case reflect.Pointer: goto Start
goto Start case reflect.Struct:
case reflect.Struct: for i := 0; i < rv.NumField(); i++ {
for i := 0; i < rv.NumField(); i++ { p := fmt.Sprintf("%s.%s", prefix, rv.Type().Field(i).Name)
p := fmt.Sprintf("%s.%s", prefix, rv.Type().Field(i).Name) field := rv.Field(i)
field := rv.Field(i)
// log.Debug("TablePrinter: prefix: %s, field: %v", p, rv.Field(i))
if !field.CanInterface() {
return if !field.CanInterface() {
} return
}
structPrinter(w, p, field.Interface())
} structPrinter(w, p, field.Interface())
} }
} }
}
func TableMapPrinter(data []byte) {
m := make(map[string]any) func TableMapPrinter(data []byte) {
if err := json.Unmarshal(data, &m); err != nil { m := make(map[string]any)
log.Logger.Warn(err.Error()) if err := json.Unmarshal(data, &m); err != nil {
return log.Warn(err.Error())
} return
}
t := table.NewWriter()
addRow(t, "", m) t := table.NewWriter()
fmt.Println(t.Render()) addRow(t, "", m)
} fmt.Println(t.Render())
}
func addRow(w table.Writer, prefix string, m any) {
rv := reflect.ValueOf(m) func addRow(w table.Writer, prefix string, m any) {
switch rv.Type().Kind() { rv := reflect.ValueOf(m)
case reflect.Map: switch rv.Type().Kind() {
for _, k := range rv.MapKeys() { case reflect.Map:
key := k.String() for _, k := range rv.MapKeys() {
if prefix != "" { key := k.String()
key = strings.Join([]string{prefix, k.String()}, ".") if prefix != "" {
} key = strings.Join([]string{prefix, k.String()}, ".")
addRow(w, key, rv.MapIndex(k).Interface()) }
} addRow(w, key, rv.MapIndex(k).Interface())
case reflect.Slice, reflect.Array: }
for i := 0; i < rv.Len(); i++ { case reflect.Slice, reflect.Array:
addRow(w, fmt.Sprintf("%s[%d]", prefix, i), rv.Index(i).Interface()) for i := 0; i < rv.Len(); i++ {
} addRow(w, fmt.Sprintf("%s[%d]", prefix, i), rv.Index(i).Interface())
default: }
w.AppendRow(table.Row{prefix, m}) default:
} w.AppendRow(table.Row{prefix, m})
} }
}

19
pkg/tool/tools.go Normal file
View File

@ -0,0 +1,19 @@
package tool
import "cmp"
func Min[T cmp.Ordered](a, b T) T {
if a <= b {
return a
}
return b
}
func Max[T cmp.Ordered](a, b T) T {
if a >= b {
return a
}
return b
}

View File

@ -1,129 +0,0 @@
package uzone
import (
"fmt"
"github.com/spf13/cast"
"gopkg.in/yaml.v3"
"os"
"reflect"
"time"
"github.com/loveuer/uzone/pkg/tool"
)
type _property struct {
Debug bool `yaml:"debug" json:"debug" env:"UZONE.DEBUG"`
Listen struct {
Http string `yaml:"http" json:"http" env:"UZONE.LISTEN.HTTP"`
} `yaml:"listen" json:"listen"`
DB struct {
URI string `json:"uri" env:"UZONE.DB.URI"`
} `yaml:"db" json:"db"`
Cache struct {
URI string `json:"uri" env:"UZONE.CACHE.URI"`
} `yaml:"cache" json:"cache"`
Elasticsearch struct {
URI string `yaml:"uri" json:"uri" env:"UZONE.ELASTICSEARCH.URI"`
} `yaml:"elasticsearch" json:"elasticsearch"`
}
var property = &_property{}
func init() {
time.Local = time.FixedZone("CST", 8*3600)
var (
err error
bs []byte
configFn = func(path string) error {
if bs, err = os.ReadFile(path); err != nil {
uzone_logger_pool.Get().(*uzone_logger).Debug("[%30s] read %s err, err = %s", "init", path, err.Error())
return err
}
if err = yaml.Unmarshal(bs, property); err != nil {
uzone_logger_pool.Get().(*uzone_logger).Debug("[%30s] unmarshal %s err, err = %s", "init", path, err.Error())
return err
}
return nil
}
)
if err = configFn("etc/config.yaml"); err == nil {
goto BindEnv
}
if err = configFn("etc/config.yml"); err == nil {
goto BindEnv
}
_ = configFn("etc/config.json")
BindEnv:
_ = bindEnv(property)
if property.Debug {
tool.TablePrinter(property)
}
}
func bindEnv(data any) error {
rv := reflect.ValueOf(data)
if rv.Type().Kind() != reflect.Pointer {
return fmt.Errorf("can only bind ptr")
}
rv = rv.Elem()
return bindStruct(rv)
}
func bindStruct(rv reflect.Value) error {
if rv.Type().Kind() != reflect.Struct {
return fmt.Errorf("can only bind struct ptr")
}
for i := 0; i < rv.NumField(); i++ {
f := rv.Field(i)
if f.Type().Kind() == reflect.Pointer {
f = f.Elem()
}
if f.Type().Kind() == reflect.Struct {
return bindStruct(f)
}
if !f.CanSet() {
continue
}
tag := rv.Type().Field(i).Tag.Get("env")
if tag == "" || tag == "-" {
continue
}
bv := os.Getenv(tag)
if bv == "" {
continue
}
switch f.Type().Kind() {
case reflect.String:
f.SetString(bv)
case reflect.Bool:
f.SetBool(cast.ToBool(bv))
case reflect.Int64, reflect.Int, reflect.Uint64, reflect.Uint, reflect.Int32, reflect.Uint32, reflect.Int16, reflect.Uint16, reflect.Int8, reflect.Uint8:
f.SetInt(cast.ToInt64(bv))
case reflect.Float64, reflect.Float32:
f.SetFloat(cast.ToFloat64(bv))
default:
uzone_logger_pool.Get().(*uzone_logger).Warn("[%30s] unsupported env binding, type = %s, value = %s", "init", f.Type().Kind().String(), bv)
}
}
return nil
}

View File

@ -1,16 +0,0 @@
package uzone
import (
"os"
"testing"
)
func Test_bindEnv(t *testing.T) {
os.Setenv("UZONE.LISTEN.HTTP", "0.0.0.0:99")
os.Setenv("UZONE.DEBUG", "true")
p := &_property{}
bindEnv(p)
t.Logf("listen.http = %s", p.Listen.Http)
t.Logf("debug = %v", p.Debug)
}

View File

@ -1,58 +1,11 @@
# UZone # UPP - your app
### Usage ### Usage
- 1. usage present ```go
```go app := upp.New()
app := uzone.New()
app.With(db, es, api) app.With(db, es, api)
app.Run(ctx) app.Run(ctx)
``` ```
- 2. simple example
```go
package main
import (
"github.com/loveuer/uzone"
"github.com/loveuer/uzone/pkg/api"
"github.com/loveuer/uzone/pkg/interfaces"
)
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 := uzone.New(uzone.Config{Debug: true})
app.With(uzone.InitDB("sqlite://data.db", &Record{}))
app.With(uzone.InitApi(api.New()))
app.With(uzone.InitFn(func(u interfaces.Uzone) {
u.UseLogger().Debug("[init] create init record")
u.UseDB().Create(&Record{Name: "init"})
}))
app.GET("/hello/:name", func(c *api.Ctx) error {
name := c.Param("name")
c.UseLogger().Debug("[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()
}
```
### Config
> The program will load configuration files in the following order:
- `etc/config.yaml`
- `etc/config.yml`
- `config.json`
> Environment variables will take precedence and override any matching configurations found in the files above.

102
run.go
View File

@ -1,102 +0,0 @@
package uzone
import (
"context"
"fmt"
"os/signal"
"syscall"
"github.com/loveuer/uzone/pkg/interfaces"
"github.com/loveuer/uzone/pkg/tool"
)
func (u *uzone) startAPI(ctx context.Context) {
address := property.Listen.Http
if address == "" {
address = u.api.config.Address
}
fmt.Printf("Uzone | api listen at %s\n", address)
go u.api.engine.Run(address)
go func() {
<-ctx.Done()
u.api.engine.Shutdown(tool.Timeout(2))
}()
}
func (u *uzone) startTask(ctx context.Context) {
fmt.Printf("Uzone | start task channel[%02d]", len(u.taskCh))
for _, _ch := range u.taskCh {
go func(ch <-chan func(interfaces.Uzone) 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 *uzone) Run(ctx context.Context) {
u.RunSignal(ctx)
}
func (u *uzone) runInitFns(ctx context.Context) {
for _, fn := range u.initFns._sync {
fn(u)
}
}
func (u *uzone) startInitFns(ctx context.Context) {
for _, fn := range u.initFns._async {
go fn(u)
}
}
func (u *uzone) 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
print(Banner)
if len(u.initFns._sync) > 0 {
u.runInitFns(ctx)
}
if len(u.initFns._async) > 0 {
u.startInitFns(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()
}

41
upp/api.go Normal file
View File

@ -0,0 +1,41 @@
package upp
import (
"net/http"
"github.com/loveuer/upp/pkg/api"
)
func (u *upp) API() *api.App { return u.api.engine }
func (u *upp) GET(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodGet, path, handlers...)
}
func (u *upp) POST(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodPost, path, handlers...)
}
func (u *upp) PUT(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodPut, path, handlers...)
}
func (u *upp) DELETE(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodDelete, path, handlers...)
}
func (u *upp) PATCH(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodPatch, path, handlers...)
}
func (u *upp) HEAD(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodHead, path, handlers...)
}
func (u *upp) OPTIONS(path string, handlers ...api.HandlerFunc) {
u.HandleAPI(http.MethodOptions, path, handlers...)
}
func (u *upp) HandleAPI(method, path string, handlers ...api.HandlerFunc) {
u.api.engine.Handle(method, path, handlers...)
}

25
upp/log.go Normal file
View File

@ -0,0 +1,25 @@
package upp
func (u *upp) Debug(msg string, data ...any) {
u.logger.Debug(msg, data...)
}
func (u *upp) Info(msg string, data ...any) {
u.logger.Info(msg, data...)
}
func (u *upp) Warn(msg string, data ...any) {
u.logger.Warn(msg, data...)
}
func (u *upp) Error(msg string, data ...any) {
u.logger.Error(msg, data...)
}
func (u *upp) Panic(msg string, data ...any) {
u.logger.Panic(msg, data...)
}
func (u *upp) Fatal(msg string, data ...any) {
u.logger.Fatal(msg, data...)
}

80
upp/module.go Normal file
View File

@ -0,0 +1,80 @@
package upp
import (
"crypto/tls"
"log"
"github.com/elastic/go-elasticsearch/v7"
"github.com/loveuer/upp/pkg/api"
"github.com/loveuer/upp/pkg/cache"
"github.com/loveuer/upp/pkg/db"
"gorm.io/gorm"
)
type module func(u *upp)
func InitDB(uri string, models ...any) module {
db, err := db.New(uri)
if err != nil {
log.Panic(err.Error())
}
if err = db.AutoMigrate(models...); err != nil {
log.Panic(err.Error())
}
return func(u *upp) {
u.db = db
}
}
func (u *upp) UseDB() *gorm.DB {
tx := u.db.Session(&gorm.Session{})
if u.debug {
tx = tx.Debug()
}
return tx
}
func InitCache(uri string) module {
cache, err := cache.New(uri)
if err != nil {
log.Panic(err.Error())
}
return func(u *upp) {
u.cache = cache
}
}
func (u *upp) UseCache() cache.Cache {
return u.cache
}
func (u *upp) UseES() *elasticsearch.Client {
return nil
}
type ApiConfig struct {
Address string
TLSConfig *tls.Config
}
func InitApi(api *api.App, cfgs ...ApiConfig) module {
cfg := ApiConfig{}
if len(cfgs) > 0 {
cfg = cfgs[0]
}
if cfg.Address == "" {
cfg.Address = "localhost:8080"
}
return func(u *upp) {
api.Upp = u
u.api = &uppApi{
engine: api,
config: cfg,
}
}
}

71
upp/upp.go Normal file
View File

@ -0,0 +1,71 @@
package upp
import (
"context"
"os/signal"
"syscall"
"github.com/loveuer/upp/pkg/api"
"github.com/loveuer/upp/pkg/cache"
"github.com/loveuer/upp/pkg/interfaces"
"github.com/loveuer/upp/pkg/log"
"github.com/loveuer/upp/pkg/tool"
"gorm.io/gorm"
)
type uppApi struct {
engine *api.App
config ApiConfig
}
type upp struct {
debug bool
logger interfaces.Logger
db *gorm.DB
cache cache.Cache
api *uppApi
}
func (u *upp) With(modules ...module) {
for _, m := range modules {
m(u)
}
}
func (u *upp) Run(ctx context.Context) {
u.StartAPI(ctx)
<-ctx.Done()
}
func (u *upp) RunSignal() {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
defer cancel()
if u.api != nil {
u.StartAPI(ctx)
}
<-ctx.Done()
u.Warn(" UPP | quit by signal...")
<-tool.Timeout(2).Done()
}
func (u *upp) StartAPI(ctx context.Context) {
u.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 New() *upp {
app := &upp{
logger: log.New(),
}
return app
}

58
use.go
View File

@ -1,58 +0,0 @@
package uzone
import (
"context"
"github.com/elastic/go-elasticsearch/v7"
"github.com/loveuer/uzone/pkg/cache"
"github.com/loveuer/uzone/pkg/interfaces"
"github.com/loveuer/uzone/pkg/tool"
"gorm.io/gorm"
)
func (u *uzone) Debug() bool {
return u.debug
}
func (u *uzone) UseCtx() context.Context {
return u.ctx
}
func (u *uzone) UseDB(ctx ...context.Context) *gorm.DB {
var c context.Context
if len(ctx) > 0 {
c = ctx[0]
} else {
c = tool.Timeout(30)
}
tx := u.db.Session(&gorm.Session{
Context: c,
})
if u.Debug() {
tx = tx.Debug()
}
return tx
}
func (u *uzone) UseCache() cache.Cache {
return u.cache
}
func (u *uzone) UseES() *elasticsearch.Client {
return u.es
}
func (u *uzone) UseLogger(ctxs ...context.Context) interfaces.Logger {
logger := u.logger.Get().(*uzone_logger)
logger.ctx = u.UseCtx()
if len(ctxs) > 0 {
logger.ctx = ctxs[0]
}
return logger
}

View File

@ -1,73 +0,0 @@
package uzone
import (
"context"
"sync"
"github.com/elastic/go-elasticsearch/v7"
"github.com/loveuer/uzone/pkg/api"
"github.com/loveuer/uzone/pkg/cache"
"github.com/loveuer/uzone/pkg/interfaces"
"github.com/loveuer/uzone/pkg/log"
"gorm.io/gorm"
)
const Banner = `
__ ______
/ / / /_ / ___ ___ ___
/ /_/ / / /_/ _ \/ _ \/ -_)
\____/ /___/\___/_//_/\__/
`
type uzoneApi struct {
engine *api.App
config ApiConfig
}
type uzone struct {
debug bool
ctx context.Context
logger *sync.Pool
db *gorm.DB
cache cache.Cache
es *elasticsearch.Client
api *uzoneApi
initFns struct {
_sync []func(interfaces.Uzone)
_async []func(interfaces.Uzone)
}
taskCh []<-chan func(interfaces.Uzone) error
}
func (u *uzone) With(modules ...module) {
for _, m := range modules {
m(u)
}
}
func New(configs ...Config) *uzone {
config := Config{}
if len(configs) > 0 {
config = configs[0]
}
app := &uzone{
logger: uzone_logger_pool,
initFns: struct {
_sync []func(interfaces.Uzone)
_async []func(interfaces.Uzone)
}{
_sync: make([]func(interfaces.Uzone), 0),
_async: make([]func(interfaces.Uzone), 0),
},
}
if config.Debug || property.Debug {
log.Debug()
app.debug = true
}
return app
}