From 60955e23377220a64d7ac06803316dd44c378211 Mon Sep 17 00:00:00 2001 From: Reza Date: Thu, 30 Nov 2023 17:04:02 +0100 Subject: [PATCH] pubsub and memo --- errors/context.go | 18 +- evo.context.go | 16 +- evo.go | 4 +- evo.user.go | 2 +- example/main.go | 18 +- fiber.context.go | 22 +- fiber.evo.go | 2 +- go.mod | 14 +- go.sum | 15 + lib/async/flow.go | 26 +- .../drivers => connectors}/kafka/kafka.go | 54 ++- .../kafka/lib}/kafka/consumer.go | 0 lib/{ => connectors/kafka/lib}/kafka/kafka.go | 2 +- .../kafka/lib}/kafka/producer.go | 0 lib/connectors/kafka/params.go | 23 ++ lib/connectors/nats/nats.go | 337 ++++++++++++++++++ lib/connectors/nats/params.go | 38 ++ .../drivers => connectors}/redis/redis.go | 141 ++++++-- lib/curl/header.go | 4 +- lib/curl/http.go | 16 +- lib/curl/req.go | 46 +-- lib/curl/resp.go | 4 +- lib/date/date.go | 16 +- lib/db/db.go | 80 ++--- lib/db/schema/migration.go | 4 +- lib/db/schema/schema.go | 4 +- lib/db/schema/table/models.go | 2 +- lib/db/types/json.go | 20 +- lib/db/types/map.go | 10 +- lib/db/types/time.go | 2 +- lib/db/types/url.go | 2 +- lib/dot/dot.go | 10 +- lib/dot/dot_test.go | 4 +- lib/frm/error.go | 2 +- lib/frm/frm.go | 8 +- lib/generic/generic.go | 32 +- lib/generic/generic_test.go | 2 +- lib/gpath/file.go | 4 +- lib/gpath/functions.go | 4 +- lib/json/json.go | 26 +- lib/json/json_map.go | 10 +- lib/kafka/kafka_test.go | 67 ---- lib/log/log.go | 52 +-- lib/{cache => memo}/drivers/memory/memory.go | 141 +++++--- lib/{cache => memo}/functions.go | 48 +-- lib/{cache => memo}/interface.go | 36 +- lib/memo/kv/kv.go | 33 ++ lib/outcome/outcome.go | 10 +- lib/pubsub/drivers/nats/nats.go | 225 ------------ lib/pubsub/functions.go | 8 +- lib/pubsub/inteface.go | 22 +- lib/reflections/reflections.go | 38 +- lib/serializer/marshal.go | 25 ++ lib/settings/database/database.go | 6 +- lib/settings/proxy.go | 8 +- lib/settings/settings.go | 22 +- lib/settings/yml/yml.go | 10 +- lib/storage/filesystem/filesystem.go | 6 +- lib/storage/ftp/ftp.go | 6 +- lib/storage/lib/interface.go | 10 +- lib/storage/s3/s3.go | 6 +- lib/storage/sftp/sftp.go | 6 +- lib/stract/stract.go | 2 +- lib/text/parser.go | 2 +- lib/tpl/tpl.go | 2 +- lib/tpl/tpl_test.go | 4 +- lib/try/try.go | 2 +- repr.go | 4 +- 68 files changed, 1093 insertions(+), 752 deletions(-) rename lib/{pubsub/drivers => connectors}/kafka/kafka.go (83%) rename lib/{ => connectors/kafka/lib}/kafka/consumer.go (100%) rename lib/{ => connectors/kafka/lib}/kafka/kafka.go (98%) rename lib/{ => connectors/kafka/lib}/kafka/producer.go (100%) create mode 100644 lib/connectors/kafka/params.go create mode 100644 lib/connectors/nats/nats.go create mode 100644 lib/connectors/nats/params.go rename lib/{cache/drivers => connectors}/redis/redis.go (65%) delete mode 100644 lib/kafka/kafka_test.go rename lib/{cache => memo}/drivers/memory/memory.go (66%) rename lib/{cache => memo}/functions.go (70%) rename lib/{cache => memo}/interface.go (71%) create mode 100644 lib/memo/kv/kv.go delete mode 100644 lib/pubsub/drivers/nats/nats.go create mode 100644 lib/serializer/marshal.go diff --git a/errors/context.go b/errors/context.go index a1af35b4..a3b3a456 100644 --- a/errors/context.go +++ b/errors/context.go @@ -3,26 +3,26 @@ package e import "fmt" type Error struct { - Type string `json:"type"` - Field string `json:"field,omitempty"` - Message string `json:"message"` - Solution string `json:"solution,omitempty"` - Params *[]interface{} `json:"params,omitempty"` + Type string `json:"type"` + Field string `json:"field,omitempty"` + Message string `json:"message"` + Solution string `json:"solution,omitempty"` + Params *[]any `json:"params,omitempty"` } type Errors []Error -func New(t, field, message, solution string, params ...interface{}) *Error { +func New(t, field, message, solution string, params ...any) *Error { return &Error{ t, field, message, solution, ¶ms, } } -func Field(field, message interface{}, params ...interface{}) *Error { +func Field(field, message any, params ...any) *Error { return New("field", fmt.Sprint(field), fmt.Sprint(message), "", params) } -func Context(message interface{}, params ...interface{}) *Error { +func Context(message any, params ...any) *Error { return New("context", "", fmt.Sprint(message), "", params) } @@ -31,7 +31,7 @@ func (e *Error) SetSolution(s string) *Error { return e } -func (e *Error) SetParams(params ...interface{}) *Error { +func (e *Error) SetParams(params ...any) *Error { e.Params = ¶ms return e } diff --git a/evo.context.go b/evo.context.go index 3df094f1..38ee4cf0 100644 --- a/evo.context.go +++ b/evo.context.go @@ -33,9 +33,9 @@ type Request struct { } type Response struct { - Success bool `json:"success"` - Error []string `json:"errors,omitempty"` - Data interface{} `json:"data,omitempty"` + Success bool `json:"success"` + Error []string `json:"errors,omitempty"` + Data any `json:"data,omitempty"` } type URL struct { @@ -72,7 +72,7 @@ func (r *Request) URL() *URL { } return r.url } -func (u *URL) Set(key string, value interface{}) *URL { +func (u *URL) Set(key string, value any) *URL { u.Query.Set(key, fmt.Sprint(value)) return u } @@ -87,7 +87,7 @@ func Upgrade(ctx *fiber.Ctx) *Request { return &r } -func (r *Request) WriteResponse(resp ...interface{}) { +func (r *Request) WriteResponse(resp ...any) { if len(resp) == 0 { return @@ -215,7 +215,7 @@ func (r *Request) _writeResponse(resp Response) { } -func (r *Request) Error(err interface{}, code ...int) bool { +func (r *Request) Error(err any, code ...int) bool { if err == nil { return false } @@ -234,7 +234,7 @@ func (r *Request) Error(err interface{}, code ...int) bool { return true } -func (r *Request) PushError(err interface{}, code ...int) bool { +func (r *Request) PushError(err any, code ...int) bool { if err == nil { return false } @@ -256,7 +256,7 @@ func (r *Request) HasError() bool { return len(r.Response.Error) > 0 } -func (r *Request) Var(key string, value ...interface{}) generic.Value { +func (r *Request) Var(key string, value ...any) generic.Value { return generic.Parse(r.Context.Locals(key, value...)) } diff --git a/evo.go b/evo.go index f8b624ac..ed7bbf4a 100644 --- a/evo.go +++ b/evo.go @@ -1,9 +1,9 @@ package evo import ( - "github.com/getevo/evo/v2/lib/cache" dbo "github.com/getevo/evo/v2/lib/db" "github.com/getevo/evo/v2/lib/generic" + "github.com/getevo/evo/v2/lib/memo" "github.com/getevo/evo/v2/lib/settings" "github.com/getevo/evo/v2/lib/settings/database" "github.com/gofiber/fiber/v2" @@ -35,7 +35,7 @@ func Setup() { settings.SetDefaultDriver(database.Driver) } - cache.Register() + memo.Register() } diff --git a/evo.user.go b/evo.user.go index 203fb43a..4d487504 100644 --- a/evo.user.go +++ b/evo.user.go @@ -12,7 +12,7 @@ func (r *Request) User() *UserInterface { type DefaultUserInterface struct{} -type Attributes map[string]interface{} +type Attributes map[string]any func (d DefaultUserInterface) Attributes() Attributes { return Attributes{} diff --git a/example/main.go b/example/main.go index bcf6cba6..84b9180d 100644 --- a/example/main.go +++ b/example/main.go @@ -3,14 +3,22 @@ package main import ( "fmt" "github.com/getevo/evo/v2" + "github.com/getevo/evo/v2/lib/connectors/nats" + "github.com/getevo/evo/v2/lib/connectors/redis" + "github.com/getevo/evo/v2/lib/memo" + "github.com/getevo/evo/v2/lib/pubsub" "github.com/getevo/evo/v2/lib/settings" ) func main() { evo.Setup() fmt.Println(settings.Get("NATS.SERVER").String()) + + pubsub.AddDriver(redis.Driver) + memo.SetDefaultDriver(nats.Driver) + //var db = evo.GetDBO() - /* var data = map[string]interface{}{} + /* var data = map[string]any{} db.Raw("SELECT * FROM services").Scan(&data) cache.SetDefaultDriver(redis.Driver) @@ -32,12 +40,12 @@ func main() { log.SetLevel(log.DebugLevel)*/ var group = evo.Group("/group").Name("mygroup") - group.Get("/:id", func(request *evo.Request) interface{} { + group.Get("/:id", func(request *evo.Request) any { var r = request.Route("mygroup.gregory", 125) return r }).Name("gregory") - evo.Get("/struct", func(request *evo.Request) interface{} { + evo.Get("/struct", func(request *evo.Request) any { return struct { Text string `json:"text"` Integer int `json:"integer"` @@ -46,11 +54,11 @@ func main() { } }) - evo.Get("/bytes", func(request *evo.Request) interface{} { + evo.Get("/bytes", func(request *evo.Request) any { return []byte{'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'} }) - evo.Get("/outcome", func(request *evo.Request) interface{} { + evo.Get("/outcome", func(request *evo.Request) any { return []error{fmt.Errorf("my error 1"), fmt.Errorf("my error 2")} }) evo.Run() diff --git a/fiber.context.go b/fiber.context.go index a6d22c56..14d6b4b4 100644 --- a/fiber.context.go +++ b/fiber.context.go @@ -71,7 +71,7 @@ func (r *Request) Body() string { // BodyParser binds the request body to a struct. // It supports decoding the following content types based on the Content-Type header: // application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data -func (r *Request) BodyParser(out interface{}) error { +func (r *Request) BodyParser(out any) error { ctype := r.ContentType() if strings.HasPrefix(ctype, MIMEApplicationJSON) { @@ -164,7 +164,7 @@ func (r *Request) Download(file string, name ...string) error { // Format performs content-negotiation on the Accept HTTP header. // It uses Accepts to select a proper format. // If the header is not specified or there is no proper format, text/plain is used. -func (r *Request) Format(body interface{}) error { +func (r *Request) Format(body any) error { var b string accept := r.Context.Accepts("html", "json") @@ -350,7 +350,7 @@ func (r *Request) Is(extension string) (match bool) { // JSON converts any interface or string to JSON using Jsoniter. // This method also sets the content header to application/json. -func (r *Request) JSON(data interface{}) error { +func (r *Request) JSON(data any) error { raw, err := json.Marshal(data) // Check for errors if err != nil { @@ -366,7 +366,7 @@ func (r *Request) JSON(data interface{}) error { // JSONP sends a JSON response with JSONP support. // This method is identical to JSON, except that it opts-in to JSONP callback support. // By default, the callback name is simply callback. -func (r *Request) JSONP(json interface{}, callback ...string) error { +func (r *Request) JSONP(json any, callback ...string) error { return r.Context.JSONP(json, callback...) } @@ -375,9 +375,9 @@ func (r *Request) Links(link ...string) { r.Context.Links(link...) } -// Locals makes it possible to pass interface{} values under string keys scoped to the request +// Locals makes it possible to pass any values under string keys scoped to the request // and therefore available to all following routes that match the request. -func (r *Request) Locals(key string, value ...interface{}) (val interface{}) { +func (r *Request) Locals(key string, value ...any) (val any) { return r.Context.Locals(key, value...) } @@ -447,7 +447,7 @@ func (r *Request) IsSecure() bool { } // Send sets the HTML response body. The Send body can be of any type. -func (r *Request) SendHTML(body interface{}) { +func (r *Request) SendHTML(body any) { r.Set("Content-Type", "text/html") r.Write(body) } @@ -518,7 +518,7 @@ func (r *Request) Vary(fields ...string) { } // Write appends any input to the HTTP body response. -func (r *Request) Write(body interface{}) { +func (r *Request) Write(body any) { var data []byte switch body := body.(type) { case string: @@ -548,7 +548,7 @@ func (r *Request) XHR() bool { } // SetCookie set cookie with given name,value and optional params (wise function) -func (r *Request) SetCookie(key string, val interface{}, params ...interface{}) { +func (r *Request) SetCookie(key string, val any, params ...any) { cookie := new(outcome.Cookie) cookie.Name = key cookie.Path = "/" @@ -585,7 +585,7 @@ func (r *Request) Params() map[string]string { } // Route generate route for named routes -func (r *Request) Route(name string, params ...interface{}) string { +func (r *Request) Route(name string, params ...any) string { var m = fiber.Map{} var jump = false var route = app.GetRoute(name) @@ -605,7 +605,7 @@ func (r *Request) Route(name string, params ...interface{}) string { m[p] = params[idx+1] jump = true } - case map[string]interface{}: + case map[string]any: m = p } } diff --git a/fiber.evo.go b/fiber.evo.go index 3434ee90..81749dfb 100644 --- a/fiber.evo.go +++ b/fiber.evo.go @@ -4,7 +4,7 @@ import ( "github.com/gofiber/fiber/v2" ) -type Handler func(request *Request) interface{} +type Handler func(request *Request) any type Middleware func(request *Request) error type group struct { diff --git a/go.mod b/go.mod index 64caf340..a3efc58d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/iancoleman/strcase v0.2.0 github.com/jlaffaye/ftp v0.1.0 github.com/kelindar/binary v1.0.17 - github.com/nats-io/nats.go v1.29.0 + github.com/nats-io/nats.go v1.31.0 github.com/otiai10/copy v1.9.0 github.com/pkg/sftp v1.13.5 github.com/segmentio/kafka-go v0.4.39 @@ -25,8 +25,8 @@ require ( github.com/tidwall/gjson v1.7.4 github.com/valyala/fasthttp v1.50.0 go.uber.org/multierr v1.9.0 - golang.org/x/crypto v0.12.0 - golang.org/x/text v0.12.0 + golang.org/x/crypto v0.16.0 + golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.4.7 gorm.io/driver/sqlite v1.4.4 @@ -58,7 +58,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.3 // indirect github.com/kr/fs v0.1.0 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -67,10 +67,10 @@ require ( github.com/mattn/go-sqlite3 v1.14.15 // indirect github.com/microsoft/go-mssqldb v0.19.0 // indirect github.com/nats-io/nats-server/v2 v2.9.22 // indirect - github.com/nats-io/nkeys v0.4.4 // indirect + github.com/nats-io/nkeys v0.4.6 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/philhofer/fwd v1.1.2 // indirect - github.com/pierrec/lz4/v4 v4.1.15 // indirect + github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect @@ -82,7 +82,7 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/sys v0.14.0 // indirect + golang.org/x/sys v0.15.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/go.sum b/go.sum index 8037b0db..69de583c 100644 --- a/go.sum +++ b/go.sum @@ -116,6 +116,8 @@ github.com/kelindar/binary v1.0.17/go.mod h1:/twdz8gRLNMffx0U4UOgqm1LywPs6nd9YK2 github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= +github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -151,8 +153,12 @@ github.com/nats-io/nats-server/v2 v2.9.22 h1:rzl88pqWFFrU4G00ed+JnY+uGHSLZ+3jrxD github.com/nats-io/nats-server/v2 v2.9.22/go.mod h1:wEjrEy9vnqIGE4Pqz4/c75v9Pmaq7My2IgFmnykc4C0= github.com/nats-io/nats.go v1.29.0 h1:dSXZ+SZeGyTdHVYeXimeq12FsIpb9dM8CJ2IZFiHcyE= github.com/nats-io/nats.go v1.29.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= +github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= +github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= +github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= +github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -170,6 +176,8 @@ github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go= @@ -239,6 +247,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -281,10 +291,13 @@ golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -292,6 +305,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/lib/async/flow.go b/lib/async/flow.go index 5015622c..82af6bc7 100644 --- a/lib/async/flow.go +++ b/lib/async/flow.go @@ -9,16 +9,16 @@ import ( // Executable represents a singular logic block. // It can be used with several functions. -type Executable func(context.Context) (interface{}, error) +type Executable func(context.Context) (any, error) // ExecutableInSequence represents one of a sequence of logic blocks. -type ExecutableInSequence func(context.Context, interface{}) (interface{}, error) +type ExecutableInSequence func(context.Context, any) (any, error) // IndexedValue stores the output of Executables, // along with the index of the source Executable for ordering. type IndexedValue struct { Index int - Value interface{} + Value any } // IndexedExecutableOutput stores both output and error values from a Excetable. @@ -27,8 +27,8 @@ type IndexedExecutableOutput struct { Err error } -func pluckVals(iVals []IndexedValue) []interface{} { - vals := []interface{}{} +func pluckVals(iVals []IndexedValue) []any { + vals := []any{} for _, val := range iVals { vals = append(vals, val.Value) } @@ -50,7 +50,7 @@ func sortIdxVals(iVals []IndexedValue) []IndexedValue { } // Take returns the first `num` values outputted by the Executables. -func Take(parentCtx context.Context, num int, execs ...Executable) ([]interface{}, error) { +func Take(parentCtx context.Context, num int, execs ...Executable) ([]any, error) { execCount := len(execs) if num > execCount { @@ -143,7 +143,7 @@ func takeUntilEnough(fail chan error, success chan []IndexedValue, num int, outp } // All returns all the outputs from all Executables, order guaranteed. -func All(parentCtx context.Context, execs ...Executable) ([]interface{}, error) { +func All(parentCtx context.Context, execs ...Executable) ([]any, error) { // Create a new sub-context for possible cancelation. ctx, cancel := context.WithCancel(parentCtx) defer cancel() @@ -177,7 +177,7 @@ func All(parentCtx context.Context, execs ...Executable) ([]interface{}, error) /* Last returns the last `num` values outputted by the Executables. */ -func Last(parentCtx context.Context, num int, execs ...Executable) ([]interface{}, error) { +func Last(parentCtx context.Context, num int, execs ...Executable) ([]any, error) { execCount := len(execs) if num > execCount { num = execCount @@ -215,13 +215,13 @@ func (err MaxRetriesExceededError) Error() string { // Retry attempts to get a value from an Executable instead of an Error. // It will keeps re-running the Executable when failed no more than `retries` times. // Also, when the parent Context canceled, it returns the `Err()` of it immediately. -func Retry(parentCtx context.Context, retries int, fn Executable) (interface{}, error) { +func Retry(parentCtx context.Context, retries int, fn Executable) (any, error) { ctx, cancel := context.WithCancel(parentCtx) defer cancel() c := 0 fail := make(chan error, 1) - success := make(chan interface{}, 1) + success := make(chan any, 1) for { go func() { @@ -260,15 +260,15 @@ func Retry(parentCtx context.Context, retries int, fn Executable) (interface{}, // passing previous result to next Executable as input. // When an error occurred, it stop the process then returns the error. // When the parent Context canceled, it returns the `Err()` of it immediately. -func Waterfall(parentCtx context.Context, execs ...ExecutableInSequence) (interface{}, error) { +func Waterfall(parentCtx context.Context, execs ...ExecutableInSequence) (any, error) { ctx, cancel := context.WithCancel(parentCtx) defer cancel() - var lastVal interface{} + var lastVal any execCount := len(execs) i := 0 fail := make(chan error, 1) - success := make(chan interface{}, 1) + success := make(chan any, 1) for { go func() { diff --git a/lib/pubsub/drivers/kafka/kafka.go b/lib/connectors/kafka/kafka.go similarity index 83% rename from lib/pubsub/drivers/kafka/kafka.go rename to lib/connectors/kafka/kafka.go index d747b52c..2e7508ea 100644 --- a/lib/pubsub/drivers/kafka/kafka.go +++ b/lib/connectors/kafka/kafka.go @@ -1,19 +1,25 @@ package kafka import ( - "github.com/getevo/evo/v2/lib/kafka" + "github.com/getevo/evo/v2/lib/connectors/kafka/lib/kafka" "github.com/getevo/evo/v2/lib/pubsub" + "github.com/getevo/evo/v2/lib/serializer" "github.com/getevo/evo/v2/lib/settings" ) -var Driver = driver{} +var Driver = Kafka{} var listeners = map[string][]func(topic string, message []byte, driver pubsub.Interface){} var producers = map[string]*kafka.Producer{} +var _serializer = serializer.JSON -type driver struct{} +type Kafka struct{} -func (d driver) Subscribe(topic string, onMessage func(topic string, message []byte, driver pubsub.Interface), params ...interface{}) { +func (d Kafka) Subscribe(topic string, onMessage func(topic string, message []byte, driver pubsub.Interface), params ...any) { + p := Parse(params) + if !p.IgnorePrefix { + topic = prefix + topic + } if _, ok := listeners[topic]; !ok { listeners[topic] = []func(topic string, message []byte, driver pubsub.Interface){onMessage} var configs []*kafka.ConsumerConfig @@ -36,7 +42,20 @@ func (d driver) Subscribe(topic string, onMessage func(topic string, message []b } } -func (d driver) Publish(topic string, message []byte, params ...interface{}) error { + +func (d Kafka) Publish(topic string, data any, params ...any) error { + b, err := _serializer.Marshal(data) + if err != nil { + return err + } + return d.PublishBytes(topic, b, params...) +} + +func (d Kafka) PublishBytes(topic string, message []byte, params ...any) error { + p := Parse(params) + if !p.IgnorePrefix { + topic = prefix + topic + } if _, ok := producers[topic]; !ok { var config = kafka.ProducerConfig{} switch settings.Get("KAFKA.COMPRESSION").String() { @@ -44,8 +63,6 @@ func (d driver) Publish(topic string, message []byte, params ...interface{}) err config.Compression(kafka.Gzip) case "snappy": config.Compression(kafka.Snappy) - case "lz4": - config.Compression(kafka.Lz4) case "zstd": config.Compression(kafka.Zstd) } @@ -96,7 +113,7 @@ func (d driver) Publish(topic string, message []byte, params ...interface{}) err var prefix = "" var Client *kafka.Client -func (driver) Register() error { +func (Kafka) Register() error { if Client != nil { return nil } @@ -230,16 +247,27 @@ func (driver) Register() error { return nil } -func (driver) Name() string { +func (Kafka) Name() string { return "kafka" } -// SetMarshaller set interface{} to []byte marshalling function -func (driver) SetMarshaller(fn func(input interface{}) ([]byte, error)) { +// SetSerializer set data serialization method +func (Kafka) SetSerializer(v serializer.Interface) { + _serializer = v +} +func (Kafka) SetPrefix(s string) { + prefix = s } -// SetUnMarshaller set []byte to interface{} unmarshalling function -func (driver) SetUnMarshaller(fn func(bytes []byte, out interface{}) error) { +func (Kafka) Serializer() serializer.Interface { + return _serializer +} + +func (Kafka) Marshal(data any) ([]byte, error) { + return _serializer.Marshal(data) +} +func (Kafka) Unmarshal(data []byte, v any) error { + return _serializer.Unmarshal(data, v) } diff --git a/lib/kafka/consumer.go b/lib/connectors/kafka/lib/kafka/consumer.go similarity index 100% rename from lib/kafka/consumer.go rename to lib/connectors/kafka/lib/kafka/consumer.go diff --git a/lib/kafka/kafka.go b/lib/connectors/kafka/lib/kafka/kafka.go similarity index 98% rename from lib/kafka/kafka.go rename to lib/connectors/kafka/lib/kafka/kafka.go index ee0ac68f..39a83a8c 100644 --- a/lib/kafka/kafka.go +++ b/lib/connectors/kafka/lib/kafka/kafka.go @@ -117,7 +117,7 @@ func (client *Client) CreateTopic(topic string, replica, partitions int) error { return nil } -func applyConfig(src interface{}, dst interface{}) { +func applyConfig(src any, dst any) { var srcDesc = structs.New(src) var srcRef = reflect.ValueOf(src).Elem() diff --git a/lib/kafka/producer.go b/lib/connectors/kafka/lib/kafka/producer.go similarity index 100% rename from lib/kafka/producer.go rename to lib/connectors/kafka/lib/kafka/producer.go diff --git a/lib/connectors/kafka/params.go b/lib/connectors/kafka/params.go new file mode 100644 index 00000000..664510ed --- /dev/null +++ b/lib/connectors/kafka/params.go @@ -0,0 +1,23 @@ +package kafka + +type Params struct { + IgnorePrefix bool +} + +const IgnorePrefix = 1 + +func Parse(params []any) Params { + var p = Params{} + for idx, _ := range params { + switch v := params[idx].(type) { + case int: + if v == IgnorePrefix { + p.IgnorePrefix = true + } + case Params: + return v + } + } + + return p +} diff --git a/lib/connectors/nats/nats.go b/lib/connectors/nats/nats.go new file mode 100644 index 00000000..e0a8b3a7 --- /dev/null +++ b/lib/connectors/nats/nats.go @@ -0,0 +1,337 @@ +package nats + +import ( + "fmt" + "github.com/getevo/evo/v2/lib/log" + "github.com/getevo/evo/v2/lib/memo/kv" + "github.com/getevo/evo/v2/lib/pubsub" + "github.com/getevo/evo/v2/lib/serializer" + "github.com/getevo/evo/v2/lib/settings" + "github.com/nats-io/nats.go" + "time" +) + +var Driver = NATS{} + +var listeners = map[string][]func(topic string, message []byte, driver pubsub.Interface){} +var _serializer = serializer.JSON +var prefix = "" +var nc *nats.Conn +var js nats.JetStreamContext + +type NATS struct{} + +func (d NATS) Subscribe(topic string, onMessage func(topic string, message []byte, driver pubsub.Interface), params ...any) { + p := Parse(params) + if !p.IgnorePrefix { + topic = prefix + topic + } + + if _, ok := listeners[topic]; !ok { + listeners[topic] = []func(topic string, message []byte, driver pubsub.Interface){onMessage} + nc.Subscribe(topic, func(msg *nats.Msg) { + for _, callback := range listeners[topic] { + go callback(topic, msg.Data, d) + } + }) + } else { + listeners[topic] = append(listeners[topic], onMessage) + } + +} +func (d NATS) Publish(topic string, data any, params ...any) error { + + b, err := _serializer.Marshal(data) + if err != nil { + return err + } + return d.PublishBytes(topic, b, params...) +} + +func (d NATS) PublishBytes(topic string, b []byte, params ...any) error { + p := Parse(params) + if !p.IgnorePrefix { + topic = prefix + topic + } + return nc.Publish(topic, b) +} + +func (NATS) Register() error { + if nc != nil { + return nil + } + settings.Register( + settings.SettingDomain{ + Title: "NATS", + Domain: "NATS", + Description: "NATS configurations", + ReadOnly: false, + Visible: true, + }, + settings.Setting{ + Domain: "NATS", + Name: "SERVER", + Title: "Servers", + Description: "List of comma separated NATS servers", + Type: "text", + ReadOnly: false, + Visible: true, + }, + + settings.Setting{ + Domain: "NATS", + Name: "MAX_RECONNECT", + Title: "Max Reconnects", + Description: "MaxReconnect attempts", + Type: "number", + Value: "5", + ReadOnly: false, + Visible: true, + }, + + settings.Setting{ + Domain: "NATS", + Name: "RECONNECT_WAIT", + Title: "Reconnect Wait", + Value: "2s", + Description: "Wait time before reconnect", + Type: "text", + ReadOnly: false, + Visible: true, + }, + + settings.Setting{ + Domain: "NATS", + Name: "RANDOMIZE", + Title: "Reconnect Wait", + Description: "Randomization of the server pool", + Type: "bool", + Value: "true", + ReadOnly: false, + Visible: true, + }, + + settings.Setting{ + Domain: "NATS", + Name: "USERNAME", + Title: "Username", + Description: "Username in case of authentication", + Type: "text", + ReadOnly: false, + Visible: true, + }, + + settings.Setting{ + Domain: "NATS", + Name: "PASSWORD", + Title: "Password", + Description: "Password in case of authentication", + Type: "text", + ReadOnly: false, + Visible: true, + }, + + settings.Setting{ + Domain: "NATS", + Name: "TOKEN", + Title: "Token", + Description: "Token in case of authentication", + Type: "text", + ReadOnly: false, + Visible: true, + }, + ) + var err error + var options []nats.Option + if !settings.Get("NATS.RANDOMIZE").Bool() { + options = append(options, nats.DontRandomize()) + } + + if settings.Get("NATS.USERNAME").String() != "" { + options = append(options, nats.UserInfo(settings.Get("NATS.USERNAME").String(), settings.Get("NATS.PASSWORD").String())) + } + + if settings.Get("NATS.TOKEN").String() != "" { + options = append(options, nats.Token(settings.Get("NATS.TOKEN").String())) + } + + if wait, err := settings.Get("NATS.RECONNECT_WAIT").Duration(); wait > 0 && err == nil { + options = append(options, nats.ReconnectWait(wait)) + } + + if reconnects := settings.Get("NATS.MAX_RECONNECT").Int(); reconnects > -1 { + options = append(options, nats.MaxReconnects(reconnects)) + } + + nc, err = nats.Connect(settings.Get("NATS.SERVER").String(), options...) + if err != nil { + return err + } + js, err = nc.JetStream() + + return err +} + +func (NATS) Name() string { + return "nats" +} + +// SetSerializer set data serialization method +func (NATS) SetSerializer(v serializer.Interface) { + _serializer = v +} + +func (NATS) SetPrefix(s string) { + prefix = s +} +func (NATS) Serializer() serializer.Interface { + return _serializer +} + +func (NATS) Marshal(data any) ([]byte, error) { + return _serializer.Marshal(data) +} + +func (NATS) Unmarshal(data []byte, v any) error { + return _serializer.Unmarshal(data, v) +} + +func (d NATS) Set(key string, value any, params ...any) error { + var p = kv.Parse(params) + b, err := _serializer.Marshal(value) + if err != nil { + return err + } + var kv nats.KeyValue + kv, err = d.GetKV(p.Bucket) + if err != nil { + return err + } + _, err = kv.Put(key, b) + return err +} + +func (d NATS) SetRaw(key string, value []byte, params ...any) error { + var p = kv.Parse(params) + kv, err := d.GetKV(p.Bucket) + if err != nil { + return err + } + _, err = kv.Put(key, value) + return err +} + +func (d NATS) Replace(key string, value any, params ...any) bool { + var p = kv.Parse(params) + b, err := _serializer.Marshal(value) + if err != nil { + return false + } + var kv nats.KeyValue + kv, err = d.GetKV(p.Bucket) + if err != nil { + return false + } + _, err = kv.Put(key, b) + return err == nil +} + +func (d NATS) Get(key string, out any, params ...any) bool { + var p = kv.Parse(params) + kv, err := d.GetKV(p.Bucket) + if err != nil { + return false + } + entry, err := kv.Get(key) + if err != nil { + return false + } + return _serializer.Unmarshal(entry.Value(), out) == nil +} + +func (d NATS) GetRaw(key string, params ...any) ([]byte, bool) { + var p = kv.Parse(params) + kv, err := d.GetKV(p.Bucket) + if err != nil { + return []byte{}, false + } + entry, err := kv.Get(key) + if err != nil { + return []byte{}, false + } + return entry.Value(), true +} + +func (d NATS) GetWithExpiration(key string, out any, params ...any) (time.Time, bool) { + log.Error(d.Name() + " does not support expiration") + return time.Time{}, false +} + +func (d NATS) GetRawWithExpiration(key string, params ...any) ([]byte, time.Time, bool) { + log.Error(d.Name() + " does not support expiration") + return []byte{}, time.Time{}, false +} + +func (d NATS) Increment(key string, n any, params ...any) (int64, error) { + var err = fmt.Errorf(d.Name() + " does not support increment") + log.Error(err) + return 0, err +} + +func (d NATS) Decrement(key string, n any, params ...any) (int64, error) { + var err = fmt.Errorf(d.Name() + " does not support decrement") + log.Error(err) + return 0, err +} + +func (d NATS) Delete(key string, params ...any) error { + var p = kv.Parse(params) + kv, err := d.GetKV(p.Bucket) + if err != nil { + return err + } + return kv.Delete(key) +} + +func (d NATS) Expire(key string, t time.Time, params ...any) error { + var err = fmt.Errorf(d.Name() + " does not support expiration") + log.Error(err) + return err +} + +func (d NATS) ItemCount() int64 { + var err = fmt.Errorf(d.Name() + " does not support Item Count") + log.Error(err) + return 0 +} + +func (d NATS) Flush() error { + var err = fmt.Errorf(d.Name() + " does not support Item Count") + log.Error(err) + return err +} + +var list = map[string]nats.KeyValue{} + +func (d NATS) GetKV(bucket string) (nats.KeyValue, error) { + if v, ok := list[bucket]; ok { + return v, nil + } + var kv nats.KeyValue + var err error + if stream, _ := js.StreamInfo(bucket); stream == nil { + kv, err = js.CreateKeyValue(&nats.KeyValueConfig{ + Bucket: bucket, + }) + if err != nil { + return nil, err + } + } else { + kv, err = js.KeyValue(bucket) + if err != nil { + return nil, err + } + } + list[bucket] = kv + return kv, nil +} diff --git a/lib/connectors/nats/params.go b/lib/connectors/nats/params.go new file mode 100644 index 00000000..193205e3 --- /dev/null +++ b/lib/connectors/nats/params.go @@ -0,0 +1,38 @@ +package nats + +type Params struct { + JetStream bool + Bucket string + IgnorePrefix bool +} +type bucket string + +const IgnorePrefix = 1 + +func Bucket(s string) bucket { + return bucket(s) +} + +func Parse(params []any) Params { + var p = Params{ + JetStream: false, + } + for idx, _ := range params { + switch v := params[idx].(type) { + case int: + if v == IgnorePrefix { + p.IgnorePrefix = true + } + case Params: + return v + case string: + p.Bucket = v + p.JetStream = true + case bucket: + p.JetStream = true + p.Bucket = string(v) + } + } + + return p +} diff --git a/lib/cache/drivers/redis/redis.go b/lib/connectors/redis/redis.go similarity index 65% rename from lib/cache/drivers/redis/redis.go rename to lib/connectors/redis/redis.go index b5b4254c..fc16be12 100644 --- a/lib/cache/drivers/redis/redis.go +++ b/lib/connectors/redis/redis.go @@ -3,22 +3,23 @@ package redis import ( "context" "github.com/getevo/evo/v2/lib/log" + "github.com/getevo/evo/v2/lib/memo/kv" "github.com/getevo/evo/v2/lib/pubsub" + "github.com/getevo/evo/v2/lib/serializer" "github.com/getevo/evo/v2/lib/settings" "github.com/go-redis/redis/v8" - "github.com/kelindar/binary" "strings" "time" ) var Driver = driver{} -var marshaller func(input interface{}) ([]byte, error) = binary.Marshal -var unmarshaller func(bytes []byte, out interface{}) error = binary.Unmarshal +var _serializer = serializer.JSON var listeners = map[string][]func(topic string, message []byte, driver pubsub.Interface){} type driver struct{} -func (d driver) Subscribe(topic string, onMessage func(topic string, message []byte, driver pubsub.Interface), params ...interface{}) { +func (d driver) Subscribe(topic string, onMessage func(topic string, message []byte, driver pubsub.Interface), params ...any) { + topic = prefix + topic if _, ok := listeners[topic]; !ok { listeners[topic] = []func(topic string, message []byte, driver pubsub.Interface){} } @@ -37,7 +38,17 @@ func (d driver) Subscribe(topic string, onMessage func(topic string, message []b } }() } -func (d driver) Publish(topic string, message []byte, params ...interface{}) error { + +func (d driver) Publish(topic string, data any, params ...any) error { + b, err := _serializer.Marshal(data) + if err != nil { + return err + } + return d.PublishBytes(topic, b, params...) +} + +func (d driver) PublishBytes(topic string, message []byte, params ...any) error { + topic = prefix + topic return Client.Publish(context.Background(), prefix+topic, message).Err() } @@ -87,37 +98,55 @@ func (driver) Name() string { } // Set add an item to the cache, replacing any existing item. If the duration is 0 -func (driver) Set(key string, value interface{}, duration time.Duration) { - b, err := marshaller(value) +func (driver) Set(key string, value any, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } + b, err := _serializer.Marshal(value) if err != nil { - log.Error("unable to marshal message", "error", err) - return + return err } - Client.Set(context.Background(), prefix+key, b, duration) + return Client.Set(context.Background(), prefix+key, b, p.Duration).Err() } // SetRaw add an item to the cache, replacing any existing item. If the duration is 0 -func (driver) SetRaw(key string, value []byte, duration time.Duration) { - Client.Set(context.Background(), prefix+key, value, duration) +func (driver) SetRaw(key string, value []byte, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } + return Client.Set(context.Background(), prefix+key, value, p.Duration).Err() } // Replace set a new value for the cache key only if it already exists, and the existing // item hasn't expired. Returns an error otherwise. -func (d driver) Replace(key string, value interface{}, duration time.Duration) bool { +func (d driver) Replace(key string, value any, params ...any) bool { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } if _, ok := d.GetRaw(key); !ok { return false } - d.Set(key, value, duration) + err := d.Set(key, value, p.Duration) + if err != nil { + return false + } return true } // Get an item from the cache. Returns a bool indicating whether the key was found. -func (driver) Get(key string, out interface{}) bool { +func (driver) Get(key string, out any, params ...any) bool { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } result, err := Client.Get(context.Background(), prefix+key).Bytes() if err != nil { return false } - err = unmarshaller(result, out) + err = _serializer.Unmarshal(result, out) if err != nil { log.Error("unable to unmarshal message", "error", err) return false @@ -126,7 +155,11 @@ func (driver) Get(key string, out interface{}) bool { } // GetRaw get an item from the cache. Returns cache content in []byte and a bool indicating whether the key was found. -func (driver) GetRaw(key string) ([]byte, bool) { +func (driver) GetRaw(key string, params ...any) ([]byte, bool) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } result, err := Client.Get(context.Background(), prefix+key).Bytes() if err == nil { return result, true @@ -138,7 +171,11 @@ func (driver) GetRaw(key string) ([]byte, bool) { // It returns the item exported to out, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. -func (d driver) GetWithExpiration(key string, out interface{}) (time.Time, bool) { +func (d driver) GetWithExpiration(key string, out any, params ...any) (time.Time, bool) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } var exists = d.Get(key, out) if !exists { return time.Time{}, false @@ -154,7 +191,11 @@ func (d driver) GetWithExpiration(key string, out interface{}) (time.Time, bool) // It returns the content in []byte, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. -func (driver) GetRawWithExpiration(key string) ([]byte, time.Time, bool) { +func (driver) GetRawWithExpiration(key string, params ...any) ([]byte, time.Time, bool) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } result, err := Client.Get(context.Background(), prefix+key).Bytes() if err != nil { return result, time.Time{}, false @@ -170,29 +211,45 @@ func (driver) GetRawWithExpiration(key string) ([]byte, time.Time, bool) { // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to increment it by n. -func (driver) Increment(key string, n interface{}) int64 { +func (driver) Increment(key string, n any, params ...any) (int64, error) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } v := toInt64(n) var result = Client.IncrBy(context.Background(), prefix+key, v) - return result.Val() + return result.Val(), result.Err() } // Decrement an item of type int, int8, int16, int32, int64, uintptr, uint, // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to decrement it by n. -func (driver) Decrement(key string, n interface{}) int64 { +func (driver) Decrement(key string, n any, params ...any) (int64, error) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } v := toInt64(n) var result = Client.IncrBy(context.Background(), prefix+key, v) - return result.Val() + return result.Val(), result.Err() } // Delete an item from the cache. Does nothing if the key is not in the cache. -func (driver) Delete(key string) { - Client.Del(context.Background(), prefix+key) +func (driver) Delete(key string, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } + return Client.Del(context.Background(), prefix+key).Err() } // Expire re-set expiration duration for a key -func (driver) Expire(key string, t time.Time) error { +func (driver) Expire(key string, t time.Time, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } return Client.Expire(context.Background(), prefix+key, time.Now().Sub(t)).Err() } @@ -207,17 +264,7 @@ func (driver) Flush() error { return nil } -// SetMarshaller set interface{} to []byte marshalling function -func (driver) SetMarshaller(fn func(input interface{}) ([]byte, error)) { - marshaller = fn -} - -// SetUnMarshaller set []byte to interface{} unmarshalling function -func (driver) SetUnMarshaller(fn func(bytes []byte, out interface{}) error) { - unmarshaller = fn -} - -func toInt64(n interface{}) int64 { +func toInt64(n any) int64 { switch v := n.(type) { case int: return int64(v) @@ -243,6 +290,22 @@ func toInt64(n interface{}) int64 { return 0 } -func (d driver) SetPrefix(p string) { - prefix = p +// SetSerializer set data serialization method +func (driver) SetSerializer(v serializer.Interface) { + _serializer = v +} + +func (driver) SetPrefix(s string) { + prefix = s +} +func (driver) Serializer() serializer.Interface { + return _serializer +} + +func (driver) Marshal(data any) ([]byte, error) { + return _serializer.Marshal(data) +} + +func (driver) Unmarshal(data []byte, v any) error { + return _serializer.Unmarshal(data, v) } diff --git a/lib/curl/header.go b/lib/curl/header.go index f953dca7..887c43e4 100644 --- a/lib/curl/header.go +++ b/lib/curl/header.go @@ -22,7 +22,7 @@ func (h Header) Clone() Header { } // ParseStruct parse struct into header -func ParseStruct(h Header, v interface{}) Header { +func ParseStruct(h Header, v any) Header { data, err := json.Marshal(v) if err != nil { return h @@ -33,7 +33,7 @@ func ParseStruct(h Header, v interface{}) Header { } // HeaderFromStruct init header from struct -func HeaderFromStruct(v interface{}) Header { +func HeaderFromStruct(v any) Header { var header Header header = ParseStruct(header, v) diff --git a/lib/curl/http.go b/lib/curl/http.go index f5143d8a..fecfe4fe 100644 --- a/lib/curl/http.go +++ b/lib/curl/http.go @@ -1,41 +1,41 @@ package curl // Get execute a http GET request -func Get(url string, v ...interface{}) (*Resp, error) { +func Get(url string, v ...any) (*Resp, error) { return std.Get(url, v...) } // Post execute a http POST request -func Post(url string, v ...interface{}) (*Resp, error) { +func Post(url string, v ...any) (*Resp, error) { return std.Post(url, v...) } // Put execute a http PUT request -func Put(url string, v ...interface{}) (*Resp, error) { +func Put(url string, v ...any) (*Resp, error) { return std.Put(url, v...) } // Head execute a http HEAD request -func Head(url string, v ...interface{}) (*Resp, error) { +func Head(url string, v ...any) (*Resp, error) { return std.Head(url, v...) } // Options execute a http OPTIONS request -func Options(url string, v ...interface{}) (*Resp, error) { +func Options(url string, v ...any) (*Resp, error) { return std.Options(url, v...) } // Delete execute a http DELETE request -func Delete(url string, v ...interface{}) (*Resp, error) { +func Delete(url string, v ...any) (*Resp, error) { return std.Delete(url, v...) } // Patch execute a http PATCH request -func Patch(url string, v ...interface{}) (*Resp, error) { +func Patch(url string, v ...any) (*Resp, error) { return std.Patch(url, v...) } // Do execute request. -func Do(method, url string, v ...interface{}) (*Resp, error) { +func Do(method, url string, v ...any) (*Resp, error) { return std.Do(method, url, v...) } diff --git a/lib/curl/req.go b/lib/curl/req.go index 70de0313..a7a66f82 100644 --- a/lib/curl/req.go +++ b/lib/curl/req.go @@ -9,7 +9,7 @@ import ( "encoding/xml" "errors" "fmt" - "github.com/getevo/evo/v2/lib/cache" + "github.com/getevo/evo/v2/lib/memo" "io" "io/ioutil" "mime/multipart" @@ -42,16 +42,16 @@ const ( type dbg bool // Param represents http request param -type Param map[string]interface{} +type Param map[string]any // Cache set a cache time to keep request in memory type Cache struct { Duration time.Duration - Interface cache.Interface + Interface memo.Interface } // QueryParam is used to force append http request param to the uri -type QueryParam map[string]interface{} +type QueryParam map[string]any // Host is used for set request's Host type Host string @@ -72,7 +72,7 @@ type UploadProgress func(current, total int64) // File upload files matching the name pattern such as // /usr/*/bin/go* (assuming the Separator is '/') -func File(patterns ...string) interface{} { +func File(patterns ...string) any { matches := []string{} for _, pattern := range patterns { m, err := filepath.Glob(pattern) @@ -101,25 +101,25 @@ func File(patterns ...string) interface{} { } type bodyJson struct { - v interface{} + v any } type bodyXml struct { - v interface{} + v any } // BodyJSON make the object be encoded in json format and set it to the request body -func BodyJSON(v interface{}) *bodyJson { +func BodyJSON(v any) *bodyJson { return &bodyJson{v: v} } // BodyXML make the object be encoded in xml format and set it to the request body -func BodyXML(v interface{}) *bodyXml { +func BodyXML(v any) *bodyXml { return &bodyXml{v: v} } // BodyRaw make the object for raw body. accepts string, []byte, io.Reader, io.ReadCloser -func BodyRaw(v interface{}) io.Reader { +func BodyRaw(v any) io.Reader { switch value := v.(type) { case []byte: return bytes.NewReader(value) @@ -170,7 +170,7 @@ func (p *param) Copy(pp param) { } } } -func (p *param) Adds(m map[string]interface{}) { +func (p *param) Adds(m map[string]any) { if len(m) == 0 { return } @@ -186,7 +186,7 @@ func (p *param) Empty() bool { // Do execute a http request with sepecify method and url, // and it can also have some optional params, depending on your needs. -func (r *Req) Do(method, rawurl string, vs ...interface{}) (resp *Resp, err error) { +func (r *Req) Do(method, rawurl string, vs ...any) (resp *Resp, err error) { if rawurl == "" { return nil, errors.New("req: url not specified") } @@ -357,11 +357,11 @@ func (r *Req) Do(method, rawurl string, vs ...interface{}) (resp *Resp, err erro rawurl = rawurl + "&" + paramStr } } - var cacheDriver cache.Interface + var cacheDriver memo.Interface if cacheConfig != nil && (req.Method == "GET" || req.Method == "HEAD") { cacheDriver = cacheConfig.Interface if cacheDriver == nil { - cacheDriver = cache.DefaultDriver() + cacheDriver = memo.DefaultDriver() } var response SerializedResponse if cacheDriver.Get("http#req#"+req.Method+"#"+rawurl, &response) { @@ -451,7 +451,7 @@ func setBodyBytes(req *http.Request, resp *Resp, data []byte) { req.ContentLength = int64(len(data)) } -func setBodyJson(req *http.Request, resp *Resp, opts *jsonEncOpts, v interface{}) (func(), error) { +func setBodyJson(req *http.Request, resp *Resp, opts *jsonEncOpts, v any) (func(), error) { var data []byte switch vv := v.(type) { case string: @@ -486,7 +486,7 @@ func setBodyJson(req *http.Request, resp *Resp, opts *jsonEncOpts, v interface{} return delayedFunc, nil } -func setBodyXml(req *http.Request, resp *Resp, opts *xmlEncOpts, v interface{}) (func(), error) { +func setBodyXml(req *http.Request, resp *Resp, opts *xmlEncOpts, v any) (func(), error) { var data []byte switch vv := v.(type) { case string: @@ -706,36 +706,36 @@ func (m *multipartHelper) writeFile(w *multipart.Writer, fieldname, filename str } // Get execute a http GET request -func (r *Req) Get(url string, v ...interface{}) (*Resp, error) { +func (r *Req) Get(url string, v ...any) (*Resp, error) { return r.Do("GET", url, v...) } // Post execute a http POST request -func (r *Req) Post(url string, v ...interface{}) (*Resp, error) { +func (r *Req) Post(url string, v ...any) (*Resp, error) { return r.Do("POST", url, v...) } // Put execute a http PUT request -func (r *Req) Put(url string, v ...interface{}) (*Resp, error) { +func (r *Req) Put(url string, v ...any) (*Resp, error) { return r.Do("PUT", url, v...) } // Patch execute a http PATCH request -func (r *Req) Patch(url string, v ...interface{}) (*Resp, error) { +func (r *Req) Patch(url string, v ...any) (*Resp, error) { return r.Do("PATCH", url, v...) } // Delete execute a http DELETE request -func (r *Req) Delete(url string, v ...interface{}) (*Resp, error) { +func (r *Req) Delete(url string, v ...any) (*Resp, error) { return r.Do("DELETE", url, v...) } // Head execute a http HEAD request -func (r *Req) Head(url string, v ...interface{}) (*Resp, error) { +func (r *Req) Head(url string, v ...any) (*Resp, error) { return r.Do("HEAD", url, v...) } // Options execute a http OPTIONS request -func (r *Req) Options(url string, v ...interface{}) (*Resp, error) { +func (r *Req) Options(url string, v ...any) (*Resp, error) { return r.Do("OPTIONS", url, v...) } diff --git a/lib/curl/resp.go b/lib/curl/resp.go index dba67122..199f9814 100644 --- a/lib/curl/resp.go +++ b/lib/curl/resp.go @@ -99,7 +99,7 @@ func (r *Resp) ToString() (string, error) { } // ToJSON convert json response body to struct or map -func (r *Resp) ToJSON(v interface{}) error { +func (r *Resp) ToJSON(v any) error { data, err := r.ToBytes() if err != nil { return err @@ -108,7 +108,7 @@ func (r *Resp) ToJSON(v interface{}) error { } // ToXML convert xml response body to struct or map -func (r *Resp) ToXML(v interface{}) error { +func (r *Resp) ToXML(v any) error { data, err := r.ToBytes() if err != nil { return err diff --git a/lib/date/date.go b/lib/date/date.go index f2a9ed24..00c75088 100644 --- a/lib/date/date.go +++ b/lib/date/date.go @@ -192,13 +192,13 @@ func FromUnix(sec int64) *Date { } } -func Parse(in interface{}) (*Date,error) { - if v,ok := in.(int64); ok{ - return FromUnix(v),nil - }else if v,ok := in.(time.Time); ok{ - return FromTime(v),nil - }else if v,ok := in.(string); ok{ +func Parse(in any) (*Date, error) { + if v, ok := in.(int64); ok { + return FromUnix(v), nil + } else if v, ok := in.(time.Time); ok { + return FromTime(v), nil + } else if v, ok := in.(string); ok { return FromString(v) } - return nil,fmt.Errorf("unrecognized date input") -} \ No newline at end of file + return nil, fmt.Errorf("unrecognized date input") +} diff --git a/lib/db/db.go b/lib/db/db.go index 5d07c4c2..05d7da0f 100644 --- a/lib/db/db.go +++ b/lib/db/db.go @@ -33,22 +33,22 @@ func Debug() (tx *gorm.DB) { } // Set store value with key into current db instance's context -func Set(key string, value interface{}) *gorm.DB { +func Set(key string, value any) *gorm.DB { return db.Set(key, value) } // Get get value with key from current db instance's context -func Get(key string) (interface{}, bool) { +func Get(key string) (any, bool) { return db.Get(key) } // InstanceSet store value with key into current db instance's context -func InstanceSet(key string, value interface{}) *gorm.DB { +func InstanceSet(key string, value any) *gorm.DB { return db.InstanceSet(key, value) } // InstanceGet get value with key from current db instance's context -func InstanceGet(key string) (interface{}, bool) { +func InstanceGet(key string) (any, bool) { return db.InstanceGet(key) } @@ -63,7 +63,7 @@ func DB() (*sql.DB, error) { } // SetupJoinTable setup join table schema -func SetupJoinTable(model interface{}, field string, joinTable interface{}) error { +func SetupJoinTable(model any, field string, joinTable any) error { return db.SetupJoinTable(model, field, joinTable) } @@ -85,42 +85,42 @@ func ToSQL(queryFn func(tx *gorm.DB) *gorm.DB) string { } // Create inserts value, returning the inserted data's primary key in value's id -func Create(value interface{}) (tx *gorm.DB) { +func Create(value any) (tx *gorm.DB) { return db.Create(value) } // CreateInBatches inserts value in batches of batchSize -func CreateInBatches(value interface{}, batchSize int) (tx *gorm.DB) { +func CreateInBatches(value any, batchSize int) (tx *gorm.DB) { return db.CreateInBatches(value, batchSize) } // Save updates value in database. If value doesn't contain a matching primary key, value is inserted. -func Save(value interface{}) (tx *gorm.DB) { +func Save(value any) (tx *gorm.DB) { return db.Save(value) } // First finds the first record ordered by primary key, matching given conditions conds -func First(dest interface{}, conds ...interface{}) (tx *gorm.DB) { +func First(dest any, conds ...any) (tx *gorm.DB) { return db.First(dest, conds...) } // Take finds the first record returned by the database in no specified order, matching given conditions conds -func Take(dest interface{}, conds ...interface{}) (tx *gorm.DB) { +func Take(dest any, conds ...any) (tx *gorm.DB) { return db.Take(dest, conds...) } // Last finds the last record ordered by primary key, matching given conditions conds -func Last(dest interface{}, conds ...interface{}) (tx *gorm.DB) { +func Last(dest any, conds ...any) (tx *gorm.DB) { return db.Last(dest, conds...) } // Find finds all records matching given conditions conds -func Find(dest interface{}, conds ...interface{}) (tx *gorm.DB) { +func Find(dest any, conds ...any) (tx *gorm.DB) { return db.Find(dest, conds...) } // FindInBatches finds all records in batches of batchSize -func FindInBatches(dest interface{}, batchSize int, fc func(tx *gorm.DB, batch int) error) *gorm.DB { +func FindInBatches(dest any, batchSize int, fc func(tx *gorm.DB, batch int) error) *gorm.DB { return db.FindInBatches(dest, batchSize, fc) } @@ -136,7 +136,7 @@ func FindInBatches(dest interface{}, batchSize int, fc func(tx *gorm.DB, batch i // // assign email regardless of if record is found // db.Where(User{Name: "jinzhu"}).Assign(User{Email: "fake@fake.org"}).FirstOrInit(&user) // // user -> User{Name: "jinzhu", Age: 20, Email: "fake@fake.org"} -func FirstOrInit(dest interface{}, conds ...interface{}) (tx *gorm.DB) { +func FirstOrInit(dest any, conds ...any) (tx *gorm.DB) { return db.FirstOrInit(dest, conds...) } @@ -154,32 +154,32 @@ func FirstOrInit(dest interface{}, conds ...interface{}) (tx *gorm.DB) { // result := db.Where(User{Name: "jinzhu"}).Assign(User{Email: "fake@fake.org"}).FirstOrCreate(&user) // // user -> User{Name: "jinzhu", Age: 20, Email: "fake@fake.org"} // // result.RowsAffected -> 1 -func FirstOrCreate(dest interface{}, conds ...interface{}) (tx *gorm.DB) { +func FirstOrCreate(dest any, conds ...any) (tx *gorm.DB) { return db.FirstOrCreate(dest, conds...) } // Update updates column with value using callbacks. Reference: https://gorm.io/docs/update.html#Update-Changed-Fields -func Update(column string, value interface{}) (tx *gorm.DB) { +func Update(column string, value any) (tx *gorm.DB) { return db.Update(column, value) } // Updates updates attributes using callbacks. values must be a struct or map. Reference: https://gorm.io/docs/update.html#Update-Changed-Fields -func Updates(values interface{}) (tx *gorm.DB) { +func Updates(values any) (tx *gorm.DB) { return db.Updates(values) } -func UpdateColumn(column string, value interface{}) (tx *gorm.DB) { +func UpdateColumn(column string, value any) (tx *gorm.DB) { return db.UpdateColumn(column, value) } -func UpdateColumns(values interface{}) (tx *gorm.DB) { +func UpdateColumns(values any) (tx *gorm.DB) { return db.UpdateColumns(values) } // Delete deletes value matching given conditions. If value contains primary key it is included in the conditions. If // value includes a deleted_at field, then Delete performs a soft delete instead by setting deleted_at with the current // time if null. -func Delete(value interface{}, conds ...interface{}) (tx *gorm.DB) { +func Delete(value any, conds ...any) (tx *gorm.DB) { return db.Delete(value, conds...) } @@ -196,7 +196,7 @@ func Rows() (*sql.Rows, error) { } // Scan scans selected value to the struct dest -func Scan(dest interface{}) (tx *gorm.DB) { +func Scan(dest any) (tx *gorm.DB) { return db.Scan(dest) } @@ -204,11 +204,11 @@ func Scan(dest interface{}) (tx *gorm.DB) { // // var ages []int64 // db.Model(&users).Pluck("age", &ages) -func Pluck(column string, dest interface{}) (tx *gorm.DB) { +func Pluck(column string, dest any) (tx *gorm.DB) { return db.Pluck(column, dest) } -func ScanRows(rows *sql.Rows, dest interface{}) error { +func ScanRows(rows *sql.Rows, dest any) error { return db.ScanRows(rows, dest) } @@ -249,7 +249,7 @@ func RollbackTo(name string) *gorm.DB { } // Exec executes raw sql -func Exec(sql string, values ...interface{}) (tx *gorm.DB) { +func Exec(sql string, values ...any) (tx *gorm.DB) { return db.Exec(sql, values...) } @@ -259,7 +259,7 @@ func Exec(sql string, values ...interface{}) (tx *gorm.DB) { // db.Model(&User{}).Update("name", "hello") // // if user's primary key is non-blank, will use it as condition, then will only update that user's name to `hello` // db.Model(&user).Update("name", "hello") -func Model(value interface{}) (tx *gorm.DB) { +func Model(value any) (tx *gorm.DB) { return db.Model(value) } @@ -285,7 +285,7 @@ func Clauses(conds ...clause.Expression) (tx *gorm.DB) { // // // Get a user // db.Table("users").take(&result) -func Table(name string, args ...interface{}) (tx *gorm.DB) { +func Table(name string, args ...any) (tx *gorm.DB) { return db.Table(name, args...) } @@ -295,7 +295,7 @@ func Table(name string, args ...interface{}) (tx *gorm.DB) { // db.Distinct("name").Find(&results) // // Select distinct name/age pairs from users // db.Distinct("name", "age").Find(&results) -func Distinct(args ...interface{}) (tx *gorm.DB) { +func Distinct(args ...any) (tx *gorm.DB) { return db.Distinct(args...) } @@ -308,7 +308,7 @@ func Distinct(args ...interface{}) (tx *gorm.DB) { // db.Select("name", "age").Find(&users) // // Select name and age of user using an array // db.Select([]string{"name", "age"}).Find(&users) -func Select(query interface{}, args ...interface{}) (tx *gorm.DB) { +func Select(query any, args ...any) (tx *gorm.DB) { return db.Select(query, args...) } @@ -329,7 +329,7 @@ func Omit(columns ...string) (tx *gorm.DB) { // db.Where("name = ?", "jinzhu").Where("age <> ?", "20").First(&user) // // [docs]: https://gorm.io/docs/query.html#Conditions -func Where(query interface{}, args ...interface{}) (tx *gorm.DB) { +func Where(query any, args ...any) (tx *gorm.DB) { return db.Where(query, args...) } @@ -339,7 +339,7 @@ func Where(query interface{}, args ...interface{}) (tx *gorm.DB) { // // // Find the first user with name not equal to jinzhu // db.Not("name = ?", "jinzhu").First(&user) -func Not(query interface{}, args ...interface{}) (tx *gorm.DB) { +func Not(query any, args ...any) (tx *gorm.DB) { return db.Not(query, args...) } @@ -349,7 +349,7 @@ func Not(query interface{}, args ...interface{}) (tx *gorm.DB) { // // // Find the first user with name equal to jinzhu or john // db.Where("name = ?", "jinzhu").Or("name = ?", "john").First(&user) -func Or(query interface{}, args ...interface{}) (tx *gorm.DB) { +func Or(query any, args ...any) (tx *gorm.DB) { return db.Or(query, args...) } @@ -358,13 +358,13 @@ func Or(query interface{}, args ...interface{}) (tx *gorm.DB) { // db.Joins("Account").Find(&user) // db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user) // db.Joins("Account", DB.Select("id").Where("user_id = users.id AND name = ?", "someName").Model(&Account{})) -func Joins(query string, args ...interface{}) (tx *gorm.DB) { +func Joins(query string, args ...any) (tx *gorm.DB) { return db.Joins(query, args...) } // InnerJoins specify inner joins conditions // db.InnerJoins("Account").Find(&user) -func InnerJoins(query string, args ...interface{}) (tx *gorm.DB) { +func InnerJoins(query string, args ...any) (tx *gorm.DB) { return db.InnerJoins(query, args...) } @@ -380,7 +380,7 @@ func Group(name string) (tx *gorm.DB) { // // // Select the sum age of users with name jinzhu // db.Model(&User{}).Select("name, sum(age) as total").Group("name").Having("name = ?", "jinzhu").Find(&result) -func Having(query interface{}, args ...interface{}) (tx *gorm.DB) { +func Having(query any, args ...any) (tx *gorm.DB) { return db.Having(query, args...) } @@ -388,7 +388,7 @@ func Having(query interface{}, args ...interface{}) (tx *gorm.DB) { // // db.Order("name DESC") // db.Order(clause.OrderByColumn{Column: clause.Column{Name: "name"}, Desc: true}) -func Order(value interface{}) (tx *gorm.DB) { +func Order(value any) (tx *gorm.DB) { return db.Order(value) } @@ -437,7 +437,7 @@ func Scopes(funcs ...func(*gorm.DB) *gorm.DB) (tx *gorm.DB) { // // // get all users, and preload all non-cancelled orders // db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users) -func Preload(query string, args ...interface{}) (tx *gorm.DB) { +func Preload(query string, args ...any) (tx *gorm.DB) { return db.Preload(query, args...) } @@ -455,7 +455,7 @@ func Preload(query string, args ...interface{}) (tx *gorm.DB) { // // [FirstOrCreate]: https://gorm.io/docs/advanced_query.html#FirstOrCreate // [FirstOrInit]: https://gorm.io/docs/advanced_query.html#FirstOrInit -func Attrs(attrs ...interface{}) (tx *gorm.DB) { +func Attrs(attrs ...any) (tx *gorm.DB) { return db.Attrs(attrs...) } @@ -474,7 +474,7 @@ func Attrs(attrs ...interface{}) (tx *gorm.DB) { // // [FirstOrCreate]: https://gorm.io/docs/advanced_query.html#FirstOrCreate // [FirstOrInit]: https://gorm.io/docs/advanced_query.html#FirstOrInit -func Assign(attrs ...interface{}) (tx *gorm.DB) { +func Assign(attrs ...any) (tx *gorm.DB) { return Assign(attrs...) } @@ -482,11 +482,11 @@ func Unscoped() (tx *gorm.DB) { return db.Unscoped() } -func Raw(sql string, values ...interface{}) (tx *gorm.DB) { +func Raw(sql string, values ...any) (tx *gorm.DB) { return db.Raw(sql, values...) } -func UseModel(models ...interface{}) { +func UseModel(models ...any) { schema.UseModel(db, models...) } diff --git a/lib/db/schema/migration.go b/lib/db/schema/migration.go index 27e657c0..d90fceb4 100644 --- a/lib/db/schema/migration.go +++ b/lib/db/schema/migration.go @@ -12,7 +12,7 @@ import ( "strings" ) -var migrations []interface{} +var migrations []any const null = "NULL" @@ -143,7 +143,7 @@ func GetMigrationScript(db *gorm.DB) []string { func DoMigration(db *gorm.DB) error { //check if tidb - var t []map[string]interface{} + var t []map[string]any db.Debug().Raw("SHOW VARIABLES LIKE 'tidb_multi_statement_mode'").Scan(&t) if len(t) > 0 { if tidbMultiStatementMode, ok := t[0]["Value"]; ok { diff --git a/lib/db/schema/schema.go b/lib/db/schema/schema.go index d03fc6cb..a2aaf9d3 100644 --- a/lib/db/schema/schema.go +++ b/lib/db/schema/schema.go @@ -11,7 +11,7 @@ import ( var Models []Model type Model struct { - Sample interface{} `json:"sample"` + Sample any `json:"sample"` Value reflect.Value `json:"-"` Type reflect.Type `json:"-"` Kind reflect.Kind `json:"-"` @@ -47,7 +47,7 @@ func quote(s string) string { return "`" + s + "`" } -func UseModel(db *gorm.DB, values ...interface{}) { +func UseModel(db *gorm.DB, values ...any) { migrations = append(migrations, values...) for index, _ := range values { ref := reflect.ValueOf(values[index]) diff --git a/lib/db/schema/table/models.go b/lib/db/schema/table/models.go index 90c953a9..1a037ac2 100644 --- a/lib/db/schema/table/models.go +++ b/lib/db/schema/table/models.go @@ -49,7 +49,7 @@ type Table struct { Charset string `json:"charset" gorm:"column:TABLE_CHARSET"` Columns Columns `json:"columns" gorm:"-"` Indexes Indexes `json:"indexes" gorm:"-"` - Model interface{} `json:"-" gorm:"-"` + Model any `json:"-" gorm:"-"` Reflect reflect.Value `json:"-" gorm:"-"` } diff --git a/lib/db/types/json.go b/lib/db/types/json.go index b10d9229..ae259fd6 100644 --- a/lib/db/types/json.go +++ b/lib/db/types/json.go @@ -38,7 +38,7 @@ func (j JSONType[T]) Value() (driver.Value, error) { } // Scan scan value into JSONType[T], implements sql.Scanner interface -func (j *JSONType[T]) Scan(value interface{}) error { +func (j *JSONType[T]) Scan(value any) error { var bytes []byte switch v := value.(type) { case []byte: @@ -105,7 +105,7 @@ func (j JSONSlice[T]) Value() (driver.Value, error) { } // Scan scan value into JSONType[T], implements sql.Scanner interface -func (j *JSONSlice[T]) Scan(value interface{}) error { +func (j *JSONSlice[T]) Scan(value any) error { var bytes []byte switch v := value.(type) { case []byte: @@ -161,7 +161,7 @@ func (j JSON) Value() (driver.Value, error) { } // Scan scan value into Jsonb, implements sql.Scanner interface -func (j *JSON) Scan(value interface{}) error { +func (j *JSON) Scan(value any) error { if value == nil { *j = JSON("null") return nil @@ -242,7 +242,7 @@ type JSONQueryExpression struct { keys []string hasKeys bool equals bool - equalsValue interface{} + equalsValue any extract bool path string } @@ -267,7 +267,7 @@ func (jsonQuery *JSONQueryExpression) HasKey(keys ...string) *JSONQueryExpressio } // Keys returns clause.Expression -func (jsonQuery *JSONQueryExpression) Equals(value interface{}, keys ...string) *JSONQueryExpression { +func (jsonQuery *JSONQueryExpression) Equals(value any, keys ...string) *JSONQueryExpression { jsonQuery.keys = keys jsonQuery.equals = true jsonQuery.equalsValue = value @@ -420,13 +420,13 @@ func jsonQueryJoin(keys []string) string { // JSONSetExpression json set expression, implements clause.Expression interface to use as updater type JSONSetExpression struct { column string - path2value map[string]interface{} + path2value map[string]any mutex sync.RWMutex } // JSONSet update fields of json column func JSONSet(column string) *JSONSetExpression { - return &JSONSetExpression{column: column, path2value: make(map[string]interface{})} + return &JSONSetExpression{column: column, path2value: make(map[string]any)} } // Set return clause.Expression. @@ -443,7 +443,7 @@ func JSONSet(column string) *JSONSetExpression { // // // In PostgreSQL, path is `{age}`, `{name}`, `{orgs,orga}`, `{tags, 0}`, `{tags, 1}`. // DB.UpdateColumn("attr", JSONSet("attr").Set("{orgs, orga}", "bar")) -func (jsonSet *JSONSetExpression) Set(path string, value interface{}) *JSONSetExpression { +func (jsonSet *JSONSetExpression) Set(path string, value any) *JSONSetExpression { jsonSet.mutex.Lock() jsonSet.path2value[path] = value jsonSet.mutex.Unlock() @@ -543,10 +543,10 @@ func JSONArrayQuery(column string) *JSONArrayExpression { type JSONArrayExpression struct { column string - equalsValue interface{} + equalsValue any } -func (json *JSONArrayExpression) Contains(value interface{}) *JSONArrayExpression { +func (json *JSONArrayExpression) Contains(value any) *JSONArrayExpression { json.equalsValue = value return json } diff --git a/lib/db/types/map.go b/lib/db/types/map.go index 9031a6ae..7ae4065f 100644 --- a/lib/db/types/map.go +++ b/lib/db/types/map.go @@ -16,7 +16,7 @@ import ( ) // JSONMap defined JSON data type, need to implements driver.Valuer, sql.Scanner interface -type JSONMap map[string]interface{} +type JSONMap map[string]any // Value return json value, implement driver.Valuer interface func (m JSONMap) Value() (driver.Value, error) { @@ -28,7 +28,7 @@ func (m JSONMap) Value() (driver.Value, error) { } // Scan scan value into Jsonb, implements sql.Scanner interface -func (m *JSONMap) Scan(val interface{}) error { +func (m *JSONMap) Scan(val any) error { if val == nil { *m = make(JSONMap) return nil @@ -42,7 +42,7 @@ func (m *JSONMap) Scan(val interface{}) error { default: return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", val)) } - t := map[string]interface{}{} + t := map[string]any{} rd := bytes.NewReader(ba) decoder := json.NewDecoder(rd) decoder.UseNumber() @@ -56,13 +56,13 @@ func (m JSONMap) MarshalJSON() ([]byte, error) { if m == nil { return []byte("null"), nil } - t := (map[string]interface{})(m) + t := (map[string]any)(m) return json.Marshal(t) } // UnmarshalJSON to deserialize []byte func (m *JSONMap) UnmarshalJSON(b []byte) error { - t := map[string]interface{}{} + t := map[string]any{} err := json.Unmarshal(b, &t) *m = JSONMap(t) return err diff --git a/lib/db/types/time.go b/lib/db/types/time.go index fb7e59bf..587c129f 100644 --- a/lib/db/types/time.go +++ b/lib/db/types/time.go @@ -51,7 +51,7 @@ func (Time) GormDBDataType(db *gorm.DB, field *schema.Field) string { } // Scan implements sql.Scanner interface and scans value into Time, -func (t *Time) Scan(src interface{}) error { +func (t *Time) Scan(src any) error { switch v := src.(type) { case []byte: t.setFromString(string(v)) diff --git a/lib/db/types/url.go b/lib/db/types/url.go index 2852861c..c7b375c2 100644 --- a/lib/db/types/url.go +++ b/lib/db/types/url.go @@ -17,7 +17,7 @@ func (u URL) Value() (driver.Value, error) { return u.String(), nil } -func (u *URL) Scan(value interface{}) error { +func (u *URL) Scan(value any) error { var us string switch v := value.(type) { case []byte: diff --git a/lib/dot/dot.go b/lib/dot/dot.go index 19e6d58e..f1d73780 100644 --- a/lib/dot/dot.go +++ b/lib/dot/dot.go @@ -12,7 +12,7 @@ import ( var arrayRegex = regexp.MustCompile(`\[[\"\'\x60]{0,1}(.*?)[\"\'\x60]{0,1}\]`) -func Get(obj interface{}, prop string) (interface{}, error) { +func Get(obj any, prop string) (any, error) { // fmt.Println("getting property") // fmt.Println(args) @@ -50,7 +50,7 @@ func Get(obj interface{}, prop string) (interface{}, error) { } // Loop through this to get properties via dot notation -func getProperty(obj interface{}, prop string) (interface{}, error) { +func getProperty(obj any, prop string) (any, error) { var _type = reflect.TypeOf(obj) if _type.Kind() == reflect.Array || _type.Kind() == reflect.Slice { val := reflect.ValueOf(obj) @@ -81,7 +81,7 @@ func getProperty(obj interface{}, prop string) (interface{}, error) { return reflections.GetField(obj, prop) } -func Set(input interface{}, prop string, value interface{}) error { +func Set(input any, prop string, value any) error { // Get the array access arr := strings.Split(prop, ".") var val = reflect.ValueOf(input) @@ -101,7 +101,7 @@ func Set(input interface{}, prop string, value interface{}) error { if v.IsValid() { obj = v } else { - var m = map[string]interface{}{} + var m = map[string]any{} obj.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(m)) obj = obj.MapIndex(reflect.ValueOf(key)) } @@ -121,7 +121,7 @@ func Set(input interface{}, prop string, value interface{}) error { } -func setProperty(obj interface{}, prop string, val interface{}) error { +func setProperty(obj any, prop string, val any) error { var ref = reflect.ValueOf(obj) if ref.Kind() == reflect.Map { ref.SetMapIndex(reflect.ValueOf(prop), reflect.ValueOf(val)) diff --git a/lib/dot/dot_test.go b/lib/dot/dot_test.go index d892f7c9..1dc55d82 100644 --- a/lib/dot/dot_test.go +++ b/lib/dot/dot_test.go @@ -8,7 +8,7 @@ import ( func TestGet(t *testing.T) { // Test case 1: Accessing a valid property in a map - obj := map[string]interface{}{ + obj := map[string]any{ "foo": "bar", } result, err := dot.Get(obj, "foo") @@ -36,7 +36,7 @@ func TestGet(t *testing.T) { func TestSet(t *testing.T) { // Test case 1: Setting a property in a map - /* obj := map[string]interface{}{ + /* obj := map[string]any{ "foo": "bar", } err := dot.Set(&obj, "foo", "new value") diff --git a/lib/frm/error.go b/lib/frm/error.go index 44c7a9df..6d5b8b38 100644 --- a/lib/frm/error.go +++ b/lib/frm/error.go @@ -59,6 +59,6 @@ func (s *Error) Cause() error { return s.err } -func newError(code uint8, field, path, format string, a ...interface{}) error { +func newError(code uint8, field, path, format string, a ...any) error { return &Error{code: code, field: field, path: path, err: fmt.Errorf(format, a...)} } diff --git a/lib/frm/frm.go b/lib/frm/frm.go index 9ad60918..fba974fd 100644 --- a/lib/frm/frm.go +++ b/lib/frm/frm.go @@ -41,7 +41,7 @@ func (m pathMaps) find(id reflect.Value, key string) *pathMap { } // DecodeCustomTypeFunc for decoding a custom type. -type DecodeCustomTypeFunc func([]string) (interface{}, error) +type DecodeCustomTypeFunc func([]string) (any, error) // decodeCustomTypeField is registered for a specific field. type decodeCustomTypeField struct { @@ -98,7 +98,7 @@ type DecoderOptions struct { } // RegisterCustomType registers a functions for decoding custom types. -func (dec *Decoder) RegisterCustomType(fn DecodeCustomTypeFunc, types []interface{}, fields []interface{}) *Decoder { +func (dec *Decoder) RegisterCustomType(fn DecodeCustomTypeFunc, types []any, fields []any) *Decoder { if dec.customTypes == nil { dec.customTypes = make(map[reflect.Type]*decodeCustomType, 100) } @@ -137,7 +137,7 @@ func NewDecoder(opts *DecoderOptions) *Decoder { // Decode the url.Values and populate the destination dst, which must be a // pointer. -func (dec Decoder) Decode(vs url.Values, dst interface{}) error { +func (dec Decoder) Decode(vs url.Values, dst any) error { main := reflect.ValueOf(dst) if main.Kind() != reflect.Ptr { return newError(ErrCodeNotAPointer, "", "", "dst %q is not a pointer", main.Kind()) @@ -149,7 +149,7 @@ func (dec Decoder) Decode(vs url.Values, dst interface{}) error { // Decode the url.Values and populate the destination dst, which must be a // pointer. -func Decode(vs url.Values, dst interface{}) error { +func Decode(vs url.Values, dst any) error { main := reflect.ValueOf(dst) if main.Kind() != reflect.Ptr { return newError(ErrCodeNotAPointer, "", "", "dst %q is not a pointer", main.Kind()) diff --git a/lib/generic/generic.go b/lib/generic/generic.go index 3a44686e..54263036 100644 --- a/lib/generic/generic.go +++ b/lib/generic/generic.go @@ -49,7 +49,7 @@ const ( // // @param i // @return Value -func Parse(i interface{}) Value { +func Parse(i any) Value { return Value{ Input: i, } @@ -57,13 +57,13 @@ func Parse(i interface{}) Value { // Type lib structure to keep input and its type type Type struct { - input interface{} + input any iType reflect.Type } // Value wraps over interface type Value struct { - Input interface{} + Input any } // IsNil returns if the value is nil @@ -74,7 +74,7 @@ func (v Value) IsNil() bool { return !reflect.ValueOf(v.Input).IsValid() } -func (v Value) direct() interface{} { +func (v Value) direct() any { ref := reflect.ValueOf(v.Input) if !ref.IsValid() { return nil @@ -90,7 +90,7 @@ func (v Value) direct() interface{} { // @receiver v // @param in // @return error -func (v Value) ParseJSON(in interface{}) error { +func (v Value) ParseJSON(in any) error { var value = v.direct() return json.Unmarshal([]byte(fmt.Sprint(value)), in) } @@ -240,7 +240,7 @@ func (v Value) Duration() (time.Duration, error) { // // @param v // @return string -func ToString(v interface{}) string { +func ToString(v any) string { ref := reflect.ValueOf(v) if !ref.IsValid() { return "" @@ -269,7 +269,7 @@ func ToString(v interface{}) string { // // @param input // @return *Type -func TypeOf(input interface{}) *Type { +func TypeOf(input any) *Type { var el = Type{ input: input, iType: reflect.TypeOf(input), @@ -282,7 +282,7 @@ func TypeOf(input interface{}) *Type { // @receiver t // @param input // @return bool -func (t *Type) Is(input interface{}) bool { +func (t *Type) Is(input any) bool { switch v := input.(type) { case reflect.Kind: return v == t.iType.Kind() @@ -362,7 +362,7 @@ func (v *Value) UnmarshalYAML(data []byte) error { return yaml.Unmarshal(data, &v.Input) } -func (v *Value) Scan(value interface{}) error { +func (v *Value) Scan(value any) error { switch cast := value.(type) { case string: v.Input = cast @@ -384,7 +384,7 @@ func (v Value) Is(s string) bool { return typ == s } -func (v Value) SameAs(s interface{}) bool { +func (v Value) SameAs(s any) bool { return reflect.TypeOf(v.Input) == reflect.TypeOf(s) } @@ -414,7 +414,7 @@ func (v Value) PropByTag(tag string) Value { return Parse(nil) } -func (v Value) SetProp(property string, value interface{}) error { +func (v Value) SetProp(property string, value any) error { ref := v.Indirect() if ref.Kind() == reflect.Struct { //var x = ref.FieldByName(property).Interface() @@ -443,7 +443,7 @@ func (v Value) SetProp(property string, value interface{}) error { return fmt.Errorf("value is not struct or map") } -func (v Value) Cast(dst interface{}) error { +func (v Value) Cast(dst any) error { var ref reflect.Value if v, ok := dst.(reflect.Value); ok { ref = v @@ -492,7 +492,7 @@ func (v Value) Cast(dst interface{}) error { x.SetProp(prop.Name, v.Prop(prop.Name).Input) } } - var x interface{} + var x any switch kind { case reflect.Int: if sizeRegex.MatchString(v.String()) { @@ -620,7 +620,7 @@ func (v Value) Indirect() reflect.Value { return indirect(v.Input) } -func indirect(input interface{}) reflect.Value { +func indirect(input any) reflect.Value { var ref = reflect.ValueOf(input) for ref.Kind() == reflect.Ptr { ref = ref.Elem() @@ -632,7 +632,7 @@ func (v Value) IndirectType() reflect.Type { return indirectType(v.Input) } -func indirectType(input interface{}) reflect.Type { +func indirectType(input any) reflect.Type { var ref = reflect.TypeOf(input) for ref.Kind() == reflect.Ptr { ref = ref.Elem() @@ -644,7 +644,7 @@ func (v Value) IsEmpty() bool { return v.Input == nil || reflect.ValueOf(v.Input).IsNil() } -func (v Value) IsAny(s ...interface{}) bool { +func (v Value) IsAny(s ...any) bool { var t = v.IndirectType() var kind = t.Kind() for _, item := range s { diff --git a/lib/generic/generic_test.go b/lib/generic/generic_test.go index 04b53aea..90b36637 100644 --- a/lib/generic/generic_test.go +++ b/lib/generic/generic_test.go @@ -13,7 +13,7 @@ func TestIs(t *testing.T) { Name: "test name", } - var y = map[string]interface{}{ + var y = map[string]any{ "a": "b", } Parse(&x).SetProp("Name", "Reza") diff --git a/lib/gpath/file.go b/lib/gpath/file.go index d37ae52e..fa973eb2 100644 --- a/lib/gpath/file.go +++ b/lib/gpath/file.go @@ -68,7 +68,7 @@ func (f *file) WriteString(v string) error { } // WriteJson take struct and write to file as json -func (f *file) WriteJson(v interface{}, pretty bool) error { +func (f *file) WriteJson(v any, pretty bool) error { if pretty { b, err := json.MarshalIndent(v, "", " ") if err != nil { @@ -134,7 +134,7 @@ func (f *file) ReadAllString() (string, error) { } // UnmarshalJson read file and parse as json -func (f *file) UnmarshalJson(v interface{}) error { +func (f *file) UnmarshalJson(v any) error { b, err := f.ReadAll() if err != nil { return err diff --git a/lib/gpath/functions.go b/lib/gpath/functions.go index 6ee55bf0..124e701d 100644 --- a/lib/gpath/functions.go +++ b/lib/gpath/functions.go @@ -150,7 +150,7 @@ func ReadFile(path string) ([]byte, error) { } // Write bytes to file -func Write(path string, content interface{}) error { +func Write(path string, content any) error { var f *os.File var err error if !IsFileExist(path) { @@ -174,7 +174,7 @@ func Write(path string, content interface{}) error { } // Append bytes to file -func Append(path string, content interface{}) error { +func Append(path string, content any) error { var f *os.File var err error f, err = os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) diff --git a/lib/json/json.go b/lib/json/json.go index e944cad2..b0e765b5 100644 --- a/lib/json/json.go +++ b/lib/json/json.go @@ -19,7 +19,7 @@ import ( "gorm.io/gorm/schema" ) -func Unmarshal(input interface{}, output interface{}) error { +func Unmarshal(input any, output any) error { switch v := input.(type) { case string: return json.Unmarshal([]byte(v), output) @@ -54,20 +54,20 @@ func Unmarshal(input interface{}, output interface{}) error { return fmt.Errorf("unreconized input") } -func Marshal(v interface{}) (JSON, error) { +func Marshal(v any) (JSON, error) { return TryParse(v) } -func (j JSON) Unmarshal(v interface{}) error { +func (j JSON) Unmarshal(v any) error { return json.Unmarshal(j, v) } -func Parse(v interface{}) JSON { +func Parse(v any) JSON { b, _ := json.Marshal(v) return JSON(b) } -func TryParse(v interface{}) (JSON, error) { +func TryParse(v any) (JSON, error) { b, err := json.Marshal(v) return JSON(b), err } @@ -96,7 +96,7 @@ func (j JSON) Value() (driver.Value, error) { } // Scan scan value into Jsonb, implements sql.Scanner interface -func (j *JSON) Scan(value interface{}) error { +func (j *JSON) Scan(value any) error { if value == nil { *j = JSON("null") return nil @@ -177,7 +177,7 @@ type JSONQueryExpression struct { keys []string hasKeys bool equals bool - equalsValue interface{} + equalsValue any extract bool path string } @@ -202,7 +202,7 @@ func (jsonQuery *JSONQueryExpression) HasKey(keys ...string) *JSONQueryExpressio } // Keys returns clause.Expression -func (jsonQuery *JSONQueryExpression) Equals(value interface{}, keys ...string) *JSONQueryExpression { +func (jsonQuery *JSONQueryExpression) Equals(value any, keys ...string) *JSONQueryExpression { jsonQuery.keys = keys jsonQuery.equals = true jsonQuery.equalsValue = value @@ -355,13 +355,13 @@ func jsonQueryJoin(keys []string) string { // JSONSetExpression json set expression, implements clause.Expression interface to use as updater type JSONSetExpression struct { column string - path2value map[string]interface{} + path2value map[string]any mutex sync.RWMutex } // JSONSet update fields of json column func JSONSet(column string) *JSONSetExpression { - return &JSONSetExpression{column: column, path2value: make(map[string]interface{})} + return &JSONSetExpression{column: column, path2value: make(map[string]any)} } // Set return clause.Expression. @@ -378,7 +378,7 @@ func JSONSet(column string) *JSONSetExpression { // // // In PostgreSQL, path is `{age}`, `{name}`, `{orgs,orga}`, `{tags, 0}`, `{tags, 1}`. // DB.UpdateColumn("attr", JSONSet("attr").Set("{orgs, orga}", "bar")) -func (jsonSet *JSONSetExpression) Set(path string, value interface{}) *JSONSetExpression { +func (jsonSet *JSONSetExpression) Set(path string, value any) *JSONSetExpression { jsonSet.mutex.Lock() jsonSet.path2value[path] = value jsonSet.mutex.Unlock() @@ -478,10 +478,10 @@ func JSONArrayQuery(column string) *JSONArrayExpression { type JSONArrayExpression struct { column string - equalsValue interface{} + equalsValue any } -func (json *JSONArrayExpression) Contains(value interface{}) *JSONArrayExpression { +func (json *JSONArrayExpression) Contains(value any) *JSONArrayExpression { json.equalsValue = value return json } diff --git a/lib/json/json_map.go b/lib/json/json_map.go index 679d402f..15f36c02 100644 --- a/lib/json/json_map.go +++ b/lib/json/json_map.go @@ -17,7 +17,7 @@ import ( ) // JSONMap defined JSON data type, need to implements driver.Valuer, sql.Scanner interface -type JSONMap map[string]interface{} +type JSONMap map[string]any func (j JSONMap) ForEach(iterator func(key, value gjson.Result) bool) { var b, _ = j.MarshalJSON() @@ -39,7 +39,7 @@ func (m JSONMap) Value() (driver.Value, error) { } // Scan scan value into Jsonb, implements sql.Scanner interface -func (m *JSONMap) Scan(val interface{}) error { +func (m *JSONMap) Scan(val any) error { if val == nil { *m = make(JSONMap) return nil @@ -53,7 +53,7 @@ func (m *JSONMap) Scan(val interface{}) error { default: return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", val)) } - t := map[string]interface{}{} + t := map[string]any{} rd := bytes.NewReader(ba) decoder := json.NewDecoder(rd) decoder.UseNumber() @@ -67,13 +67,13 @@ func (m JSONMap) MarshalJSON() ([]byte, error) { if m == nil { return []byte("null"), nil } - t := (map[string]interface{})(m) + t := (map[string]any)(m) return json.Marshal(t) } // UnmarshalJSON to deserialize []byte func (m *JSONMap) UnmarshalJSON(b []byte) error { - t := map[string]interface{}{} + t := map[string]any{} err := json.Unmarshal(b, &t) *m = JSONMap(t) return err diff --git a/lib/kafka/kafka_test.go b/lib/kafka/kafka_test.go deleted file mode 100644 index f9380206..00000000 --- a/lib/kafka/kafka_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package kafka_test - -import ( - "fmt" - "github.com/getevo/evo/v2/lib/kafka" - "github.com/getevo/evo/v2/lib/text" - "testing" - "time" -) - -func TestKafka(t *testing.T) { - var config = kafka.NewConsumerConfig() - var brokers = "10.11.10.100:31092,10.11.10.101:31092,10.11.10.102:31092,10.11.10.103:31093" - consumer := kafka.NewConsumer(brokers, "samsa_roundone", config) - consumer.OnMessage(func(message kafka.Message) { - fmt.Println(message.Topic, string(message.Key), string(message.Value)) - }) - fmt.Printf("%+v \n", consumer.Config) - - var cfg = kafka.NewProducerConfig().BatchSize(0).BatchTimeout(100 * time.Millisecond) - producer := kafka.NewProducer(brokers, "samsa_roundone", cfg) - - fmt.Printf("%+v \n", *producer.Writer) - c := 0 - for { - c++ - producer.Write(kafka.Message{ - Value: []byte(fmt.Sprint(time.Now().Unix())), - }) - if c == 10 { - fmt.Printf("%+v \n", producer.Writer.Stats()) - break - } - } - - for { - time.Sleep(10 * time.Second) - } - -} - -func TestClient(t *testing.T) { - var brokers = "10.11.10.100:31092,10.11.10.101:31092,10.11.10.102:31092,10.11.10.103:31093" - var client = kafka.NewClient(brokers) - fmt.Println(client.Topics()) - fmt.Println(client.Partitions()) - client.CreateTopic("RezaTopic", 1, 1) - - var producer = client.NewProducer("RezaTopic") - - var c = 0 - for { - var message = struct { - Name string - Counter int - }{ - Name: "Greg!", - Counter: c, - } - c++ - - producer.Write(kafka.Message{ - Value: []byte(text.ToJSON(message)), - }) - time.Sleep(1 * time.Second) - } -} diff --git a/lib/log/log.go b/lib/log/log.go index ba883e04..19292249 100644 --- a/lib/log/log.go +++ b/lib/log/log.go @@ -72,7 +72,7 @@ func SetStackTrace(lvl int) { stackTraceLevel = lvl } -func msg(message interface{}, level Level, params ...interface{}) { +func msg(message any, level Level, params ...any) { if message == nil { return } @@ -105,7 +105,7 @@ func msg(message interface{}, level Level, params ...interface{}) { } } -func toValue(param interface{}) string { +func toValue(param any) string { var ref = reflect.ValueOf(param) for ref.Kind() == reflect.Ptr { ref = ref.Elem() @@ -135,7 +135,7 @@ func quote(s string) string { } // Fatal is just like func l.Critical logger except that it is followed by exit to program -func Fatal(message interface{}, params ...interface{}) { +func Fatal(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } @@ -143,7 +143,7 @@ func Fatal(message interface{}, params ...interface{}) { } // FatalF is just like func l.CriticalF logger except that it is followed by exit to program -func FatalF(message interface{}, params ...interface{}) { +func FatalF(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } @@ -151,7 +151,7 @@ func FatalF(message interface{}, params ...interface{}) { } // FatalF is just like func l.CriticalF logger except that it is followed by exit to program -func Fatalf(message interface{}, params ...interface{}) { +func Fatalf(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } @@ -159,7 +159,7 @@ func Fatalf(message interface{}, params ...interface{}) { } // Panic is just like func l.Critical except that it is followed by a call to panic -func Panic(message interface{}, params ...interface{}) { +func Panic(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } @@ -167,7 +167,7 @@ func Panic(message interface{}, params ...interface{}) { } // PanicF is just like func l.CriticalF except that it is followed by a call to panic -func PanicF(message interface{}, params ...interface{}) { +func PanicF(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } @@ -175,7 +175,7 @@ func PanicF(message interface{}, params ...interface{}) { } // PanicF is just like func l.CriticalF except that it is followed by a call to panic -func Panicf(message interface{}, params ...interface{}) { +func Panicf(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } @@ -183,21 +183,21 @@ func Panicf(message interface{}, params ...interface{}) { } // Critical logs a message at a Critical Level -func Critical(message interface{}, params ...interface{}) { +func Critical(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } } // CriticalF logs a message at Critical level using the same syntax and options as fmt.Printf -func CriticalF(message interface{}, params ...interface{}) { +func CriticalF(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } } // CriticalF logs a message at Critical level using the same syntax and options as fmt.Printf -func Criticalf(message interface{}, params ...interface{}) { +func Criticalf(message any, params ...any) { if level >= CriticalLevel { msg(message, CriticalLevel, params...) } @@ -205,7 +205,7 @@ func Criticalf(message interface{}, params ...interface{}) { } // Error logs a message at Error level -func Error(message interface{}, params ...interface{}) { +func Error(message any, params ...any) { if level >= ErrorLevel { msg(message, ErrorLevel, params...) } @@ -213,98 +213,98 @@ func Error(message interface{}, params ...interface{}) { } // ErrorF logs a message at Error level using the same syntax and options as fmt.Printf -func ErrorF(message interface{}, params ...interface{}) { +func ErrorF(message any, params ...any) { if level >= ErrorLevel { msg(message, ErrorLevel, params...) } } // ErrorF logs a message at Error level using the same syntax and options as fmt.Printf -func Errorf(message interface{}, params ...interface{}) { +func Errorf(message any, params ...any) { if level >= ErrorLevel { msg(message, ErrorLevel, params...) } } // Warning logs a message at Warning level -func Warning(message interface{}, params ...interface{}) { +func Warning(message any, params ...any) { if level >= WarningLevel { msg(message, WarningLevel, params...) } } // WarningF logs a message at Warning level using the same syntax and options as fmt.Printf -func WarningF(message interface{}, params ...interface{}) { +func WarningF(message any, params ...any) { if level >= WarningLevel { msg(message, WarningLevel, params...) } } // WarningF logs a message at Warning level using the same syntax and options as fmt.Printf -func Warningf(message interface{}, params ...interface{}) { +func Warningf(message any, params ...any) { if level >= WarningLevel { msg(message, WarningLevel, params...) } } // Notice logs a message at Notice level -func Notice(message interface{}, params ...interface{}) { +func Notice(message any, params ...any) { if level >= NoticeLevel { msg(message, NoticeLevel, params...) } } // NoticeF logs a message at Notice level using the same syntax and options as fmt.Printf -func NoticeF(message interface{}, params ...interface{}) { +func NoticeF(message any, params ...any) { if level >= NoticeLevel { msg(message, NoticeLevel, params...) } } // NoticeF logs a message at Notice level using the same syntax and options as fmt.Printf -func Noticef(message interface{}, params ...interface{}) { +func Noticef(message any, params ...any) { if level >= NoticeLevel { msg(message, NoticeLevel, params...) } } // Info logs a message at Info level -func Info(message interface{}, params ...interface{}) { +func Info(message any, params ...any) { if level >= InfoLevel { msg(message, InfoLevel, params...) } } // InfoF logs a message at Info level using the same syntax and options as fmt.Printf -func InfoF(message interface{}, params ...interface{}) { +func InfoF(message any, params ...any) { if level >= InfoLevel { msg(message, InfoLevel, params...) } } // InfoF logs a message at Info level using the same syntax and options as fmt.Printf -func Infof(message interface{}, params ...interface{}) { +func Infof(message any, params ...any) { if level >= InfoLevel { msg(message, InfoLevel, params...) } } // Debug logs a message at Debug level -func Debug(message interface{}, params ...interface{}) { +func Debug(message any, params ...any) { if level >= DebugLevel { msg(message, DebugLevel, params...) } } // DebugF logs a message at Debug level using the same syntax and options as fmt.Printf -func DebugF(message interface{}, params ...interface{}) { +func DebugF(message any, params ...any) { if level >= DebugLevel { msg(message, DebugLevel, params...) } } // DebugF logs a message at Debug level using the same syntax and options as fmt.Printf -func Debugf(message interface{}, params ...interface{}) { +func Debugf(message any, params ...any) { if level >= DebugLevel { msg(message, DebugLevel, params...) } diff --git a/lib/cache/drivers/memory/memory.go b/lib/memo/drivers/memory/memory.go similarity index 66% rename from lib/cache/drivers/memory/memory.go rename to lib/memo/drivers/memory/memory.go index 048cf59a..2d3f96d3 100644 --- a/lib/cache/drivers/memory/memory.go +++ b/lib/memo/drivers/memory/memory.go @@ -3,18 +3,19 @@ package memory import ( "fmt" "github.com/getevo/evo/v2/lib/log" + "github.com/getevo/evo/v2/lib/memo/kv" + "github.com/getevo/evo/v2/lib/serializer" "github.com/getevo/evo/v2/lib/settings" - "github.com/kelindar/binary" "sync" "time" ) var Driver = driver{} -var marshaller func(input interface{}) ([]byte, error) = binary.Marshal -var unmarshaller func(bytes []byte, out interface{}) error = binary.Unmarshal type driver struct{} +var _serializer serializer.Interface + func (d driver) SetPrefix(p string) { return } @@ -73,39 +74,56 @@ func (driver) Name() string { } // Set add an item to the cache, replacing any existing item. If the duration is 0 -func (driver) Set(key string, value interface{}, duration time.Duration) { - b, err := marshaller(value) +func (driver) Set(key string, value any, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } + b, err := _serializer.Marshal(value) if err != nil { - log.Error("unable to marshal message", "error", err) - return + return err } items.Store(key, item{ data: b, - expires: time.Now().Add(duration).Unix(), + expires: time.Now().Add(p.Duration).Unix(), }) + return nil } // SetRaw add an item to the cache, replacing any existing item. If the duration is 0 -func (driver) SetRaw(key string, value []byte, duration time.Duration) { +func (driver) SetRaw(key string, value []byte, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } items.Store(key, item{ data: value, - expires: time.Now().Add(duration).Unix(), + expires: time.Now().Add(p.Duration).Unix(), }) + return nil } // Replace set a new value for the cache key only if it already exists, and the existing // item hasn't expired. Returns an error otherwise. -func (d driver) Replace(key string, value interface{}, duration time.Duration) bool { +func (d driver) Replace(key string, value any, params ...any) bool { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } if _, ok := d.GetRaw(key); !ok { return false } - d.Set(key, value, duration) + d.Set(key, value, p.Duration) return true } // Get an item from the cache. Returns a bool indicating whether the key was found. -func (driver) Get(key string, out interface{}) bool { +func (driver) Get(key string, out any, params ...any) bool { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } v, ok := items.Load(key) if !ok { return false @@ -113,7 +131,7 @@ func (driver) Get(key string, out interface{}) bool { if v.(item).expires < time.Now().Unix() { return false } - var err = unmarshaller(v.(item).data, out) + var err = _serializer.Unmarshal(v.(item).data, out) if err != nil { log.Error("unable to unmarshal message", "error", err) return false @@ -122,7 +140,11 @@ func (driver) Get(key string, out interface{}) bool { } // GetRaw get an item from the cache. Returns cache content in []byte and a bool indicating whether the key was found. -func (driver) GetRaw(key string) ([]byte, bool) { +func (driver) GetRaw(key string, params ...any) ([]byte, bool) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } v, ok := items.Load(key) if !ok { return nil, false @@ -137,7 +159,11 @@ func (driver) GetRaw(key string) ([]byte, bool) { // It returns the item exported to out, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. -func (d driver) GetWithExpiration(key string, out interface{}) (time.Time, bool) { +func (d driver) GetWithExpiration(key string, out any, params ...any) (time.Time, bool) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } v, ok := items.Load(key) if !ok { return time.Time{}, false @@ -145,7 +171,7 @@ func (d driver) GetWithExpiration(key string, out interface{}) (time.Time, bool) if v.(item).expires < time.Now().Unix() { return time.Time{}, false } - var err = unmarshaller(v.(item).data, out) + var err = _serializer.Unmarshal(v.(item).data, out) if err != nil { log.Error("unable to unmarshal message", "error", err) return time.Time{}, false @@ -157,7 +183,11 @@ func (d driver) GetWithExpiration(key string, out interface{}) (time.Time, bool) // It returns the content in []byte, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. -func (driver) GetRawWithExpiration(key string) ([]byte, time.Time, bool) { +func (driver) GetRawWithExpiration(key string, params ...any) ([]byte, time.Time, bool) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } v, ok := items.Load(key) if !ok { return nil, time.Time{}, false @@ -172,7 +202,11 @@ func (driver) GetRawWithExpiration(key string) ([]byte, time.Time, bool) { // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to increment it by n. -func (d driver) Increment(key string, n interface{}) int64 { +func (d driver) Increment(key string, n any, params ...any) (int64, error) { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } var v int64 loaded, ok := items.Load(key) @@ -180,59 +214,69 @@ func (d driver) Increment(key string, n interface{}) int64 { var i item if ok && loaded.(item).expires >= time.Now().Unix() { i = loaded.(item) - var err = unmarshaller(i.data, &v) + var err = _serializer.Unmarshal(i.data, &v) if err != nil { - log.Error("unable to unmarshal message", "error", err) - return 0 + return 0, err } v = v + toInt64(n) - i.data, _ = marshaller(v) + i.data, _ = _serializer.Marshal(v) } else { i = item{ expires: -1, } - i.data, _ = marshaller(1) + i.data, _ = _serializer.Marshal(1) } items.Store(key, i) - return v + return v, nil } // Decrement an item of type int, int8, int16, int32, int64, uintptr, uint, // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to decrement it by n. -func (driver) Decrement(key string, n interface{}) int64 { +func (driver) Decrement(key string, n any, params ...any) (int64, error) { var v int64 - + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } loaded, ok := items.Load(key) var i item if ok && loaded.(item).expires >= time.Now().Unix() { i = loaded.(item) - var err = unmarshaller(i.data, &v) + var err = _serializer.Unmarshal(i.data, &v) if err != nil { - log.Error("unable to unmarshal message", "error", err) - return 0 + return 0, err } v = v - toInt64(n) - i.data, _ = marshaller(v) + i.data, _ = _serializer.Marshal(v) } else { i = item{ expires: -1, } - i.data, _ = marshaller(1) + i.data, _ = _serializer.Marshal(1) } items.Store(key, i) - return v + return v, nil } // Delete an item from the cache. Does nothing if the key is not in the cache. -func (driver) Delete(key string) { +func (driver) Delete(key string, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } items.Delete(key) + return nil } // Expire re-set expiration duration for a key -func (driver) Expire(key string, t time.Time) error { +func (driver) Expire(key string, t time.Time, params ...any) error { + var p = kv.Parse(params) + if p.Bucket != "" { + key = p.Bucket + "." + key + } loaded, ok := items.Load(key) if !ok { return fmt.Errorf("key not found") @@ -255,17 +299,7 @@ func (driver) Flush() error { return nil } -// SetMarshaller set interface{} to []byte marshalling function -func (driver) SetMarshaller(fn func(input interface{}) ([]byte, error)) { - marshaller = fn -} - -// SetUnMarshaller set []byte to interface{} unmarshalling function -func (driver) SetUnMarshaller(fn func(bytes []byte, out interface{}) error) { - unmarshaller = fn -} - -func toInt64(n interface{}) int64 { +func toInt64(n any) int64 { switch v := n.(type) { case int: return int64(v) @@ -290,3 +324,18 @@ func toInt64(n interface{}) int64 { } return 0 } + +func (driver) SetSerializer(v serializer.Interface) { + _serializer = v +} +func (driver) Serializer() serializer.Interface { + return _serializer +} + +func (driver) Marshal(data any) ([]byte, error) { + return _serializer.Marshal(data) +} + +func (driver) Unmarshal(data []byte, v any) error { + return _serializer.Unmarshal(data, v) +} diff --git a/lib/cache/functions.go b/lib/memo/functions.go similarity index 70% rename from lib/cache/functions.go rename to lib/memo/functions.go index c3a6b561..35087375 100644 --- a/lib/cache/functions.go +++ b/lib/memo/functions.go @@ -1,8 +1,8 @@ -package cache +package memo import ( - "github.com/getevo/evo/v2/lib/cache/drivers/memory" "github.com/getevo/evo/v2/lib/log" + "github.com/getevo/evo/v2/lib/memo/drivers/memory" "time" ) @@ -47,71 +47,71 @@ func AddDriver(driver Interface) { } // Set add an item to the cache, replacing any existing item. If the duration is 0 -func Set(key string, value interface{}, duration time.Duration) { - defaultDriver.Set(key, value, duration) +func Set(key string, value any, params ...any) error { + return defaultDriver.Set(key, value, params...) } // SetRaw add an item to the cache, replacing any existing item. If the duration is 0 -func SetRaw(key string, value []byte, duration time.Duration) { - defaultDriver.SetRaw(key, value, duration) +func SetRaw(key string, value []byte, params ...any) error { + return defaultDriver.SetRaw(key, value, params...) } // Replace set a new value for the cache key only if it already exists, and the existing // item hasn't expired. Returns an error otherwise. -func Replace(key string, value interface{}, duration time.Duration) bool { - return defaultDriver.Replace(key, value, duration) +func Replace(key string, value any, params ...any) bool { + return defaultDriver.Replace(key, value, params...) } // Get an item from the cache. Returns a bool indicating whether the key was found. -func Get(key string, out interface{}) bool { - return defaultDriver.Get(key, out) +func Get(key string, out any, params ...any) bool { + return defaultDriver.Get(key, out, params...) } // GetRaw get an item from the cache. Returns cache content in []byte and a bool indicating whether the key was found. -func GetRaw(key string) ([]byte, bool) { - return defaultDriver.GetRaw(key) +func GetRaw(key string, params ...any) ([]byte, bool) { + return defaultDriver.GetRaw(key, params...) } // GetWithExpiration returns an item and its expiration time from the cache. // It returns the item exported to out, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. -func GetWithExpiration(key string, out interface{}) (time.Time, bool) { - return defaultDriver.GetWithExpiration(key, out) +func GetWithExpiration(key string, out any, params ...any) (time.Time, bool) { + return defaultDriver.GetWithExpiration(key, out, params...) } // GetRawWithExpiration returns an item and its expiration time from the cache. // It returns the content in []byte, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. -func GetRawWithExpiration(key string) ([]byte, time.Time, bool) { - return defaultDriver.GetRawWithExpiration(key) +func GetRawWithExpiration(key string, params ...any) ([]byte, time.Time, bool) { + return defaultDriver.GetRawWithExpiration(key, params...) } // Increment an item of type int, int8, int16, int32, int64, uintptr, uint, // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to increment it by n. -func Increment(key string, n interface{}) int64 { - return defaultDriver.Increment(key, n) +func Increment(key string, n any, params ...any) (int64, error) { + return defaultDriver.Increment(key, n, params...) } // Decrement an item of type int, int8, int16, int32, int64, uintptr, uint, // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to decrement it by n. -func Decrement(key string, n interface{}) int64 { - return defaultDriver.Decrement(key, n) +func Decrement(key string, n any, params ...any) (int64, error) { + return defaultDriver.Decrement(key, n, params...) } // Delete an item from the cache. Does nothing if the key is not in the cache. -func Delete(key string) { - defaultDriver.Delete(key) +func Delete(key string, params ...any) error { + return defaultDriver.Delete(key, params...) } // Expire set expiration date for a key -func Expire(key string, t time.Time) error { - return defaultDriver.Expire(key, t) +func Expire(key string, t time.Time, params ...any) error { + return defaultDriver.Expire(key, t, params...) } // ItemCount Returns the number of items in the cache. This may include items that have diff --git a/lib/cache/interface.go b/lib/memo/interface.go similarity index 71% rename from lib/cache/interface.go rename to lib/memo/interface.go index 040526c0..480b4193 100644 --- a/lib/cache/interface.go +++ b/lib/memo/interface.go @@ -1,10 +1,11 @@ -package cache +package memo import ( + "github.com/getevo/evo/v2/lib/serializer" "time" ) -const PERMANENT = -1 +const PERMANENT = time.Duration(-1) type Interface interface { // Name returns driver name @@ -14,50 +15,50 @@ type Interface interface { Register() error // Set add an item to the cache, replacing any existing item. If the duration is 0 - Set(key string, value interface{}, duration time.Duration) + Set(key string, value any, params ...any) error // SetRaw add an item to the cache, replacing any existing item. If the duration is 0 - SetRaw(key string, value []byte, duration time.Duration) + SetRaw(key string, value []byte, params ...any) error // Replace set a new value for the cache key only if it already exists, and the existing // item hasn't expired. Returns an error otherwise. - Replace(key string, value interface{}, duration time.Duration) bool + Replace(key string, value any, params ...any) bool // Get an item from the cache. Returns a bool indicating whether the key was found. - Get(key string, out interface{}) bool + Get(key string, out any, params ...any) bool // GetRaw get an item from the cache. Returns cache content in []byte and a bool indicating whether the key was found. - GetRaw(key string) ([]byte, bool) + GetRaw(key string, params ...any) ([]byte, bool) // GetWithExpiration returns an item and its expiration time from the cache. // It returns the item exported to out, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. - GetWithExpiration(key string, out interface{}) (time.Time, bool) + GetWithExpiration(key string, out any, params ...any) (time.Time, bool) // GetRawWithExpiration returns an item and its expiration time from the cache. // It returns the content in []byte, the expiration time if one is set (if the item // never expires a zero value for time.Time is returned), and a bool indicating // whether the key was found. - GetRawWithExpiration(key string) ([]byte, time.Time, bool) + GetRawWithExpiration(key string, params ...any) ([]byte, time.Time, bool) // Increment an item of type int, int8, int16, int32, int64, uintptr, uint, // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to increment it by n. - Increment(key string, n interface{}) int64 + Increment(key string, n any, params ...any) (int64, error) // Decrement an item of type int, int8, int16, int32, int64, uintptr, uint, // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the // item's value is not an integer, if it was not found, or if it is not // possible to decrement it by n. - Decrement(key string, n interface{}) int64 + Decrement(key string, n any, params ...any) (int64, error) // Delete an item from the cache. Does nothing if the key is not in the cache. - Delete(key string) + Delete(key string, params ...any) error // Expire re-set expiration duration for a key - Expire(key string, t time.Time) error + Expire(key string, t time.Time, params ...any) error // ItemCount Returns the number of items in the cache. This may include items that have // expired, but have not yet been cleaned up. @@ -66,11 +67,12 @@ type Interface interface { // Flush delete all items from the cache. Flush() error - // SetMarshaller set interface{} to []byte marshalling function - SetMarshaller(func(input interface{}) ([]byte, error)) + SetSerializer(v serializer.Interface) - // SetUnMarshaller set []byte to interface{} unmarshalling function - SetUnMarshaller(func(bytes []byte, out interface{}) error) + Serializer() serializer.Interface + + Marshal(v any) ([]byte, error) + Unmarshal(data []byte, v any) error // SetPrefix set a key prefix SetPrefix(p string) diff --git a/lib/memo/kv/kv.go b/lib/memo/kv/kv.go new file mode 100644 index 00000000..e08e5250 --- /dev/null +++ b/lib/memo/kv/kv.go @@ -0,0 +1,33 @@ +package kv + +import "time" + +type Params struct { + Duration time.Duration + Bucket string +} +type bucket string + +func Bucket(s string) bucket { + return bucket(s) +} + +func Parse(params []any) Params { + var p = Params{ + Duration: time.Duration(-1), + } + for idx, _ := range params { + switch v := params[idx].(type) { + case Params: + return v + case time.Duration: + p.Duration = v + case string: + p.Bucket = v + case bucket: + p.Bucket = string(v) + } + } + + return p +} diff --git a/lib/outcome/outcome.go b/lib/outcome/outcome.go index 7f0c6f27..d191c685 100644 --- a/lib/outcome/outcome.go +++ b/lib/outcome/outcome.go @@ -11,7 +11,7 @@ import ( type Response struct { ContentType string - Data interface{} + Data any StatusCode int Headers map[string]string RedirectURL string @@ -56,7 +56,7 @@ func RedirectTemporary(to string) *Response { return response.Redirect(to, fiber.StatusTemporaryRedirect) } -func Json(input interface{}) *Response { +func Json(input any) *Response { var response = Response{ ContentType: fiber.MIMEApplicationJSONCharsetUTF8, StatusCode: 200, @@ -78,7 +78,7 @@ func (response *Response) Header(key, value string) *Response { return response } -func (response *Response) Content(input interface{}) *Response { +func (response *Response) Content(input any) *Response { switch v := input.(type) { case string: response.Data = []byte(v) @@ -111,7 +111,7 @@ type Cookie struct { SameSite string `json:"same_site"` } -func (response *Response) Cookie(key string, val interface{}, params ...interface{}) *Response { +func (response *Response) Cookie(key string, val any, params ...any) *Response { cookie := new(Cookie) cookie.Name = key cookie.Path = "/" @@ -164,7 +164,7 @@ func (response *Response) RedirectTemporary(to string) *Response { return response.Redirect(to, fiber.StatusTemporaryRedirect) } -func (response *Response) Error(value interface{}, code ...int) *Response { +func (response *Response) Error(value any, code ...int) *Response { if len(code) > 0 { response.StatusCode = code[0] } else { diff --git a/lib/pubsub/drivers/nats/nats.go b/lib/pubsub/drivers/nats/nats.go deleted file mode 100644 index 8bc25515..00000000 --- a/lib/pubsub/drivers/nats/nats.go +++ /dev/null @@ -1,225 +0,0 @@ -package nats - -import ( - "github.com/getevo/evo/v2/lib/kafka" - "github.com/getevo/evo/v2/lib/pubsub" - "github.com/getevo/evo/v2/lib/settings" - "github.com/nats-io/nats.go" -) - -var Driver = driver{} - -var listeners = map[string][]func(topic string, message []byte, driver pubsub.Interface){} -var producers = map[string]*kafka.Producer{} - -type driver struct{} - -func (d driver) Subscribe(topic string, onMessage func(topic string, message []byte, driver pubsub.Interface), params ...interface{}) { - if _, ok := listeners[topic]; !ok { - listeners[topic] = []func(topic string, message []byte, driver pubsub.Interface){onMessage} - var configs []*kafka.ConsumerConfig - for idx, _ := range params { - if v, ok := params[idx].(kafka.ConsumerConfig); ok { - configs = append(configs, &v) - continue - } - if v, ok := params[idx].(*kafka.ConsumerConfig); ok { - configs = append(configs, v) - } - } - Client.NewConsumer(topic, configs...).OnMessage(func(message kafka.Message) { - for _, callback := range listeners[topic] { - go callback(topic, message.Value, d) - } - }) - } else { - listeners[topic] = append(listeners[topic], onMessage) - } - -} -func (d driver) Publish(topic string, message []byte, params ...interface{}) error { - if _, ok := producers[topic]; !ok { - var config = kafka.ProducerConfig{} - switch settings.Get("KAFKA.COMPRESSION").String() { - case "gzip": - config.Compression(kafka.Gzip) - case "snappy": - config.Compression(kafka.Snappy) - case "lz4": - config.Compression(kafka.Lz4) - case "zstd": - config.Compression(kafka.Zstd) - } - switch settings.Get("KAFKA.BALANCER").String() { - case "MurMur2": - config.Balancer(kafka.MurMur2) - case "CRC32": - config.Balancer(kafka.CRC32) - case "Hash": - config.Balancer(kafka.Hash) - case "LeastBytes": - config.Balancer(kafka.LeastBytes) - case "RoundRobin": - config.Balancer(kafka.RoundRobin) - } - switch settings.Get("KAFKA.REQUIRE_ACKS").String() { - case "RequireNone": - config.Ack(kafka.RequireNone) - case "RequireOne": - config.Ack(kafka.RequireOne) - case "RequireAll": - config.Ack(kafka.RequireAll) - } - readTimeout, err := settings.Get("KAFKA.BatchTimeout").Duration() - if err != nil { - config.ReadTimeout(readTimeout) - } - writeTimeout, err := settings.Get("KAFKA.WriteTimeout").Duration() - if err != nil { - config.WriteTimeout(writeTimeout) - } - - batchTimeout, err := settings.Get("KAFKA.BatchTimeout").Duration() - if err != nil { - config.BatchTimeout(batchTimeout) - } - config.MaxAttempts(settings.Get("KAFKA.MaxAttempts").Int()) - config.BatchSize(settings.Get("KAFKA.BatchSize").Int()) - config.BatchBytes(settings.Get("KAFKA.BatchBytes").Int64()) - config.Async(settings.Get("KAFKA.ASYNC_WRITE").Bool()) - producers[topic] = Client.NewProducer(topic, &config) - } - return producers[topic].Write(kafka.Message{ - Value: message, - }) -} - -var prefix = "" -var Client *nats.Conn - -func (driver) Register() error { - if Client != nil { - return nil - } - settings.Register( - settings.SettingDomain{ - Title: "NATS", - Domain: "NATS", - Description: "NATS configurations", - ReadOnly: false, - Visible: true, - }, - settings.Setting{ - Domain: "NATS", - Name: "SERVER", - Title: "Servers", - Description: "List of comma separated NATS servers", - Type: "text", - ReadOnly: false, - Visible: true, - }, - - settings.Setting{ - Domain: "NATS", - Name: "MAX_RECONNECT", - Title: "Max Reconnects", - Description: "MaxReconnect attempts", - Type: "number", - Value: "5", - ReadOnly: false, - Visible: true, - }, - - settings.Setting{ - Domain: "NATS", - Name: "RECONNECT_WAIT", - Title: "Reconnect Wait", - Value: "2s", - Description: "Wait time before reconnect", - Type: "text", - ReadOnly: false, - Visible: true, - }, - - settings.Setting{ - Domain: "NATS", - Name: "RANDOMIZE", - Title: "Reconnect Wait", - Description: "Randomization of the server pool", - Type: "bool", - Value: "true", - ReadOnly: false, - Visible: true, - }, - - settings.Setting{ - Domain: "NATS", - Name: "USERNAME", - Title: "Username", - Description: "Username in case of authentication", - Type: "text", - ReadOnly: false, - Visible: true, - }, - - settings.Setting{ - Domain: "NATS", - Name: "PASSWORD", - Title: "Password", - Description: "Password in case of authentication", - Type: "text", - ReadOnly: false, - Visible: true, - }, - - settings.Setting{ - Domain: "NATS", - Name: "TOKEN", - Title: "Token", - Description: "Token in case of authentication", - Type: "text", - ReadOnly: false, - Visible: true, - }, - ) - var err error - var options []nats.Option - if !settings.Get("NATS.RANDOMIZE").Bool() { - options = append(options, nats.DontRandomize()) - } - - if settings.Get("NATS.USERNAME").String() != "" { - options = append(options, nats.UserInfo(settings.Get("NATS.USERNAME").String(), settings.Get("NATS.PASSWORD").String())) - } - - if settings.Get("NATS.TOKEN").String() != "" { - options = append(options, nats.Token(settings.Get("NATS.TOKEN").String())) - } - - if wait, err := settings.Get("NATS.RECONNECT_WAIT").Duration(); wait > 0 && err == nil { - options = append(options, nats.ReconnectWait(wait)) - } - - if reconnects := settings.Get("NATS.MAX_RECONNECT").Int(); reconnects > -1 { - options = append(options, nats.MaxReconnects(reconnects)) - } - - nats.CustomInboxPrefix() - Client, err = nats.Connect(settings.Get("NATS.SERVER").String(), options...) - - return err -} - -func (driver) Name() string { - return "kafka" -} - -// SetMarshaller set interface{} to []byte marshalling function -func (driver) SetMarshaller(fn func(input interface{}) ([]byte, error)) { - -} - -// SetUnMarshaller set []byte to interface{} unmarshalling function -func (driver) SetUnMarshaller(fn func(bytes []byte, out interface{}) error) { - -} diff --git a/lib/pubsub/functions.go b/lib/pubsub/functions.go index fc6de6f9..72e584ec 100644 --- a/lib/pubsub/functions.go +++ b/lib/pubsub/functions.go @@ -44,13 +44,17 @@ func AddDriver(driver Interface) { } } -func Subscribe(topic string, onMessage func(topic string, message []byte, driver Interface), params ...interface{}) { +func Subscribe(topic string, onMessage func(topic string, message []byte, driver Interface), params ...any) { defaultDriver.Subscribe(topic, onMessage, params...) } -func Publish(topic string, message []byte, params ...interface{}) error { +func Publish(topic string, message []byte, params ...any) error { return defaultDriver.Publish(topic, message, params...) } +func SetPrefix(s string) { + defaultDriver.SetPrefix(s) +} + func Register() error { return nil } diff --git a/lib/pubsub/inteface.go b/lib/pubsub/inteface.go index 13443d7d..6e3969c7 100644 --- a/lib/pubsub/inteface.go +++ b/lib/pubsub/inteface.go @@ -1,6 +1,9 @@ package pubsub -import "time" +import ( + "github.com/getevo/evo/v2/lib/serializer" + "time" +) type Message struct { Time time.Time @@ -10,12 +13,17 @@ type Message struct { type Interface interface { Name() string Register() error - Subscribe(topic string, onMessage func(topic string, message []byte, driver Interface), params ...interface{}) - Publish(topic string, message []byte, params ...interface{}) error + Subscribe(topic string, onMessage func(topic string, message []byte, driver Interface), params ...any) + Publish(topic string, message any, params ...any) error + PublishBytes(topic string, message []byte, params ...any) error - // SetMarshaller set interface{} to []byte marshalling function - SetMarshaller(func(input interface{}) ([]byte, error)) + // SetSerializer change serialization method + SetSerializer(v serializer.Interface) - // SetUnMarshaller set []byte to interface{} unmarshalling function - SetUnMarshaller(func(bytes []byte, out interface{}) error) + Serializer() serializer.Interface + + Marshal(v any) ([]byte, error) + Unmarshal(data []byte, v any) error + + SetPrefix(s string) } diff --git a/lib/reflections/reflections.go b/lib/reflections/reflections.go index 6a5b6424..5299e73b 100644 --- a/lib/reflections/reflections.go +++ b/lib/reflections/reflections.go @@ -15,7 +15,7 @@ var ErrUnexportedField = errors.New("unexported field") // GetField returns the value of the provided obj field. // The `obj` can either be a structure or pointer to structure. -func GetField(obj interface{}, name string) (interface{}, error) { +func GetField(obj any, name string) (any, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return nil, fmt.Errorf("cannot use GetField on a non-struct object: %w", ErrUnsupportedType) } @@ -31,7 +31,7 @@ func GetField(obj interface{}, name string) (interface{}, error) { // GetFieldKind returns the kind of the provided obj field. // The `obj` can either be a structure or pointer to structure. -func GetFieldKind(obj interface{}, name string) (reflect.Kind, error) { +func GetFieldKind(obj any, name string) (reflect.Kind, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return reflect.Invalid, fmt.Errorf("cannot use GetFieldKind on a non-struct interface: %w", ErrUnsupportedType) } @@ -48,7 +48,7 @@ func GetFieldKind(obj interface{}, name string) (reflect.Kind, error) { // GetFieldType returns the kind of the provided obj field. // The `obj` can either be a structure or pointer to structure. -func GetFieldType(obj interface{}, name string) (string, error) { +func GetFieldType(obj any, name string) (string, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return "", fmt.Errorf("cannot use GetFieldType on a non-struct interface: %w", ErrUnsupportedType) } @@ -65,7 +65,7 @@ func GetFieldType(obj interface{}, name string) (string, error) { // GetFieldTag returns the provided obj field tag value. // The `obj` parameter can either be a structure or pointer to structure. -func GetFieldTag(obj interface{}, fieldName, tagKey string) (string, error) { +func GetFieldTag(obj any, fieldName, tagKey string) (string, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return "", fmt.Errorf("cannot use GetFieldTag on a non-struct interface: %w", ErrUnsupportedType) } @@ -88,7 +88,7 @@ func GetFieldTag(obj interface{}, fieldName, tagKey string) (string, error) { // GetFieldNameByTagValue looks up a field with a matching `{tagKey}:"{tagValue}"` tag in the provided `obj` item. // The `obj` parameter must be a `struct`, or a `pointer` to one. If the `obj` parameter doesn't have a field tagged // with the `tagKey`, and the matching `tagValue`, this function returns an error. -func GetFieldNameByTagValue(obj interface{}, tagKey, tagValue string) (string, error) { +func GetFieldNameByTagValue(obj any, tagKey, tagValue string) (string, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return "", fmt.Errorf("cannot use GetFieldByTag on a non-struct interface: %w", ErrUnsupportedType) } @@ -111,7 +111,7 @@ func GetFieldNameByTagValue(obj interface{}, tagKey, tagValue string) (string, e // // The `obj` parameter must be a pointer to a struct, otherwise it soundly fails. // The provided `value` type should match with the struct field being set. -func SetField(obj interface{}, name string, value interface{}) error { +func SetField(obj any, name string, value any) error { // Fetch the field reflect.Value structValue := reflect.ValueOf(obj).Elem() structFieldValue := structValue.FieldByName(name) @@ -137,7 +137,7 @@ func SetField(obj interface{}, name string, value interface{}) error { // HasField checks if the provided `obj` struct has field named `name`. // The `obj` can either be a structure or pointer to structure. -func HasField(obj interface{}, name string) (bool, error) { +func HasField(obj any, name string) (bool, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return false, fmt.Errorf("cannot use HasField on a non-struct interface: %w", ErrUnsupportedType) } @@ -154,18 +154,18 @@ func HasField(obj interface{}, name string) (bool, error) { // Fields returns the struct fields names list. // The `obj` parameter can either be a structure or pointer to structure. -func Fields(obj interface{}) ([]string, error) { +func Fields(obj any) ([]string, error) { return fields(obj, false) } // FieldsDeep returns "flattened" fields. // // Note that FieldsDeept treats fields from anonymous inner structs as normal fields. -func FieldsDeep(obj interface{}) ([]string, error) { +func FieldsDeep(obj any) ([]string, error) { return fields(obj, true) } -func fields(obj interface{}, deep bool) ([]string, error) { +func fields(obj any, deep bool) ([]string, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return nil, fmt.Errorf("cannot use fields on a non-struct interface: %w", ErrUnsupportedType) } @@ -197,17 +197,17 @@ func fields(obj interface{}, deep bool) ([]string, error) { // Items returns the field:value struct pairs as a map. // The `obj` parameter can either be a structure or pointer to structure. -func Items(obj interface{}) (map[string]interface{}, error) { +func Items(obj any) (map[string]any, error) { return items(obj, false) } // ItemsDeep returns "flattened" items. // Note that ItemsDeep will treat fields from anonymous inner structs as normal fields. -func ItemsDeep(obj interface{}) (map[string]interface{}, error) { +func ItemsDeep(obj any) (map[string]any, error) { return items(obj, true) } -func items(obj interface{}, deep bool) (map[string]interface{}, error) { +func items(obj any, deep bool) (map[string]any, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return nil, fmt.Errorf("cannot use items on a non-struct interface: %w", ErrUnsupportedType) } @@ -216,7 +216,7 @@ func items(obj interface{}, deep bool) (map[string]interface{}, error) { objType := objValue.Type() fieldsCount := objType.NumField() - allItems := make(map[string]interface{}) + allItems := make(map[string]any) for i := 0; i < fieldsCount; i++ { field := objType.Field(i) @@ -244,18 +244,18 @@ func items(obj interface{}, deep bool) (map[string]interface{}, error) { // Tags lists the struct tag fields. // The `obj` can whether be a structure or pointer to structure. -func Tags(obj interface{}, key string) (map[string]string, error) { +func Tags(obj any, key string) (map[string]string, error) { return tags(obj, key, false) } // TagsDeep returns "flattened" tags. // Note that TagsDeep treats fields from anonymous // inner structs as normal fields. -func TagsDeep(obj interface{}, key string) (map[string]string, error) { +func TagsDeep(obj any, key string) (map[string]string, error) { return tags(obj, key, true) } -func tags(obj interface{}, key string, deep bool) (map[string]string, error) { +func tags(obj any, key string, deep bool) (map[string]string, error) { if !isSupportedType(obj, []reflect.Kind{reflect.Struct, reflect.Ptr}) { return nil, fmt.Errorf("cannot use tags on a non-struct interface: %w", ErrUnsupportedType) } @@ -289,7 +289,7 @@ func tags(obj interface{}, key string, deep bool) (map[string]string, error) { return allTags, nil } -func reflectValue(obj interface{}) reflect.Value { +func reflectValue(obj any) reflect.Value { var val reflect.Value if reflect.TypeOf(obj).Kind() == reflect.Ptr { @@ -306,7 +306,7 @@ func isExportableField(field reflect.StructField) bool { return field.PkgPath == "" } -func isSupportedType(obj interface{}, types []reflect.Kind) bool { +func isSupportedType(obj any, types []reflect.Kind) bool { for _, t := range types { if reflect.TypeOf(obj).Kind() == t { return true diff --git a/lib/serializer/marshal.go b/lib/serializer/marshal.go new file mode 100644 index 00000000..68c1ffa6 --- /dev/null +++ b/lib/serializer/marshal.go @@ -0,0 +1,25 @@ +package serializer + +import ( + "encoding/json" + "github.com/kelindar/binary" +) + +type Interface struct { + Marshal func(v any) ([]byte, error) + Unmarshal func(data []byte, v any) error +} + +func New(marshal func(v any) ([]byte, error), unmarshal func(data []byte, v any) error) Interface { + return Interface{ + marshal, unmarshal, + } +} + +var JSON = Interface{ + json.Marshal, json.Unmarshal, +} + +var Binary = Interface{ + binary.Marshal, binary.Unmarshal, +} diff --git a/lib/settings/database/database.go b/lib/settings/database/database.go index 47b0686c..6bf3a4b1 100644 --- a/lib/settings/database/database.go +++ b/lib/settings/database/database.go @@ -58,7 +58,7 @@ func (config *Database) All() map[string]generic.Value { } return m } -func (config *Database) Set(key string, value interface{}) error { +func (config *Database) Set(key string, value any) error { key = strings.ToUpper(key) var chunks = strings.SplitN(key, ".", 2) if len(chunks) == 2 { @@ -66,7 +66,7 @@ func (config *Database) Set(key string, value interface{}) error { } return nil } -func (config *Database) SetMulti(data map[string]interface{}) error { +func (config *Database) SetMulti(data map[string]any) error { for key, value := range data { key = strings.ToUpper(key) var chunks = strings.SplitN(key, ".", 2) @@ -76,7 +76,7 @@ func (config *Database) SetMulti(data map[string]interface{}) error { } return nil } -func (config *Database) Register(settings ...interface{}) error { +func (config *Database) Register(settings ...any) error { for _, s := range settings { var v = generic.Parse(s) diff --git a/lib/settings/proxy.go b/lib/settings/proxy.go index fccf3477..cc20aedb 100644 --- a/lib/settings/proxy.go +++ b/lib/settings/proxy.go @@ -47,7 +47,7 @@ func (config *proxy) Has(key string) (bool, generic.Value) { func (config *proxy) All() map[string]generic.Value { return drivers[len(drivers)-1].All() } -func (config *proxy) Set(key string, value interface{}) error { +func (config *proxy) Set(key string, value any) error { drivers[len(drivers)-1].Set(key, value) delete(fastAccess, key) if v, ok := tracker[key]; ok { @@ -55,7 +55,7 @@ func (config *proxy) Set(key string, value interface{}) error { } return nil } -func (config *proxy) SetMulti(data map[string]interface{}) error { +func (config *proxy) SetMulti(data map[string]any) error { drivers[len(drivers)-1].SetMulti(data) for key, _ := range data { if v, ok := tracker[key]; ok { @@ -64,7 +64,7 @@ func (config *proxy) SetMulti(data map[string]interface{}) error { } return nil } -func (config *proxy) Register(settings ...interface{}) error { +func (config *proxy) Register(settings ...any) error { if len(settings) > 0 { if _, ok := settings[0].(Setting); ok { return drivers[len(drivers)-1].Register(settings...) @@ -72,7 +72,7 @@ func (config *proxy) Register(settings ...interface{}) error { return drivers[len(drivers)-1].Register(settings...) } else { var pkg = "" - var set []interface{} + var set []any for _, setting := range settings { var s = generic.Parse(setting) var ref = s.Indirect() diff --git a/lib/settings/settings.go b/lib/settings/settings.go index 188eee64..f689c492 100644 --- a/lib/settings/settings.go +++ b/lib/settings/settings.go @@ -10,14 +10,14 @@ var drivers = []Interface{&yml.Yaml{}} var defaultDriver Interface = &yml.Yaml{} type Interface interface { - Name() string // Name returns driver name - Get(key string) generic.Value // Get returns single value - Has(key string) (bool, generic.Value) // Has check if key exists - All() map[string]generic.Value // All returns all of configuration values - Set(key string, value interface{}) error // Set sets value of a key - SetMulti(data map[string]interface{}) error // SetMulti sets multiple keys at once - Register(settings ...interface{}) error // Register a new key to be used in the future - Init(params ...string) error // Init will be called at the initialization of application + Name() string // Name returns driver name + Get(key string) generic.Value // Get returns single value + Has(key string) (bool, generic.Value) // Has check if key exists + All() map[string]generic.Value // All returns all of configuration values + Set(key string, value any) error // Set sets value of a key + SetMulti(data map[string]any) error // SetMulti sets multiple keys at once + Register(settings ...any) error // Register a new key to be used in the future + Init(params ...string) error // Init will be called at the initialization of application } type Setting struct { @@ -102,15 +102,15 @@ func All() map[string]generic.Value { return defaultDriver.All() } -func Set(key string, value interface{}) error { +func Set(key string, value any) error { return defaultDriver.Set(key, value) } -func SetMulti(data map[string]interface{}) error { +func SetMulti(data map[string]any) error { return defaultDriver.SetMulti(data) } -func Register(settings ...interface{}) { +func Register(settings ...any) { defaultDriver.Register(settings...) /* var key = "" for idx, _ := range settings { diff --git a/lib/settings/yml/yml.go b/lib/settings/yml/yml.go index 9f277989..5972f738 100644 --- a/lib/settings/yml/yml.go +++ b/lib/settings/yml/yml.go @@ -12,7 +12,7 @@ import ( var Driver = &Yaml{} type Yaml struct { - data map[string]interface{} + data map[string]any path string writeFn func() } @@ -40,18 +40,18 @@ func (config *Yaml) Has(key string) (bool, generic.Value) { func (config *Yaml) All() map[string]generic.Value { return map[string]generic.Value{} } -func (config *Yaml) Set(key string, value interface{}) error { +func (config *Yaml) Set(key string, value any) error { dot.Set(config.data, key, value) return config.write() } -func (config *Yaml) SetMulti(data map[string]interface{}) error { +func (config *Yaml) SetMulti(data map[string]any) error { for key, value := range data { dot.Set(&config.data, key, value) } return config.write() } -func (config *Yaml) Register(settings ...interface{}) error { +func (config *Yaml) Register(settings ...any) error { for _, s := range settings { var v = generic.Parse(s) if !v.Is("settings.Setting") { @@ -65,7 +65,7 @@ func (config *Yaml) Register(settings ...interface{}) error { return nil } func (config *Yaml) Init(params ...string) error { - config.data = map[string]interface{}{} + config.data = map[string]any{} if len(params) != 0 { for _, path := range params { bytes, err := gpath.ReadFile(path) diff --git a/lib/storage/filesystem/filesystem.go b/lib/storage/filesystem/filesystem.go index 1cdc8ac1..64dd5230 100644 --- a/lib/storage/filesystem/filesystem.go +++ b/lib/storage/filesystem/filesystem.go @@ -128,7 +128,7 @@ func (driver *Driver) Touch(path string) error { return nil } -func (driver *Driver) WriteJson(path string, content interface{}) error { +func (driver *Driver) WriteJson(path string, content any) error { var b, err = json.Marshal(content) if err != nil { return err @@ -136,7 +136,7 @@ func (driver *Driver) WriteJson(path string, content interface{}) error { return driver.Write(path, b) } -func (driver *Driver) Append(path string, content interface{}) error { +func (driver *Driver) Append(path string, content any) error { path = driver.getRealPath(path) return gpath.Append(path, content) } @@ -222,7 +222,7 @@ func (driver *Driver) MkdirAll(path string, perm ...fs.FileMode) error { return os.MkdirAll(path, perm[0]) } -func (driver *Driver) Write(path string, content interface{}) error { +func (driver *Driver) Write(path string, content any) error { return gpath.Write(path, content) } diff --git a/lib/storage/ftp/ftp.go b/lib/storage/ftp/ftp.go index 070ad2f2..fb9f97ab 100644 --- a/lib/storage/ftp/ftp.go +++ b/lib/storage/ftp/ftp.go @@ -138,7 +138,7 @@ func (driver *Driver) Touch(path string) error { return driver.Write(path, "") } -func (driver *Driver) WriteJson(path string, content interface{}) error { +func (driver *Driver) WriteJson(path string, content any) error { var b, err = json.Marshal(content) if err != nil { return err @@ -146,7 +146,7 @@ func (driver *Driver) WriteJson(path string, content interface{}) error { return driver.Write(path, b) } -func (driver *Driver) Append(path string, content interface{}) error { +func (driver *Driver) Append(path string, content any) error { path = driver.getRealPath(path) var connection, err = driver.getConnection() defer driver.Close(connection) @@ -357,7 +357,7 @@ func (driver *Driver) MkdirAll(path string, perm ...fs.FileMode) error { return nil } -func (driver *Driver) Write(path string, content interface{}) error { +func (driver *Driver) Write(path string, content any) error { var conn, err = driver.getConnection() defer driver.Close(conn) if err != nil { diff --git a/lib/storage/lib/interface.go b/lib/storage/lib/interface.go index c7114a4f..9bdff001 100644 --- a/lib/storage/lib/interface.go +++ b/lib/storage/lib/interface.go @@ -12,9 +12,9 @@ type Driver interface { SetWorkingDir(path string) error WorkingDir() string Touch(path string) error - WriteJson(path string, content interface{}) error - Write(path string, content interface{}) error - Append(path string, content interface{}) error + WriteJson(path string, content any) error + Write(path string, content any) error + Append(path string, content any) error SetMetadata(path string, meta Metadata) error GetMetadata(path string) (*Metadata, error) CopyDir(src, dest string) error @@ -85,14 +85,14 @@ func (f FileInfo) Sys() any { return f.sys } -func (f FileInfo) Append(content interface{}) error { +func (f FileInfo) Append(content any) error { if f.IsDir() { return fmt.Errorf("cant write on directory") } return f.storage.Append(f.path, content) } -func (f FileInfo) Write(content interface{}) error { +func (f FileInfo) Write(content any) error { if f.IsDir() { return fmt.Errorf("cant write on directory") } diff --git a/lib/storage/s3/s3.go b/lib/storage/s3/s3.go index aa8b562d..fd172a60 100644 --- a/lib/storage/s3/s3.go +++ b/lib/storage/s3/s3.go @@ -260,7 +260,7 @@ func (driver *Driver) Touch(path string) error { return nil } -func (driver *Driver) WriteJson(path string, content interface{}) error { +func (driver *Driver) WriteJson(path string, content any) error { var b, err = json.Marshal(content) if err != nil { return err @@ -268,7 +268,7 @@ func (driver *Driver) WriteJson(path string, content interface{}) error { return driver.Write(path, b) } -func (driver *Driver) Append(path string, content interface{}) error { +func (driver *Driver) Append(path string, content any) error { path = driver.getRealPath(path) b, err := driver.ReadAll(path) if err != nil { @@ -464,7 +464,7 @@ func (driver *Driver) MkdirAll(path string, perm ...fs.FileMode) error { return driver.Write(path+"/.ignore", "") } -func (driver *Driver) Write(path string, content interface{}) error { +func (driver *Driver) Write(path string, content any) error { path = driver.getRealPath(path) var data *bytes.Reader diff --git a/lib/storage/sftp/sftp.go b/lib/storage/sftp/sftp.go index ae92f325..f2470e55 100644 --- a/lib/storage/sftp/sftp.go +++ b/lib/storage/sftp/sftp.go @@ -135,7 +135,7 @@ func (driver *Driver) Touch(path string) error { return driver.client.Touch(path) } -func (driver *Driver) WriteJson(path string, content interface{}) error { +func (driver *Driver) WriteJson(path string, content any) error { var b, err = json.Marshal(content) if err != nil { return err @@ -143,7 +143,7 @@ func (driver *Driver) WriteJson(path string, content interface{}) error { return driver.Write(path, b) } -func (driver *Driver) Append(path string, content interface{}) error { +func (driver *Driver) Append(path string, content any) error { path = driver.getRealPath(path) var data *bytes.Reader switch v := content.(type) { @@ -282,7 +282,7 @@ func (driver *Driver) MkdirAll(path string, perm ...fs.FileMode) error { return driver.client.MkdirAll(path) } -func (driver *Driver) Write(path string, content interface{}) error { +func (driver *Driver) Write(path string, content any) error { path = driver.getRealPath(path) var data *bytes.Reader switch v := content.(type) { diff --git a/lib/stract/stract.go b/lib/stract/stract.go index 4d161545..65f68c25 100644 --- a/lib/stract/stract.go +++ b/lib/stract/stract.go @@ -314,7 +314,7 @@ func cleanText(t string) string { return t } -func PrettyStruct(data interface{}) string { +func PrettyStruct(data any) string { val, err := json.MarshalIndent(data, "", " ") if err != nil { return "" diff --git a/lib/text/parser.go b/lib/text/parser.go index 33dd698d..ebdb75e2 100644 --- a/lib/text/parser.go +++ b/lib/text/parser.go @@ -26,7 +26,7 @@ func ParseWildCard(input, expr string) []string { return res[0][1:] } -func ToJSON(v interface{}) string { +func ToJSON(v any) string { b, _ := json.Marshal(v) return string(b) } diff --git a/lib/tpl/tpl.go b/lib/tpl/tpl.go index ac40703e..8da89059 100644 --- a/lib/tpl/tpl.go +++ b/lib/tpl/tpl.go @@ -10,7 +10,7 @@ import ( var varRegex = regexp.MustCompile(`(?mi)\$([a-z\.\_\[\]0-9]+)*`) -func Render(src string, params ...interface{}) string { +func Render(src string, params ...any) string { return varRegex.ReplaceAllStringFunc(src, func(s string) string { var key = s[1:] for _, item := range params { diff --git a/lib/tpl/tpl_test.go b/lib/tpl/tpl_test.go index 06c557b2..6bcdb468 100644 --- a/lib/tpl/tpl_test.go +++ b/lib/tpl/tpl_test.go @@ -12,10 +12,10 @@ type User struct { func TestRender(t *testing.T) { var text = `Hello $title $user.Name $user.Family you have $sender[0] email From $sender[2][from]($sender[2][user].Name $sender[2][user].Family) at $date[0]:$date[1]:$date[2]` - fmt.Println(Render(text, map[string]interface{}{ + fmt.Println(Render(text, map[string]any{ "title": "Mrs", "user": User{Name: "Maria", Family: "Rossy"}, - "sender": []interface{}{1, "empty!", map[string]interface{}{"from": "example@example.com", "user": User{Name: "Marco", Family: "Pollo"}}}, + "sender": []any{1, "empty!", map[string]any{"from": "example@example.com", "user": User{Name: "Marco", Family: "Pollo"}}}, "date": []int{10, 15, 20}, })) } diff --git a/lib/try/try.go b/lib/try/try.go index a56b6848..32e3a55f 100644 --- a/lib/try/try.go +++ b/lib/try/try.go @@ -5,7 +5,7 @@ import "github.com/getevo/evo/v2/lib/panics" const rethrow_panic = "_____rethrow" type ( - Error interface{} + Error any exception struct { finally func() Error Error diff --git a/repr.go b/repr.go index c6a6e839..fdc7b2f6 100644 --- a/repr.go +++ b/repr.go @@ -2,10 +2,10 @@ package evo import "github.com/alecthomas/repr" -func Repr(v interface{}) string { +func Repr(v any) string { return repr.String(v) } -func Dump(v interface{}) { +func Dump(v any) { repr.Println(v) }