diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 00000000..2af6ad68 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,2 @@ +[url "git@github.com:"] + insteadOf = https://github.com/ diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 00000000..26bdeb63 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,53 @@ +version: "2" +issues: + fix: true +linters: + default: none + enable: + - govet + exclusions: + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - internal/example + - cmds + - vendor + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - goimports + - gofmt + - gofumpt + settings: + gofumpt: + extra-rules: true + goimports: + # A list of prefixes, which, if set, checks import paths + # with the given prefixes are grouped after 3rd-party packages. + # Default: [] + local-prefixes: + - github.com/pubgo/funk/v2 + gofmt: + # Simplify code: gofmt with `-s` option. + # Default: true + simplify: false + # Apply the rewrite rules to the source before reformatting. + # https://pkg.go.dev/cmd/gofmt + # Default: [] + rewrite-rules: + - pattern: 'interface{}' + replacement: 'any' + - pattern: 'a[b:len(a)]' + replacement: 'a[b:]' + + exclusions: + paths: + - internal/example + - vendor + - examples$ + - proto diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index f5d20afa..00000000 --- a/.golangci.yml +++ /dev/null @@ -1,29 +0,0 @@ -version: "2" -linters: - default: none - enable: - - govet - exclusions: - presets: - - comments - - common-false-positives - - legacy - - std-error-handling - paths: - - internal/example - - cmds - - vendor - - third_party$ - - builtin$ - - examples$ -formatters: - enable: - - goimports - exclusions: - paths: - - internal/example - - cmds - - vendor - - third_party$ - - builtin$ - - examples$ diff --git a/.version b/.version new file mode 100644 index 00000000..6eaf8943 --- /dev/null +++ b/.version @@ -0,0 +1 @@ +v2.0.0 \ No newline at end of file diff --git a/assert/aaa.go b/assert/aaa.go new file mode 100644 index 00000000..f0c1578e --- /dev/null +++ b/assert/aaa.go @@ -0,0 +1,7 @@ +package assert + +import "github.com/pubgo/funk/v2/features" + +const Name = "assert" + +var FeatureDebugMode = features.Bool("assert.debug_mode", false, "debug mode, pretty stack and error") diff --git a/assert/assert.go b/assert/assert.go index 07db5cea..27f9bca3 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -2,23 +2,32 @@ package assert import ( "fmt" -) -var EnablePrintStack bool + "github.com/google/go-cmp/cmp" + "github.com/k0kubun/pp/v3" +) -func Assert(b bool, format string, a ...interface{}) { +func Assert(b bool, format string, a ...any) { if b { must(fmt.Errorf(format, a...)) } } -func If(b bool, format string, a ...interface{}) { +func MustEqual[T any](a, b T) { + if !cmp.Equal(a, b) { + pp.Println("a: ", a) + pp.Println("b: ", b) + must(fmt.Errorf("a,b not equal")) + } +} + +func If(b bool, format string, a ...any) { if b { must(fmt.Errorf(format, a...)) } } -func T(b bool, format string, a ...interface{}) { +func T(b bool, format string, a ...any) { if b { must(fmt.Errorf(format, a...)) } diff --git a/assert/assert_test.go b/assert/assert_test.go index dc127319..124d0eb8 100644 --- a/assert/assert_test.go +++ b/assert/assert_test.go @@ -3,14 +3,10 @@ package assert_test import ( "testing" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/recovery" ) -func init() { - assert.EnablePrintStack = true -} - func TestCheckNil(t *testing.T) { var a *int diff --git a/assert/must.go b/assert/must.go index 09eee9c5..79ee861b 100644 --- a/assert/must.go +++ b/assert/must.go @@ -7,7 +7,7 @@ import ( "runtime/debug" ) -func Must(err error, args ...interface{}) { +func Must(err error, args ...any) { if err == nil { return } @@ -15,7 +15,7 @@ func Must(err error, args ...interface{}) { must(err, args...) } -func MustFn(errFn func() error, args ...interface{}) { +func MustFn(errFn func() error, args ...any) { err := try(errFn) if err == nil { return @@ -24,7 +24,7 @@ func MustFn(errFn func() error, args ...interface{}) { must(err, args...) } -func MustF(err error, msg string, args ...interface{}) { +func MustF(err error, msg string, args ...any) { if err == nil { return } @@ -32,48 +32,48 @@ func MustF(err error, msg string, args ...interface{}) { must(err, fmt.Sprintf(msg, args...)) } -func Must1[T any](ret T, err error, args ...any) T { +func Must1[T any](ret T, err error) T { if err != nil { - must(err, args...) + must(err) } return ret } -func Exit(err error, args ...interface{}) { +func Exit(err error, args ...any) { if err == nil { return } - slog.Error("os exit with error", "err", err, "msg", fmt.Sprint(args...)) + logErr(err, "os exit with error", slog.String("log-msg", fmt.Sprint(args...))) debug.PrintStack() os.Exit(1) } -func ExitFn(errFn func() error, args ...interface{}) { +func ExitFn(errFn func() error, args ...any) { err := try(errFn) if err == nil { return } - slog.Error("os exit with error func", "err", err, "msg", fmt.Sprint(args...)) + logErr(err, "os exit with error func", slog.String("log-msg", fmt.Sprint(args...))) debug.PrintStack() os.Exit(1) } -func ExitF(err error, msg string, args ...interface{}) { +func ExitF(err error, msg string, args ...any) { if err == nil { return } - slog.Error("os exit with error format", "err", err, "msg", fmt.Sprintf(msg, args...)) + logErr(err, "os exit with error format", slog.String("log-msg", fmt.Sprintf(msg, args...))) debug.PrintStack() os.Exit(1) } func Exit1[T any](ret T, err error) T { if err != nil { - slog.Error("os exit with error unwrap", "err", err) + logErr(err, "os exit with error unwrap") debug.PrintStack() os.Exit(1) } diff --git a/assert/must_test.go b/assert/must_test.go index 7eea19d6..56936741 100644 --- a/assert/must_test.go +++ b/assert/must_test.go @@ -2,13 +2,20 @@ package assert_test import ( "fmt" + "log/slog" "testing" - assert1 "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" "github.com/stretchr/testify/assert" + + assert1 "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" ) +func init() { + slog.SetDefault(slog.New(log.NewSlog(log.GetLogger(assert1.Name)))) +} + type errBase struct { msg string } @@ -50,11 +57,16 @@ func init1Next() (err error) { return nil } +func TestDebugMode(t *testing.T) { + assert1.Exit(assert1.FeatureDebugMode.Set("true")) + assert1.Must(fmt.Errorf("test next")) +} + func BenchmarkNoPanic(b *testing.B) { for i := 0; i < b.N; i++ { _ = func() (err error) { assert1.Must(nil) - return + return err }() } } diff --git a/assert/util.go b/assert/util.go index 6db7507b..749c6d18 100644 --- a/assert/util.go +++ b/assert/util.go @@ -3,9 +3,17 @@ package assert import ( "fmt" "log/slog" + "reflect" "runtime/debug" + "sync" - "github.com/pubgo/funk/stack" + "github.com/k0kubun/pp/v3" + "github.com/samber/lo" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" + + "github.com/pubgo/funk/v2/log/logfields" + "github.com/pubgo/funk/v2/stack" ) func messageFromMsgAndArgs(msgAndArgs ...any) string { @@ -17,10 +25,28 @@ func messageFromMsgAndArgs(msgAndArgs ...any) string { if msgAsStr, ok := msgAndArgs[0].(string); ok { return msgAsStr } - return fmt.Sprintf("%+v", msgAndArgs[0]) } - return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + return pretty().Sprint(msgAndArgs...) +} + +var assetFile = stack.Caller(0) + +func logErr(err error, message string, attrs ...slog.Attr) { + if err == nil { + return + } + + traces := lo.Filter(stack.Trace(), func(item *stack.Frame, index int) bool { + return !item.IsRuntime() && item.Pkg != assetFile.Pkg + }) + attrs = append(attrs, + slog.String(logfields.Module, Name), + slog.String(logfields.Error, err.Error()), + slog.Any(logfields.ErrorStack, lo.Map(traces, func(item *stack.Frame, index int) string { return item.String() })), + slog.String(logfields.ErrorDetail, fmt.Sprintf("%v", err)), + ) + slog.Error(message, lo.ToAnySlice(attrs)...) } func must(err error, messageArgs ...any) { @@ -28,39 +54,67 @@ func must(err error, messageArgs ...any) { return } + attrs := []slog.Attr{slog.Bool("panic", true)} + if v, ok := lo.ErrorsAs[interface { + ID() string + Error() string + }](err); ok && v != nil { + attrs = append(attrs, slog.String(logfields.ErrorID, v.ID())) + } + message := messageFromMsgAndArgs(messageArgs...) if message == "" { - message = err.Error() + if v, ok := lo.ErrorsAs[interface { + Proto() proto.Message + Error() string + }](err); ok && v != nil { + message = fmt.Sprintf("%s\n%s", err.Error(), prototext.Format(v.Proto())) + } else { + message = err.Error() + } } else { - message = fmt.Sprintf("msg:%s err:%s", message, err.Error()) + message = fmt.Sprintf("msg:%v err:%s", message, err.Error()) } - if EnablePrintStack { - slog.Error(message) + logErr(err, message, attrs...) + + if FeatureDebugMode.GetValue() { + _, _ = pp.Println(err) debug.PrintStack() } - panic(message) + panic(err) } +var pretty = sync.OnceValue(func() *pp.PrettyPrinter { + printer := pp.New() + printer.SetColoringEnabled(false) + printer.SetExportedOnly(false) + printer.SetOmitEmpty(true) + printer.SetMaxDepth(5) + return printer +}) + func try(fn func() error) (gErr error) { if fn == nil { - gErr = fmt.Errorf("[fn] is nil") - return + gErr = fmt.Errorf("assert: [fn] is nil") + logErr(gErr, gErr.Error()) + debug.PrintStack() + return gErr } - defer func() { - if gErr != nil { - gErr = fmt.Errorf("stack:%s, err:%w", stack.CallerWithFunc(fn).String(), gErr) - } - }() - defer func() { if err := recover(); err != nil { gErr = fmt.Errorf("%v", err) + logErr(gErr, gErr.Error()) + debug.PrintStack() + } + + if gErr != nil { + gErr = fmt.Errorf("stack:%s, err:%w", reflect.TypeOf(fn).String(), gErr) } }() gErr = fn() - return + return gErr } diff --git a/async/base.go b/async/base.go index 1afc19a8..1b976740 100644 --- a/async/base.go +++ b/async/base.go @@ -1,6 +1,6 @@ package async -import "github.com/pubgo/funk/log" +import "github.com/pubgo/funk/v2/log" const Name = "async" diff --git a/async/base_test.go b/async/base_test.go index 36445ec1..d6c5f06d 100644 --- a/async/base_test.go +++ b/async/base_test.go @@ -3,7 +3,7 @@ package async import ( "testing" - "github.com/pubgo/funk/log" + "github.com/pubgo/funk/v2/log" ) func TestLogger(t *testing.T) { diff --git a/async/future.go b/async/future.go index f30fbb58..d6f7e702 100644 --- a/async/future.go +++ b/async/future.go @@ -1,7 +1,7 @@ package async import ( - "github.com/pubgo/funk/result" + "github.com/pubgo/funk/v2/result" ) func newFuture[T any]() *Future[T] { diff --git a/async/go.go b/async/go.go index 455bfe3f..71da5640 100644 --- a/async/go.go +++ b/async/go.go @@ -6,13 +6,13 @@ import ( "runtime/debug" "time" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/recovery" - "github.com/pubgo/funk/running" - "github.com/pubgo/funk/stack" - "github.com/pubgo/funk/try" + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/recovery" + "github.com/pubgo/funk/v2/running" + "github.com/pubgo/funk/v2/stack" + "github.com/pubgo/funk/v2/try" ) // Async 异步执行函数并同步等待 @@ -46,7 +46,7 @@ func GoSafe(fn func() error, cb ...func(err error)) { go func() { err := try.Try(fn) - if generic.IsNil(err) { + if funk.IsNil(err) { return } @@ -119,12 +119,12 @@ func Timeout(dur time.Duration, fn func() error) error { } } -func logErr(fn interface{}, err error) { - if generic.IsNil(err) { +func logErr(fn any, err error) { + if funk.IsNil(err) { return } - if running.IsDebug { + if running.Debug() { debug.PrintStack() errors.Debug(err) } diff --git a/async/go_test.go b/async/go_test.go index 09f65c82..0e9ff345 100644 --- a/async/go_test.go +++ b/async/go_test.go @@ -13,8 +13,8 @@ func TestAsync(t *testing.T) { ret := Async(func() (*http.Response, error) { //nolint return http.Get("https://httpbin.org") }).Await() - assert.NoError(t, ret.Err()) - rsp := ret.Unwrap() + assert.NoError(t, ret.GetErr()) + rsp := ret.Must() if b := rsp.Body; b != nil { defer b.Close() } @@ -36,9 +36,9 @@ func TestGoChan(t *testing.T) { val2 := Async(func() (string, error) { time.Sleep(time.Millisecond * 10) fmt.Println("2") - ret := val1.Await().Unwrap() + ret := val1.Await().Must() return ret + " hello2", nil }) - assert.Equal(t, "hello1 hello2", val2.Await().Unwrap()) + assert.Equal(t, "hello1 hello2", val2.Await().Must()) } diff --git a/async/iterator.go b/async/iterator.go index d3d39ebd..b97b3237 100644 --- a/async/iterator.go +++ b/async/iterator.go @@ -1,7 +1,7 @@ package async import ( - "github.com/pubgo/funk/result" + "github.com/pubgo/funk/v2/result" ) func iteratorOf[T any]() *Iterator[T] { diff --git a/async/promise.go b/async/promise.go index 56bed6bc..d857f255 100644 --- a/async/promise.go +++ b/async/promise.go @@ -3,10 +3,10 @@ package async import ( "sync" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/recovery" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/recovery" + "github.com/pubgo/funk/v2/stack" ) func Promise[T any](fn func(resolve func(T), reject func(err error))) *Future[T] { diff --git a/async/promise_test.go b/async/promise_test.go index 390e5aca..cdb2d4b5 100644 --- a/async/promise_test.go +++ b/async/promise_test.go @@ -16,7 +16,7 @@ func TestPromise(t *testing.T) { resolve("ok") }) - assert.Equal(t, future.Await().Unwrap(), "ok") + assert.Equal(t, future.Await().Must(), "ok") }) t.Run("err", func(t *testing.T) { @@ -26,7 +26,7 @@ func TestPromise(t *testing.T) { reject(err) }) - assert.Equal(t, future.Await().Err(), err) + assert.Equal(t, future.Await().GetErr(), err) }) } @@ -38,7 +38,7 @@ func TestYield(t *testing.T) { yield(3) return nil }) - assert.Equal(t, iter.Await().Unwrap(), []int{1, 2, 3}) + assert.Equal(t, iter.Await().Must(), []int{1, 2, 3}) }) err := fmt.Errorf("test error") @@ -49,7 +49,7 @@ func TestYield(t *testing.T) { yield(3) return err }) - assert.Equal(t, iter.Await().Err(), err) + assert.Equal(t, iter.Await().GetErr(), err) }) } @@ -60,10 +60,10 @@ func TestGroup(t *testing.T) { }() rsp := httpGetList().Await() - assert.NoError(t, rsp.Err()) - assert.Equal(t, len(rsp.Unwrap()), 10) + assert.NoError(t, rsp.GetErr()) + assert.Equal(t, len(rsp.Must()), 10) - data := rsp.Unwrap() + data := rsp.Must() sort.Ints(data) assert.Equal(t, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, data) } diff --git a/buildinfo/build.go b/buildinfo/build.go new file mode 100644 index 00000000..464d23cb --- /dev/null +++ b/buildinfo/build.go @@ -0,0 +1,29 @@ +package buildinfo + +var ( + domain string + mainPath string +) + +// git rev-parse HEAD +// git describe --always --abbrev=7 --dirty +var ( + // commitID, git commit id + commitID string + + // buildTime, build time, rfc3339 + buildTime string +) + +// git describe --tags --abbrev=0 +// git tag --sort=committerdate | tail -n 1 +var ( + // version, git tag + version string + + // project, project name + project string +) + +// release tag +var release string diff --git a/buildinfo/version.go b/buildinfo/version.go new file mode 100644 index 00000000..30fd2e23 --- /dev/null +++ b/buildinfo/version.go @@ -0,0 +1,65 @@ +package buildinfo + +import ( + "runtime/debug" + "strings" + "time" + + "github.com/samber/lo" + "golang.org/x/mod/module" + + v "github.com/pubgo/funk/v2/buildinfo/version" +) + +func init() { + bi, ok := debug.ReadBuildInfo() + if !ok { + return + } + + mainPath = bi.Main.Path + if project == "" { + project = lo.LastOrEmpty(strings.Split(mainPath, "/")) + } + + if version == "" { + version = bi.Main.Version + } + + if module.IsPseudoVersion(bi.Main.Version) { + ver := bi.Main.Version + if a, err := module.PseudoVersionTime(ver); err == nil { + buildTime = a.Format(time.RFC3339) + } + + if b, err := module.PseudoVersionRev(ver); err == nil { + commitID = b + } + + if c, err := module.PseudoVersionBase(ver); err == nil { + version = c + } + } + + if version == "" { + version = "v0.0.1-dev-99" + } + + for i := range bi.Settings { + setting := bi.Settings[i] + switch setting.Key { + case "vcs.revision": + commitID = setting.Value + case "vcs.time": + buildTime = setting.Value + } + } + + _ = v.SetBuildTime(buildTime) + _ = v.SetCommitID(commitID) + _ = v.SetProject(project) + _ = v.SetReleaseVersion(release) + _ = v.SetMainPath(mainPath) + _ = v.SetVersion(version) + _ = v.SetDomain(domain) +} diff --git a/buildinfo/version/version.go b/buildinfo/version/version.go new file mode 100644 index 00000000..7366a4d4 --- /dev/null +++ b/buildinfo/version/version.go @@ -0,0 +1,70 @@ +package version + +import "github.com/pubgo/funk/v2" + +var ( + mainPath string + domain string + commitID string + buildTime string + version string + project string + release string +) + +func CommitID() string { return commitID } +func MainPath() string { return mainPath } +func Version() string { return version } +func ReleaseVersion() string { return release } +func BuildTime() string { return buildTime } +func Project() string { return project } +func Domain() string { return domain } + +func SetCommitID(id string) funk.Void { + if id != "" { + commitID = id + } + return funk.Void{} +} + +func SetMainPath(path string) funk.Void { + if path != "" { + mainPath = path + } + return funk.Void{} +} + +func SetVersion(v string) funk.Void { + if v != "" { + version = v + } + return funk.Void{} +} + +func SetReleaseVersion(r string) funk.Void { + if r != "" { + release = r + } + return funk.Void{} +} + +func SetBuildTime(t string) funk.Void { + if t != "" { + buildTime = t + } + return funk.Void{} +} + +func SetProject(p string) funk.Void { + if p != "" { + project = p + } + return funk.Void{} +} + +func SetDomain(d string) funk.Void { + if d != "" { + domain = d + } + return funk.Void{} +} diff --git a/buildinfo/version_test.go b/buildinfo/version_test.go new file mode 100644 index 00000000..c5ca7be1 --- /dev/null +++ b/buildinfo/version_test.go @@ -0,0 +1,26 @@ +package buildinfo_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "golang.org/x/mod/module" +) + +func TestVersion(t *testing.T) { + ver := "v0.0.8-0.20251008154318-d8a2f764dac7+dirty" + assert.True(t, module.IsPseudoVersion(ver)) + + a, err := module.PseudoVersionTime(ver) + assert.NoError(t, err) + assert.Equal(t, "2025-10-08 15:43:18", a.Format(time.DateTime)) + + b, err := module.PseudoVersionRev(ver) + assert.NoError(t, err) + assert.Equal(t, "d8a2f764dac7", b) + + c, err := module.PseudoVersionBase(ver) + assert.NoError(t, err) + assert.Equal(t, "v0.0.7+dirty", c) +} diff --git a/cmds/configcmd/cmd.go b/cmds/configcmd/cmd.go index 8ff03fa1..18d180ab 100644 --- a/cmds/configcmd/cmd.go +++ b/cmds/configcmd/cmd.go @@ -5,11 +5,11 @@ import ( "fmt" "github.com/urfave/cli/v3" - "gopkg.in/yaml.v3" + yaml "gopkg.in/yaml.v3" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/recovery" ) func New[Cfg any]() *cli.Command { diff --git a/cmds/ent/main1.go b/cmds/ent/main1.go index 8c15c01d..1ff50597 100644 --- a/cmds/ent/main1.go +++ b/cmds/ent/main1.go @@ -13,7 +13,7 @@ import ( "entgo.io/ent/dialect/sql/schema" "entgo.io/ent/entc" "entgo.io/ent/entc/gen" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/recovery" // https://github.com/ent/ent/blob/master/cmd/internal/base/base.go ) diff --git a/cmds/envcmd/cmd.go b/cmds/envcmd/cmd.go index 4e192833..7abc58b8 100644 --- a/cmds/envcmd/cmd.go +++ b/cmds/envcmd/cmd.go @@ -6,10 +6,10 @@ import ( "github.com/urfave/cli/v3" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/env" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/env" + "github.com/pubgo/funk/v2/pretty" + "github.com/pubgo/funk/v2/recovery" ) func New() *cli.Command { @@ -22,7 +22,7 @@ func New() *cli.Command { env.Reload() fmt.Println("config path:", config.GetConfigPath()) - envs := config.LoadEnvConfigMap(config.GetConfigPath()) + envs := config.LoadEnvMap(config.GetConfigPath()) for name, cfg := range envs { envData := env.Get(name) if envData != "" { diff --git a/cmds/protoc-gen-go-cloudevent/internal/gen.go b/cmds/protoc-gen-go-cloudevent2/internal/gen.go similarity index 84% rename from cmds/protoc-gen-go-cloudevent/internal/gen.go rename to cmds/protoc-gen-go-cloudevent2/internal/gen.go index 93de8fec..b0969ea5 100644 --- a/cmds/protoc-gen-go-cloudevent/internal/gen.go +++ b/cmds/protoc-gen-go-cloudevent2/internal/gen.go @@ -13,19 +13,19 @@ import ( "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/component/cloudevent" - "github.com/pubgo/funk/errors/errcheck" - cloudeventpb "github.com/pubgo/funk/proto/cloudevent" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/component/cloudevent" + cloudeventpb "github.com/pubgo/funk/v2/proto/cloudevent" + "github.com/pubgo/funk/v2/stack" ) -var cloudeventPkg = reflect.TypeOf(cloudevent.Client{}).PkgPath() -var jobTypesPkg = reflect.TypeOf(cloudeventpb.PushEventOptions{}).PkgPath() -var resultTypesPkg = stack.CallerWithFunc(errcheck.Check).Pkg -var ctxPkg = stack.CallerWithFunc(context.WithTimeout).Pkg -var assertPkt = stack.CallerWithFunc(assert.Assert).Pkg -var protojsonPkt = stack.CallerWithFunc(protojson.Marshal).Pkg +var ( + cloudeventPkg = reflect.TypeOf(cloudevent.Client{}).PkgPath() + jobTypesPkg = reflect.TypeOf(cloudeventpb.PushEventOptions{}).PkgPath() + ctxPkg = stack.CallerWithFunc(context.WithTimeout).Pkg + assertPkt = stack.CallerWithFunc(assert.Assert).Pkg + protojsonPkt = stack.CallerWithFunc(protojson.Marshal).Pkg +) type eventInfo struct { srv *protogen.Service @@ -56,7 +56,7 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated return g } - var events = make(map[string]map[string]*eventInfo) + events := make(map[string]map[string]*eventInfo) for _, srv := range file.Services { job, ok := proto.GetExtension(srv.Desc.Options(), cloudeventpb.E_Job).(*cloudeventpb.CloudEventServiceOptions) if !ok || job == nil { @@ -120,7 +120,7 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated for _, subName := range subjectNames { info := subjects[subName] - var keyName = fmt.Sprintf("%sCloudEventKey", info.mth.GoName) + keyName := fmt.Sprintf("%sCloudEventKey", info.mth.GoName) genFile.Commentf("%s /%s/%s", keyName, info.srv.Desc.FullName(), info.mth.GoName) genFile.Comment(strings.TrimSpace(info.mth.Comments.Leading.String())) genFile.Const(). @@ -149,7 +149,7 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated //} subjectValues := lo.Values(subjects) - var cloudEventName = fmt.Sprintf("%sCloudEvent", subjectValues[0].srv.GoName) + cloudEventName := fmt.Sprintf("%sCloudEvent", subjectValues[0].srv.GoName) genFile.Type().Id(cloudEventName).StructFunc(func(group *jen.Group) { for _, ss := range subjectValues { group.Id("On"+ss.mth.GoName).Func().Params( @@ -167,27 +167,27 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated jen.Id("opts").Op("...").Op("*").Qual(jobTypesPkg, "RegisterJobOptions"), ).BlockFunc(func(group *jen.Group) { for _, ss := range subjectValues { - var keyName = fmt.Sprintf("%sCloudEventKey", ss.mth.GoName) + keyName := fmt.Sprintf("%sCloudEventKey", ss.mth.GoName) group.If(jen.Id("event").Dot("On" + ss.mth.GoName)).Op("!=").Nil().BlockFunc(func(group *jen.Group) { group.Qual(cloudeventPkg, "RegisterJobHandler").Call( jen.Id("jobCli"), jen.Id(jobKeyName), jen.Id(keyName), jen.Id("event").Dot("On"+ss.mth.GoName), - //jen.Qual(cloudeventPkg, "WrapHandler").Call(jen.Id("event").Dot(ss.mth.GoName)), + // jen.Qual(cloudeventPkg, "WrapHandler").Call(jen.Id("event").Dot(ss.mth.GoName)), jen.Id("opts").Op("..."), ) }).Line() } }) - var publisher = fmt.Sprintf("%sPublisher", cloudEventName) + publisher := fmt.Sprintf("%sPublisher", cloudEventName) genFile.Type().Id(publisher).StructFunc(func(group *jen.Group) { group.Id("Client").Op("*").Qual(cloudeventPkg, "Client") }) for _, ss := range subjectValues { - var mthName = fmt.Sprintf("Push%sEvent", ss.mth.GoName) - var keyName = fmt.Sprintf("%sCloudEventKey", ss.mth.GoName) + mthName := fmt.Sprintf("Push%sEvent", ss.mth.GoName) + keyName := fmt.Sprintf("%sCloudEventKey", ss.mth.GoName) genFile.Func(). Params(jen.Id(fmt.Sprintf("a %s", publisher))). Id(mthName). @@ -225,7 +225,7 @@ func getSrv(data map[string]*eventInfo) *protogen.Service { } func getPkg(file *protogen.File, goIdent protogen.GoIdent) *jen.Statement { - var pkgName = "" + pkgName := "" if file.GoImportPath != goIdent.GoImportPath { pkgName = string(goIdent.GoImportPath) } diff --git a/cmds/protoc-gen-go-cloudevent/internal/version.go b/cmds/protoc-gen-go-cloudevent2/internal/version.go similarity index 100% rename from cmds/protoc-gen-go-cloudevent/internal/version.go rename to cmds/protoc-gen-go-cloudevent2/internal/version.go diff --git a/cmds/protoc-gen-go-cloudevent/main.go b/cmds/protoc-gen-go-cloudevent2/main.go similarity index 89% rename from cmds/protoc-gen-go-cloudevent/main.go rename to cmds/protoc-gen-go-cloudevent2/main.go index 8dfcb72a..8c8a7525 100644 --- a/cmds/protoc-gen-go-cloudevent/main.go +++ b/cmds/protoc-gen-go-cloudevent2/main.go @@ -3,7 +3,7 @@ package main import ( "flag" - "github.com/pubgo/funk/cmds/protoc-gen-go-cloudevent/internal" + "github.com/pubgo/funk/v2/cmds/protoc-gen-go-cloudevent2/internal" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/pluginpb" ) diff --git a/cmds/protoc-gen-go-enum/internal/gen.go b/cmds/protoc-gen-go-enum2/internal/gen.go similarity index 100% rename from cmds/protoc-gen-go-enum/internal/gen.go rename to cmds/protoc-gen-go-enum2/internal/gen.go diff --git a/cmds/protoc-gen-go-enum/internal/version.go b/cmds/protoc-gen-go-enum2/internal/version.go similarity index 100% rename from cmds/protoc-gen-go-enum/internal/version.go rename to cmds/protoc-gen-go-enum2/internal/version.go diff --git a/cmds/protoc-gen-go-enum/main.go b/cmds/protoc-gen-go-enum2/main.go similarity index 86% rename from cmds/protoc-gen-go-enum/main.go rename to cmds/protoc-gen-go-enum2/main.go index 6c8b0a48..2be4d1c1 100644 --- a/cmds/protoc-gen-go-enum/main.go +++ b/cmds/protoc-gen-go-enum2/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/pubgo/funk/cmds/protoc-gen-go-enum/internal" + "github.com/pubgo/funk/v2/cmds/protoc-gen-go-enum2/internal" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/pluginpb" ) diff --git a/cmds/protoc-gen-go-errors/internal/version.go b/cmds/protoc-gen-go-errors/internal/version.go deleted file mode 100644 index 7ec42e5c..00000000 --- a/cmds/protoc-gen-go-errors/internal/version.go +++ /dev/null @@ -1,3 +0,0 @@ -package internal - -const version = "v0.0.7" diff --git a/cmds/protoc-gen-go-errors/internal/gen.go b/cmds/protoc-gen-go-errors2/internal/gen.go similarity index 84% rename from cmds/protoc-gen-go-errors/internal/gen.go rename to cmds/protoc-gen-go-errors2/internal/gen.go index 506e8a53..2a641f2f 100644 --- a/cmds/protoc-gen-go-errors/internal/gen.go +++ b/cmds/protoc-gen-go-errors2/internal/gen.go @@ -6,12 +6,18 @@ import ( "github.com/dave/jennifer/jen" "github.com/iancoleman/strcase" - "github.com/pubgo/funk/proto/errorpb" + "github.com/pubgo/funk/v2/proto/errorpb" + "github.com/samber/lo" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/proto" ) -const errorPbPkg = "github.com/pubgo/funk/proto/errorpb" +const errorPbPkg = "github.com/pubgo/funk/v2/proto/errorpb" + +var ( + registerErrCodes = lo.T2("github.com/pubgo/funk/v2/errors/errorcodes", "RegisterErrCodes") + supportPackageIsVersion7 = lo.T2("google.golang.org/grpc", "SupportPackageIsVersion7") +) // GenerateFile generates a .errors.pb.go file containing service definitions. func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile { @@ -19,9 +25,9 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated g := gen.NewGeneratedFile(filename, file.GoImportPath) genFile := jen.NewFile(string(file.GoPackageName)) - genFile.HeaderComment("Code generated by protoc-gen-go-errors. DO NOT EDIT.") + genFile.HeaderComment("Code generated by protoc-gen-go-errors2. DO NOT EDIT.") genFile.HeaderComment("versions:") - genFile.HeaderComment(fmt.Sprintf("- protoc-gen-go-errors %s", version)) + genFile.HeaderComment(fmt.Sprintf("- protoc-gen-go-errors2 %s", version)) genFile.HeaderComment(fmt.Sprintf("- protoc %s", protocVersion(gen))) if file.Proto.GetOptions().GetDeprecated() { genFile.HeaderComment(fmt.Sprintf("%s is a deprecated file.", file.Desc.Path())) @@ -32,7 +38,7 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated genFile.Comment("This is a compile-time assertion to ensure that this generated file") genFile.Comment("is compatible with the grpc package it is being compiled against.") genFile.Comment("Requires gRPC-Go v1.32.0 or later.") - genFile.Id("const _ =").Qual("google.golang.org/grpc", "SupportPackageIsVersion7") + genFile.Id("const _ =").Qual(supportPackageIsVersion7.Unpack()) g.Skip() for i := range file.Enums { @@ -93,7 +99,7 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated jen.Id("Message"): jen.Lit(rr), }) genFile.Var().Id("_").Op("="). - Qual("github.com/pubgo/funk/errors", "RegisterErrCodes"). + Qual(registerErrCodes.Unpack()). Call(jen.Id(errCodeName)).Line() } } diff --git a/cmds/protoc-gen-go-errors2/internal/version.go b/cmds/protoc-gen-go-errors2/internal/version.go new file mode 100644 index 00000000..0b104a4e --- /dev/null +++ b/cmds/protoc-gen-go-errors2/internal/version.go @@ -0,0 +1,3 @@ +package internal + +const version = "v0.0.8" diff --git a/cmds/protoc-gen-go-errors/main.go b/cmds/protoc-gen-go-errors2/main.go similarity index 86% rename from cmds/protoc-gen-go-errors/main.go rename to cmds/protoc-gen-go-errors2/main.go index 8088a784..be269c4c 100644 --- a/cmds/protoc-gen-go-errors/main.go +++ b/cmds/protoc-gen-go-errors2/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/pubgo/funk/cmds/protoc-gen-go-errors/internal" + "github.com/pubgo/funk/v2/cmds/protoc-gen-go-errors2/internal" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/pluginpb" ) diff --git a/cmds/protoc-gen-go-sql/internal/gen.go b/cmds/protoc-gen-go-sql2/internal/gen.go similarity index 100% rename from cmds/protoc-gen-go-sql/internal/gen.go rename to cmds/protoc-gen-go-sql2/internal/gen.go diff --git a/cmds/protoc-gen-go-sql/internal/version.go b/cmds/protoc-gen-go-sql2/internal/version.go similarity index 100% rename from cmds/protoc-gen-go-sql/internal/version.go rename to cmds/protoc-gen-go-sql2/internal/version.go diff --git a/cmds/protoc-gen-go-sql/main.go b/cmds/protoc-gen-go-sql2/main.go similarity index 87% rename from cmds/protoc-gen-go-sql/main.go rename to cmds/protoc-gen-go-sql2/main.go index 236c99b7..0566e47d 100644 --- a/cmds/protoc-gen-go-sql/main.go +++ b/cmds/protoc-gen-go-sql2/main.go @@ -4,7 +4,7 @@ import ( "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/pluginpb" - "github.com/pubgo/funk/cmds/protoc-gen-go-sql/internal" + "github.com/pubgo/funk/v2/cmds/protoc-gen-go-sql2/internal" ) func main() { diff --git a/cmds/testmain/main.go b/cmds/testmain/main.go index ff3b9fb9..a1e83219 100644 --- a/cmds/testmain/main.go +++ b/cmds/testmain/main.go @@ -7,12 +7,13 @@ import ( "sort" "github.com/moby/term" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/cliutils" - "github.com/pubgo/funk/cmds/versioncmd" - "github.com/pubgo/funk/ctxutil" - "github.com/pubgo/funk/version" "github.com/urfave/cli/v3" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/buildinfo/version" + "github.com/pubgo/funk/v2/cliutils" + "github.com/pubgo/funk/v2/cmds/versioncmd" + "github.com/pubgo/funk/v2/ctxutil" ) func main() { diff --git a/cmds/versioncmd/cmd.go b/cmds/versioncmd/cmd.go index dfceabfe..5992be4c 100644 --- a/cmds/versioncmd/cmd.go +++ b/cmds/versioncmd/cmd.go @@ -4,12 +4,11 @@ import ( "context" "fmt" + "github.com/pubgo/funk/v2/buildinfo/version" + "github.com/pubgo/funk/v2/pretty" + "github.com/pubgo/funk/v2/recovery" + "github.com/pubgo/funk/v2/running" "github.com/urfave/cli/v3" - - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/recovery" - "github.com/pubgo/funk/running" - "github.com/pubgo/funk/version" ) func New() *cli.Command { diff --git a/cmux/mux.go b/cmux/mux.go index 43535749..d01672e4 100644 --- a/cmux/mux.go +++ b/cmux/mux.go @@ -7,8 +7,8 @@ package cmux // "os" // "strings" // -// "github.com/pubgo/funk/config" -// "github.com/pubgo/funk/log" +// "github.com/pubgo/funk/v2/config" +// "github.com/pubgo/funk/v2/log" // "github.com/soheilhy/cmux" // "github.com/tmc/grpc-websocket-proxy/wsproxy" // clientv3 "go.etcd.io/etcd/client/v3" diff --git a/component/bbolt/client.go b/component/bbolt/client.go index f8e33e45..14e27646 100644 --- a/component/bbolt/client.go +++ b/component/bbolt/client.go @@ -4,20 +4,21 @@ import ( "context" "path/filepath" + result2 "github.com/pubgo/funk/v2/result" + bolt "go.etcd.io/bbolt" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/merge" - "github.com/pubgo/funk/pathutil" - "github.com/pubgo/funk/strutil" - "github.com/pubgo/funk/v2/result" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/merge" + "github.com/pubgo/funk/v2/pathutil" + "github.com/pubgo/funk/v2/strutil" ) func New(cfg *Config, log log.Logger) *Client { - cfg = merge.Copy(DefaultConfig(), cfg).Unwrap() + cfg = merge.Copy(DefaultConfig(), cfg).Must() path := filepath.Join(config.GetConfigDir(), cfg.Path) assert.Must(pathutil.IsNotExistMkDir(filepath.Dir(path))) @@ -46,7 +47,7 @@ func (t *Client) Set(ctx context.Context, key string, val []byte, names ...strin }, names...) } -func (t *Client) Get(ctx context.Context, key string, names ...string) result.Result[[]byte] { +func (t *Client) Get(ctx context.Context, key string, names ...string) result2.Result[[]byte] { var ( val []byte err = t.View(ctx, func(bucket *bolt.Bucket) error { @@ -55,7 +56,7 @@ func (t *Client) Get(ctx context.Context, key string, names ...string) result.Re }, names...) ) - return result.Wrap(val, err) + return result2.Wrap(val, err) } func (t *Client) List(ctx context.Context, fn func(k, v []byte) error, names ...string) error { diff --git a/component/bbolt/config.go b/component/bbolt/config.go index d7002128..2257370d 100644 --- a/component/bbolt/config.go +++ b/component/bbolt/config.go @@ -4,8 +4,9 @@ import ( "io/fs" "time" - "github.com/pubgo/funk/merge" bolt "go.etcd.io/bbolt" + + "github.com/pubgo/funk/v2/merge" ) const Name = "bolt" @@ -27,7 +28,7 @@ type Config struct { func (t *Config) getOpts() *bolt.Options { options := bolt.DefaultOptions options.Timeout = time.Second * 2 - return merge.Struct(options, t).Unwrap() + return merge.Struct(options, t).Must() } func DefaultConfig() *Config { diff --git a/component/cloudevent/aaa.go b/component/cloudevent/aaa.go index 53796133..b4416600 100644 --- a/component/cloudevent/aaa.go +++ b/component/cloudevent/aaa.go @@ -5,10 +5,11 @@ import ( "github.com/nats-io/nats.go" "github.com/nats-io/nats.go/jetstream" - "github.com/pubgo/funk/log" - cloudeventpb "github.com/pubgo/funk/proto/cloudevent" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/emptypb" + + "github.com/pubgo/funk/v2/log" + cloudeventpb "github.com/pubgo/funk/v2/proto/cloudevent" ) var logger = log.GetLogger("cloudevent") @@ -17,8 +18,10 @@ type EventRegister interface { RegisterCloudEvent(jobCli *Client) } -type EventHandler[T proto.Message] func(ctx context.Context, args T) error -type RpcEventHandler[T proto.Message] func(ctx context.Context, args T) (*emptypb.Empty, error) +type ( + EventHandler[T proto.Message] func(ctx context.Context, args T) error + RpcEventHandler[T proto.Message] func(ctx context.Context, args T) (*emptypb.Empty, error) +) type Options = cloudeventpb.PushEventOptions diff --git a/component/cloudevent/client.go b/component/cloudevent/client.go index b3aeab86..89b50613 100644 --- a/component/cloudevent/client.go +++ b/component/cloudevent/client.go @@ -10,23 +10,24 @@ import ( mapset "github.com/deckarep/golang-set/v2" "github.com/nats-io/nats.go/jetstream" ants "github.com/panjf2000/ants/v2" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/component/lifecycle" - "github.com/pubgo/funk/component/natsclient" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/errors/errcheck" - "github.com/pubgo/funk/internal/anyhow" - "github.com/pubgo/funk/log" - cloudeventpb "github.com/pubgo/funk/proto/cloudevent" - "github.com/pubgo/funk/running" - "github.com/pubgo/funk/stack" - "github.com/pubgo/funk/try" - "github.com/pubgo/funk/typex" - "github.com/pubgo/funk/version" "github.com/rs/zerolog" "github.com/samber/lo" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/buildinfo/version" + "github.com/pubgo/funk/v2/component/lifecycle" + "github.com/pubgo/funk/v2/component/natsclient" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/log/logfields" + cloudeventpb "github.com/pubgo/funk/v2/proto/cloudevent" + "github.com/pubgo/funk/v2/result" + "github.com/pubgo/funk/v2/running" + "github.com/pubgo/funk/v2/stack" + "github.com/pubgo/funk/v2/try" + "github.com/pubgo/funk/v2/typex" ) type Params struct { @@ -73,7 +74,7 @@ type Client struct { } func (c *Client) initStream() (r error) { - defer errcheck.RecoveryAndCheck(&r) + defer result.RecoveryErr(&r) ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout) defer cancel() @@ -91,27 +92,23 @@ func (c *Client) initStream() (r error) { Subjects: streamSubjects, Metadata: metadata, Storage: storageType, - //Retention: jetstream.InterestPolicy, + // Retention: jetstream.InterestPolicy, // Duplicates is the window within which to track duplicate messages. // If not set, server default is 2 minutes. Duplicates: time.Minute * 5, } - stream, err := c.js.CreateOrUpdateStream(ctx, streamCfg) - err = errors.IfErr(err, func(err error) error { - return errors.Wrapf(err, "failed to create stream:%s", streamName) + stream := result.Wrap(c.js.CreateOrUpdateStream(ctx, streamCfg)).Must(func(e *zerolog.Event) { + e.Str(logfields.Msg, fmt.Sprintf("failed to create stream:%s", streamName)) }) - if errcheck.Check(&r, err) { - return - } c.streams[streamName] = stream } - return + return r } func (c *Client) initConsumer() (r error) { - defer errcheck.RecoveryAndCheck(&r) + defer result.RecoveryErr(&r) allEventKeysSet := mapset.NewSet(lo.MapToSlice(c.subjects, func(key string, value *cloudeventpb.CloudEventMethodOptions) string { return c.subjectName(key) })...) @@ -198,13 +195,13 @@ func (c *Client) initConsumer() (r error) { }) } } - return + return r } func (c *Client) doConsumeHandler(streamName, consumerName string, jobSubjects map[string]*jobEventHandler, concurrent int) func(msg jetstream.Msg) { - var handler = func(msg jetstream.Msg) { - var now = time.Now() - var addMsgInfo = func(e *zerolog.Event) { + handler := func(msg jetstream.Msg) { + now := time.Now() + addMsgInfo := func(e *zerolog.Event) { e.Str("stream", streamName) e.Str("consumer", consumerName) e.Any("header", msg.Headers()) @@ -219,7 +216,7 @@ func (c *Client) doConsumeHandler(streamName, consumerName string, jobSubjects m e.Msg("received cloud job event") }) - var handlerDelayJob = func() (_ bool, gErr error) { + handlerDelayJob := func() (_ bool, gErr error) { delayDur := strings.TrimSpace(msg.Headers().Get(DefaultCloudEventDelayKey)) if delayDur == "" { return false, nil @@ -264,8 +261,8 @@ func (c *Client) doConsumeHandler(streamName, consumerName string, jobSubjects m return } - var cfg = handler.cfg - var checkErrAndLog = func(err error, msg string) { + cfg := handler.cfg + checkErrAndLog := func(err error, msg string) { if err == nil { return } @@ -292,8 +289,8 @@ func (c *Client) doConsumeHandler(streamName, consumerName string, jobSubjects m return } - var backoff = lo.FromPtr(cfg.RetryBackoff) - var maxRetries = lo.FromPtr(cfg.MaxRetry) + backoff := lo.FromPtr(cfg.RetryBackoff) + maxRetries := lo.FromPtr(cfg.MaxRetry) // If the error is a redelivery error, then the backoff duration is the error duration if err1 := isRedeliveryErr(err); err1 != nil { @@ -349,8 +346,8 @@ func (c *Client) doErrHandler(streamName, consumerName string) jetstream.PullCon }) } -func (c *Client) doHandler(meta *jetstream.MsgMetadata, msg jetstream.Msg, job *jobEventHandler, cfg *JobEventConfig) (gErr anyhow.Error) { - var timeout = lo.FromPtr(cfg.Timeout) +func (c *Client) doHandler(meta *jetstream.MsgMetadata, msg jetstream.Msg, job *jobEventHandler, cfg *JobEventConfig) (gErr result.Error) { + timeout := lo.FromPtr(cfg.Timeout) ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() @@ -373,7 +370,7 @@ func (c *Client) doHandler(meta *jetstream.MsgMetadata, msg jetstream.Msg, job * Config: cfg, } - var now = time.Now() + now := time.Now() var args any defer func() { if gErr.IsOK() { @@ -391,31 +388,31 @@ func (c *Client) doHandler(meta *jetstream.MsgMetadata, msg jetstream.Msg, job * }() var pb anypb.Any - err := anyhow.ErrOf(proto.Unmarshal(msg.Data(), &pb)). + err := result.ErrOf(proto.Unmarshal(msg.Data(), &pb)). Map(func(err error) error { return errors.WrapTag(err, errors.T("msg", "failed to unmarshal stream msg data to any proto"), errors.T("args", string(msg.Data())), ) }) - if err.CatchErr(&gErr) { - return + if err.Catch(&gErr) { + return gErr } args = &pb - dst := anyhow.Wrap(anypb.UnmarshalNew(args.(*anypb.Any), proto.UnmarshalOptions{})). + dst := result.Wrap(anypb.UnmarshalNew(args.(*anypb.Any), proto.UnmarshalOptions{})). MapErr(func(err error) error { return errors.WrapTag(err, errors.T("msg", "failed to unmarshal any proto to proto msg"), errors.T("args", args), ) }) - if dst.CatchErr(&gErr) { - return + if dst.Catch(&gErr) { + return gErr } ctx = createCtxWithContext(ctx, msgCtx) - err = anyhow.ErrOf(job.handler(ctx, dst.GetValue())). + err = result.ErrOf(job.handler(ctx, dst.GetValue())). Map(func(err error) error { return errors.WrapTag(err, errors.T("msg", "failed to do cloud job handler"), @@ -427,7 +424,7 @@ func (c *Client) doHandler(meta *jetstream.MsgMetadata, msg jetstream.Msg, job * } func (c *Client) doConsume() (r error) { - defer errcheck.RecoveryAndCheck(&r) + defer result.RecoveryErr(&r) for streamName, consumers := range c.consumers { for consumerName, consumer := range consumers { assert.If(c.jobs[streamName] == nil, "stream not found, stream=%s", streamName) @@ -457,7 +454,7 @@ func (c *Client) doConsume() (r error) { c.p.Lc.BeforeStop(lifecycle.WrapNoCtxErr(con.Stop)) } } - return + return r } func (c *Client) Start() error { diff --git a/component/cloudevent/config.go b/component/cloudevent/config.go index c163c0eb..b1a6aaff 100644 --- a/component/cloudevent/config.go +++ b/component/cloudevent/config.go @@ -5,26 +5,29 @@ import ( "fmt" "time" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/running" - "github.com/pubgo/funk/typex" "google.golang.org/protobuf/proto" yaml "gopkg.in/yaml.v3" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/buildinfo/version" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/typex" ) -const DefaultPrefix = "acj" -const DefaultTimeout = 15 * time.Second -const DefaultMaxRetry = 3 -const DefaultRetryBackoff = time.Second -const DefaultSenderKey = "sender" -const DefaultCloudEventDelayKey = "__cloudevent_delay_run_at" -const DefaultJobName = "default" -const DefaultConcurrent = 100 -const DefaultMaxConcurrent = 1000 -const DefaultMinConcurrent = 1 +const ( + DefaultPrefix = "acj" + DefaultTimeout = 15 * time.Second + DefaultMaxRetry = 3 + DefaultRetryBackoff = time.Second + DefaultSenderKey = "sender" + DefaultCloudEventDelayKey = "__cloudevent_delay_run_at" + DefaultJobName = "default" + DefaultConcurrent = 100 + DefaultMaxConcurrent = 1000 + DefaultMinConcurrent = 1 +) -var senderValue = fmt.Sprintf("%s/%s", running.Project, running.Version) +var senderValue = fmt.Sprintf("%s/%s", version.Project(), version.Version()) type Config struct { // Streams: nats stream config @@ -111,6 +114,6 @@ func (p *strOrJobConfig) UnmarshalYAML(value *yaml.Node) error { default: var val any assert.Exit(value.Decode(&val)) - return errors.Format("yaml kind type error,kind=%v data=%v", value.Kind, val) + return errors.Errorf("yaml kind type error,kind=%v data=%v", value.Kind, val) } } diff --git a/component/cloudevent/context.go b/component/cloudevent/context.go index ea9c2776..b6b1c637 100644 --- a/component/cloudevent/context.go +++ b/component/cloudevent/context.go @@ -5,9 +5,10 @@ import ( "net/http" "time" - cloudeventpb "github.com/pubgo/funk/proto/cloudevent" "github.com/rs/xid" "google.golang.org/protobuf/proto" + + cloudeventpb "github.com/pubgo/funk/v2/proto/cloudevent" ) type Context struct { @@ -86,7 +87,7 @@ func WithPushOpt(opts ...func(opt *cloudeventpb.PushEventOptions)) *cloudeventpb } func getOptions(ctx context.Context, opts ...*cloudeventpb.PushEventOptions) *cloudeventpb.PushEventOptions { - var evtOpt = new(cloudeventpb.PushEventOptions) + evtOpt := new(cloudeventpb.PushEventOptions) opt, ok := ctx.Value(pushEventCtxKey).(*cloudeventpb.PushEventOptions) if ok { evtOpt = opt diff --git a/component/cloudevent/errors.go b/component/cloudevent/errors.go index b4fc6ad8..c625a391 100644 --- a/component/cloudevent/errors.go +++ b/component/cloudevent/errors.go @@ -4,14 +4,16 @@ import ( "fmt" "time" - "github.com/pubgo/funk/errors" + "github.com/pubgo/funk/v2/errors" ) -var errReject = errors.New("cloudevent: reject retry and discard msg") -var errRedeliveryStr = "cloudevent: redelivery message with custom delay duration" +var ( + errReject = errors.New("cloudevent: reject retry and discard msg") + errRedeliveryStr = "cloudevent: redelivery message with custom delay duration" +) func Reject(errs ...error) error { - var reason = "reject" + reason := "reject" if len(errs) > 0 { reason = errs[0].Error() } @@ -35,7 +37,7 @@ func (err errRedelivery) Error() string { } func Redelivery(delay time.Duration, errs ...error) error { - var reason = "redelivery" + reason := "redelivery" if len(errs) > 0 { reason = errs[0].Error() } diff --git a/component/cloudevent/publisher.go b/component/cloudevent/publisher.go index 623a6e1d..82603aa2 100644 --- a/component/cloudevent/publisher.go +++ b/component/cloudevent/publisher.go @@ -2,27 +2,30 @@ package cloudevent import ( "context" + "fmt" "time" + result2 "github.com/pubgo/funk/v2/result" + "github.com/nats-io/nats.go" "github.com/nats-io/nats.go/jetstream" - "github.com/pubgo/funk/ctxutil" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/errors/errcheck" - cloudeventpb "github.com/pubgo/funk/proto/cloudevent" - "github.com/pubgo/funk/result" - "github.com/pubgo/funk/stack" - "github.com/pubgo/funk/try" - "github.com/pubgo/funk/typex" "github.com/rs/xid" "github.com/rs/zerolog" "github.com/samber/lo" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" + + "github.com/pubgo/funk/v2/ctxutil" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log/logfields" + cloudeventpb "github.com/pubgo/funk/v2/proto/cloudevent" + "github.com/pubgo/funk/v2/stack" + "github.com/pubgo/funk/v2/try" + "github.com/pubgo/funk/v2/typex" ) -func PushEvent[T any](handler func(*Client, context.Context, T, ...*cloudeventpb.PushEventOptions) (*PubAckInfo, error), jobCli *Client, ctx context.Context, t T, opts ...*cloudeventpb.PushEventOptions) chan result.Result[*PubAckInfo] { - errChan := make(chan result.Result[*PubAckInfo]) +func PushEvent[T any](handler func(*Client, context.Context, T, ...*cloudeventpb.PushEventOptions) (*PubAckInfo, error), jobCli *Client, ctx context.Context, t T, opts ...*cloudeventpb.PushEventOptions) chan result2.Result[*PubAckInfo] { + errChan := make(chan result2.Result[*PubAckInfo]) timeout := ctxutil.GetTimeout(ctx) now := time.Now() fnCaller := stack.Caller(1).String() @@ -30,12 +33,12 @@ func PushEvent[T any](handler func(*Client, context.Context, T, ...*cloudeventpb // clone ctx and recalculate timeout ctx = lo.T2(ctxutil.Clone(ctx, DefaultTimeout)).A go func() { - var getPubAck = func() (pubAck *PubAckInfo, err error) { + getPubAck := func() (pubAck *PubAckInfo, err error) { err = try.Try(func() error { pubAck, err = handler(jobCli, ctx, t, opts...) return err }) - return + return pubAck, err } pubAck, err := getPubAck() err = errors.IfErr(err, func(err error) error { @@ -52,7 +55,7 @@ func PushEvent[T any](handler func(*Client, context.Context, T, ...*cloudeventpb }) return err }) - errChan <- result.Wrap(pubAck, err) + errChan <- result2.Wrap(pubAck, err) }() return errChan } @@ -68,7 +71,7 @@ func PushRpcEvent[T proto.Message](handler RpcEventHandler[T], ctx context.Conte timeout := ctxutil.GetTimeout(ctx) now := time.Now() - var pushEventBasic = func(handler RpcEventHandler[T], ctx context.Context) error { + pushEventBasic := func(handler RpcEventHandler[T], ctx context.Context) error { err := try.Try(func() error { return lo.T2(handler(ctx, t)).B }) if err == nil { return nil @@ -97,14 +100,15 @@ func (c *Client) Publish(ctx context.Context, topic string, args proto.Message, } func (c *Client) publish(ctx context.Context, topic string, args proto.Message, opts ...*cloudeventpb.PushEventOptions) (_ *PubAckInfo, gErr error) { - var timeout = ctxutil.GetTimeout(ctx) - var now = time.Now() - var msgId = xid.New().String() + defer result2.RecoveryErr(&gErr) + timeout := ctxutil.GetTimeout(ctx) + now := time.Now() + msgId := xid.New().String() var pushEventOpt *cloudeventpb.PushEventOptions var pubActInfo *jetstream.PubAck defer func() { - var msgFn = func(e *zerolog.Event) { + msgFn := func(e *zerolog.Event) { e.Str("pub_topic", topic) e.Str("pub_start", now.String()) e.Any("pub_args", args) @@ -127,20 +131,22 @@ func (c *Client) publish(ctx context.Context, topic string, args proto.Message, msgId = pushEventOpt.GetMsgId() } - pb, err := anypb.New(args) - err = errors.IfErr(err, func(err error) error { - return errors.Wrap(err, "failed to marshal args to any proto") - }) - if errcheck.Check(&gErr, err) { + pb := result2.Wrap(anypb.New(args)). + Log(func(e *zerolog.Event) { + e.Str(logfields.Msg, "failed to marshal args to any proto") + }). + UnwrapErr(&gErr) + if gErr != nil { return } // TODO get parent event info from ctx - data, err := proto.Marshal(pb) - err = errors.IfErr(err, func(err error) error { - return errors.Wrap(err, "failed to marshal any proto to bytes") - }) - if errcheck.Check(&gErr, err) { + data := result2.Wrap(proto.Marshal(pb)). + Log(func(e *zerolog.Event) { + e.Str(logfields.Msg, "failed to marshal any proto to bytes") + }). + UnwrapErr(&gErr) + if gErr != nil { return } @@ -159,11 +165,12 @@ func (c *Client) publish(ctx context.Context, topic string, args proto.Message, msg := &nats.Msg{Subject: topic, Data: data, Header: header} jetOpts := append([]jetstream.PublishOpt{}, jetstream.WithMsgID(msgId)) - pubActInfo, err = c.js.PublishMsg(ctx, msg, jetOpts...) - err = errors.IfErr(err, func(err error) error { - return errors.Wrapf(err, "failed to publish msg to stream, topic=%s msg_id=%s", topic, msgId) - }) - if errcheck.Check(&gErr, err) { + pubActInfo = result2.Wrap(c.js.PublishMsg(ctx, msg, jetOpts...)). + Log(func(e *zerolog.Event) { + e.Str(logfields.Msg, fmt.Sprintf("failed to publish msg to stream, topic=%s msg_id=%s", topic, msgId)) + }). + UnwrapErr(&gErr) + if gErr != nil { return } diff --git a/component/cloudevent/register.go b/component/cloudevent/register.go index f79bb98c..3490d1f6 100644 --- a/component/cloudevent/register.go +++ b/component/cloudevent/register.go @@ -5,16 +5,17 @@ import ( "fmt" "reflect" - "github.com/pubgo/funk/assert" - cloudeventpb "github.com/pubgo/funk/proto/cloudevent" - "github.com/pubgo/funk/stack" - "github.com/pubgo/funk/vars" "github.com/rs/zerolog" "github.com/samber/lo" "google.golang.org/protobuf/proto" + + "github.com/pubgo/funk/v2/assert" + cloudeventpb "github.com/pubgo/funk/v2/proto/cloudevent" + "github.com/pubgo/funk/v2/stack" + "github.com/pubgo/funk/v2/vars" ) -func WrapHandler[Req proto.Message, Rsp proto.Message](handler func(ctx context.Context, req Req) (Rsp, error)) func(ctx context.Context, req Req) error { +func WrapHandler[Req, Rsp proto.Message](handler func(ctx context.Context, req Req) (Rsp, error)) func(ctx context.Context, req Req) error { return func(ctx context.Context, req Req) error { _, err := handler(ctx, req) return err @@ -34,7 +35,7 @@ func init() { }) } -func RegisterJobHandler[T proto.Message](jobCli *Client, jobName string, topic string, handler EventHandler[T], opts ...*cloudeventpb.RegisterJobOptions) { +func RegisterJobHandler[T proto.Message](jobCli *Client, jobName, topic string, handler EventHandler[T], opts ...*cloudeventpb.RegisterJobOptions) { assert.Fn(reflect.TypeOf(jobCli.subjects[topic]) != reflect.TypeOf(lo.Empty[T]()), func() error { return fmt.Errorf("type not match, topic-type=%s handler-input-type=%s", reflect.TypeOf(jobCli.subjects[topic]).String(), reflect.TypeOf(lo.Empty[T]()).String()) }) @@ -46,11 +47,11 @@ func RegisterJobHandler[T proto.Message](jobCli *Client, jobName string, topic s jobCli.registerJobHandler(jobName, topic, func(ctx context.Context, args proto.Message) error { return handler(ctx, args.(T)) }, opts...) } -func (c *Client) registerJobHandler(jobName string, topic string, handler EventHandler[proto.Message], opts ...*cloudeventpb.RegisterJobOptions) { +func (c *Client) registerJobHandler(jobName, topic string, handler EventHandler[proto.Message], opts ...*cloudeventpb.RegisterJobOptions) { assert.If(handler == nil, "job handler is nil") assert.If(c.subjects[topic] == nil, "topic:%s not found", topic) - var evtOpt = new(cloudeventpb.RegisterJobOptions) + evtOpt := new(cloudeventpb.RegisterJobOptions) for _, o := range opts { proto.Merge(evtOpt, o) } diff --git a/component/cloudevent/util.go b/component/cloudevent/util.go index c1751e5c..e947c4ff 100644 --- a/component/cloudevent/util.go +++ b/component/cloudevent/util.go @@ -7,14 +7,15 @@ import ( "time" "github.com/nats-io/nats.go/jetstream" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - cloudeventpb "github.com/pubgo/funk/proto/cloudevent" - "github.com/pubgo/funk/protoutils" - "github.com/pubgo/funk/result" "github.com/rs/zerolog" "github.com/samber/lo" "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + cloudeventpb "github.com/pubgo/funk/v2/proto/cloudevent" + "github.com/pubgo/funk/v2/protoutils" + "github.com/pubgo/funk/v2/result" ) func getStorageType(name string) jetstream.StorageType { @@ -28,7 +29,7 @@ func getStorageType(name string) jetstream.StorageType { } } -func mergeJobConfig(dst *JobEventConfig, src *JobEventConfig) *JobEventConfig { +func mergeJobConfig(dst, src *JobEventConfig) *JobEventConfig { if src == nil { src = handleDefaultJobConfig(nil) } @@ -72,7 +73,7 @@ func handleDefaultJobConfig(cfg *JobEventConfig) *JobEventConfig { return cfg } -func handleSubjectName(name string, prefix string) string { +func handleSubjectName(name, prefix string) string { prefix = fmt.Sprintf("%s.", prefix) if strings.HasPrefix(name, prefix) { return name @@ -101,7 +102,7 @@ type subjectOpt struct { *cloudeventpb.CloudEventMethodOptions } -func registerSubject(subjects map[string]*cloudeventpb.CloudEventMethodOptions, subject string, operation string, data *cloudeventpb.CloudEventMethodOptions) any { +func registerSubject(subjects map[string]*cloudeventpb.CloudEventMethodOptions, subject, operation string, data *cloudeventpb.CloudEventMethodOptions) any { assert.If(subject == "", "subject is empty") assert.If(operation == "", "operation is empty") assert.If(data == nil, "data is nil") @@ -121,7 +122,7 @@ func registerSubject(subjects map[string]*cloudeventpb.CloudEventMethodOptions, } func getAllSubject() map[string]*cloudeventpb.CloudEventMethodOptions { - var subjects = make(map[string]*cloudeventpb.CloudEventMethodOptions) + subjects := make(map[string]*cloudeventpb.CloudEventMethodOptions) for _, opt := range getAllSubjectOptions() { registerSubject(subjects, opt.CloudEventServiceOptions.Name, *opt.Operation, opt.CloudEventMethodOptions) } diff --git a/component/cloudevent/z_util_test.go b/component/cloudevent/z_util_test.go index f8995579..0f058b47 100644 --- a/component/cloudevent/z_util_test.go +++ b/component/cloudevent/z_util_test.go @@ -10,7 +10,7 @@ import ( ) func TestCalcTimeout(t *testing.T) { - var ctx = context.Background() + ctx := context.Background() deadline, ok := ctx.Deadline() assert.Equal(t, ok, false) diff --git a/migrates/entmigrates/aaa.go b/component/entmigrates/aaa.go similarity index 100% rename from migrates/entmigrates/aaa.go rename to component/entmigrates/aaa.go diff --git a/migrates/entmigrates/config.go b/component/entmigrates/config.go similarity index 96% rename from migrates/entmigrates/config.go rename to component/entmigrates/config.go index 711b4f40..069b6d74 100644 --- a/migrates/entmigrates/config.go +++ b/component/entmigrates/config.go @@ -3,8 +3,9 @@ package entmigrates import ( _ "embed" - "github.com/pubgo/funk/assert" "gopkg.in/yaml.v3" + + "github.com/pubgo/funk/v2/assert" ) //go:embed config.yaml diff --git a/migrates/entmigrates/config.yaml b/component/entmigrates/config.yaml similarity index 100% rename from migrates/entmigrates/config.yaml rename to component/entmigrates/config.yaml diff --git a/migrates/entmigrates/migrate.go b/component/entmigrates/migrate.go similarity index 97% rename from migrates/entmigrates/migrate.go rename to component/entmigrates/migrate.go index 5582e4d6..63de31fe 100644 --- a/migrates/entmigrates/migrate.go +++ b/component/entmigrates/migrate.go @@ -13,12 +13,7 @@ import ( "entgo.io/ent/dialect/sql/schema" "github.com/dave/jennifer/jen" mapset "github.com/deckarep/golang-set/v2" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/version" + "github.com/samber/lo" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/postgres" "github.com/testcontainers/testcontainers-go/wait" @@ -26,6 +21,12 @@ import ( dp "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/buildinfo/version" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" ) type MigrationWrap struct { @@ -58,7 +59,7 @@ type GoMigrate struct { // New returns a new GoMigrate. func New(db *entsql.Driver, cfg *Config, migrations []*Migration, tables []*schema.Table) *GoMigrate { - cfg = config.MergeR(generic.Ptr(DefaultConfig), cfg).Unwrap() + cfg = config.MergeR(lo.ToPtr(DefaultConfig), cfg).Must() orm := assert.Must1(gorm.Open(dp.New(dp.Config{ DriverName: db.Dialect(), diff --git a/component/etcdv3/client.go b/component/etcdv3/client.go index 7ceddb7b..31d17773 100644 --- a/component/etcdv3/client.go +++ b/component/etcdv3/client.go @@ -5,15 +5,15 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/merge" - "github.com/pubgo/funk/retry" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/merge" + "github.com/pubgo/funk/v2/retry" ) func New(conf *Config) *Client { - conf = config.MergeR(DefaultCfg(), *conf).Unwrap() - cfg := merge.Struct(new(client3.Config), conf).Unwrap() + conf = config.MergeR(DefaultCfg(), *conf).Must() + cfg := merge.Struct(new(client3.Config), conf).Must() cfg.DialOptions = append( cfg.DialOptions, grpc.WithBlock(), @@ -21,7 +21,7 @@ func New(conf *Config) *Client { ) // 创建etcd client对象 - return &Client{Client: assert.Must1(retry.Default().DoVal(func(i int) (interface{}, error) { + return &Client{Client: assert.Must1(retry.Default().DoVal(func(i int) (any, error) { return client3.New(*cfg) })).(*client3.Client)} } diff --git a/component/gormclient/builder.go b/component/gormclient/builder.go index 0836a9ce..36ca32f3 100644 --- a/component/gormclient/builder.go +++ b/component/gormclient/builder.go @@ -3,14 +3,15 @@ package gormclient import ( "time" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/merge" + "github.com/samber/lo" "gorm.io/gorm" "gorm.io/gorm/logger" "gorm.io/gorm/schema" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/merge" ) func NewClients(conf map[string]*Config, logs log.Logger) map[string]*Client { @@ -23,9 +24,9 @@ func NewClients(conf map[string]*Config, logs log.Logger) map[string]*Client { func New(conf *Config, logs log.Logger) *Client { logs = logs.WithName(Name) - conf = config.MergeR(generic.Ptr(DefaultCfg()), conf).Unwrap() + conf = config.MergeR(lo.ToPtr(DefaultCfg()), conf).Must() - ormCfg := merge.Copy(new(gorm.Config), conf).Unwrap() + ormCfg := merge.Copy(new(gorm.Config), conf).Must() ormCfg.NowFunc = func() time.Time { return time.Now().UTC() } ormCfg.NamingStrategy = schema.NamingStrategy{TablePrefix: conf.TablePrefix} @@ -37,6 +38,7 @@ func New(conf *Config, logs log.Logger) *Client { factory := Get(conf.Driver) assert.If(factory == nil, "driver factory[%s] not found", conf.Driver) + dialect := factory(conf.DriverCfg) db := assert.Must1(gorm.Open(dialect, ormCfg)) diff --git a/component/gormclient/client.go b/component/gormclient/client.go index ebeea2e3..a7614ed9 100644 --- a/component/gormclient/client.go +++ b/component/gormclient/client.go @@ -3,9 +3,10 @@ package gormclient import ( "database/sql" - "github.com/pubgo/funk/result" - "github.com/pubgo/funk/vars" "gorm.io/gorm" + + "github.com/pubgo/funk/v2/result" + "github.com/pubgo/funk/v2/vars" ) const Name = "orm" @@ -23,8 +24,8 @@ func (c *Client) Ping() error { return _db.Ping() } -func (c *Client) Vars() vars.Value { - return func() interface{} { +func (c *Client) Vars() vars.Func { + return func() any { _db, err := c.DB.DB() if err != nil { return err.Error() @@ -47,5 +48,5 @@ func (c *Client) Stats() (r result.Result[sql.DBStats]) { if err != nil { return r.WithErr(err) } - return r.WithVal(db.Stats()) + return r.WithValue(db.Stats()) } diff --git a/component/gormclient/config.go b/component/gormclient/config.go index 9e428094..5b237dcc 100644 --- a/component/gormclient/config.go +++ b/component/gormclient/config.go @@ -3,8 +3,9 @@ package gormclient import ( "time" - "github.com/pubgo/funk/config" "gorm.io/gorm/logger" + + "github.com/pubgo/funk/v2/config" ) type Config struct { diff --git a/component/gormclient/drivers/mysql/driver.go b/component/gormclient/drivers/mysql/driver.go index 6f837b0a..321b5ebf 100644 --- a/component/gormclient/drivers/mysql/driver.go +++ b/component/gormclient/drivers/mysql/driver.go @@ -1,14 +1,15 @@ package mysql import ( - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/component/gormclient" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/merge" - "github.com/pubgo/funk/recovery" "gorm.io/driver/mysql" "gorm.io/gorm" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/component/gormclient" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/merge" + "github.com/pubgo/funk/v2/recovery" ) type Config struct { @@ -32,7 +33,7 @@ func init() { conf := DefaultCfg() assert.Must(cfg.Decode(&conf)) - ret := merge.Struct(new(mysql.Config), conf).Unwrap() + ret := merge.Struct(new(mysql.Config), conf).Must() return mysql.New(*ret) }) } diff --git a/component/gormclient/drivers/postgres/driver.go b/component/gormclient/drivers/postgres/driver.go index 34dfd168..eb35072e 100644 --- a/component/gormclient/drivers/postgres/driver.go +++ b/component/gormclient/drivers/postgres/driver.go @@ -3,13 +3,14 @@ package sqlite import ( "fmt" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/component/gormclient" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/recovery" "gorm.io/driver/postgres" "gorm.io/gorm" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/component/gormclient" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/recovery" ) func init() { diff --git a/component/gormclient/drivers/sqlite/driver.go b/component/gormclient/drivers/sqlite/driver.go index 3f618a18..210dcd38 100644 --- a/component/gormclient/drivers/sqlite/driver.go +++ b/component/gormclient/drivers/sqlite/driver.go @@ -4,14 +4,15 @@ import ( "fmt" "path/filepath" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/component/gormclient" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/pathutil" - "github.com/pubgo/funk/recovery" "gorm.io/driver/sqlite" "gorm.io/gorm" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/component/gormclient" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/pathutil" + "github.com/pubgo/funk/v2/recovery" ) func init() { diff --git a/component/gormclient/factory.go b/component/gormclient/factory.go index 39ddd469..6d648918 100644 --- a/component/gormclient/factory.go +++ b/component/gormclient/factory.go @@ -1,10 +1,11 @@ package gormclient import ( - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/config" - "github.com/pubgo/funk/recovery" "gorm.io/gorm" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/recovery" ) type Factory func(cfg config.Node) gorm.Dialector diff --git a/component/gormclient/migratecmd/cmd.go b/component/gormclient/migratecmd/cmd.go index 191e644d..b66a9736 100644 --- a/component/gormclient/migratecmd/cmd.go +++ b/component/gormclient/migratecmd/cmd.go @@ -1,156 +1,139 @@ package migratecmd -import ( - "context" - "path/filepath" - "time" - - "github.com/pubgo/dix" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/component/gormclient" - "github.com/pubgo/funk/component/gormclient/migrates" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/recovery" - cli "github.com/urfave/cli/v3" - "gorm.io/gen" -) - -type params struct { - Log log.Logger - Db *gormclient.Client - Migrations []migrates.Migrate - Generations migrates.Generation -} - -func migrate(m []migrates.Migrate) []*migrates.Migration { - var migrations []*migrates.Migration - for i := range m { - migrations = append(migrations, m[i]()) - } - return migrations -} - -func New(di *dix.Dix) *cli.Command { - var id string - - options := migrates.DefaultConfig - return &cli.Command{ - Name: "migrate", - Usage: "db migrate", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "id", - Usage: "migration id", - Destination: &id, - }, - }, - Before: func(ctx context.Context, command *cli.Command) (context.Context, error) { - p := dix.Inject(di, new(params)) - options.TableName = p.Db.TablePrefix + migrates.DefaultConfig.TableName - return ctx, nil - }, - Commands: []*cli.Command{ - { - Name: "migrate", - Usage: "do migrate", - Aliases: []string{"m"}, - Action: func(ctx context.Context, command *cli.Command) error { - defer recovery.Exit() - - p := dix.Inject(di, new(params)) - m := migrates.New(p.Db.DB, &options, migrate(p.Migrations)) - if id == "" { - assert.Must(m.Migrate()) - } else { - assert.Must(m.MigrateTo(id)) - } - p.Log.Info().Msg("migration ok") - return nil - }, - }, - { - Name: "list", - Usage: "list migrate", - Aliases: []string{"l"}, - Action: func(ctx context.Context, command *cli.Command) error { - defer recovery.Exit() - - p := dix.Inject(di, new(params)) - - var ids []string - assert.Must(p.Db.Table(options.TableName).Select("id").Find(&ids).Error) - - for _, m := range migrate(p.Migrations) { - p.Log.Info().Msgf("migration-id=%s %s", m.ID, generic.Ternary(generic.Contains(ids, m.ID), "done", "missing")) - ids = generic.Delete(ids, m.ID) - } - - for i := range ids { - p.Log.Info().Msgf("migration-id=%s %s", ids[i], "undo") - } - - time.Sleep(time.Millisecond * 10) - return nil - }, - }, - { - Name: "rollback", - Usage: "do rollback", - Aliases: []string{"r"}, - Action: func(ctx context.Context, command *cli.Command) error { - defer recovery.Recovery(func(err error) { - if errors.Is(err, migrates.ErrNoRunMigration) { - return - } - - assert.Exit(err) - }) - - p := dix.Inject(di, new(params)) - m := migrates.New(p.Db.DB, &options, migrate(p.Migrations)) - if id == "" { - assert.Must(m.RollbackLast()) - } else { - assert.Must(m.RollbackTo(id)) - } - p.Log.Info().Msg("rollback last ok") - return nil - }, - }, - { - Name: "gen", - Usage: "do gen orm model and query code", - Aliases: []string{"g"}, - UsageText: "migrate gen [./internal/db]", - Action: func(ctx context.Context, command *cli.Command) error { - defer recovery.Exit() - - genPath := "./internal/db" - if command.NArg() > 0 { - genPath = command.Args().First() - } - - g := gen.NewGenerator(gen.Config{ - OutPath: filepath.Join(genPath, "query"), - ModelPkgPath: filepath.Join(genPath, "models"), - FieldWithTypeTag: true, - FieldWithIndexTag: true, - FieldNullable: true, - FieldCoverable: true, - Mode: gen.WithQueryInterface | gen.WithDefaultQuery | gen.WithoutContext, - }) - - p := dix.Inject(di, new(params)) - g.UseDB(p.Db.DB) - - g.ApplyBasic(p.Generations(g)...) - g.Execute() - - return nil - }, - }, - }, - } -} +//type params struct { +// Log log.Logger +// Db *gormclient.Client +// Migrations []migrates.Migrate +// Generations migrates.Generation +//} +// +//func migrate(m []migrates.Migrate) []*migrates.Migration { +// var migrations []*migrates.Migration +// for i := range m { +// migrations = append(migrations, m[i]()) +// } +// return migrations +//} +// +//func New(di *dix.Dix) *cli.Command { +// var id string +// +// options := migrates.DefaultConfig +// return &cli.Command{ +// Name: "migrate", +// Usage: "db migrate", +// Flags: []cli.Flag{ +// &cli.StringFlag{ +// Name: "id", +// Usage: "migration id", +// Destination: &id, +// }, +// }, +// Before: func(ctx context.Context, command *cli.Command) (context.Context, error) { +// p := dix.Inject(di, new(params)) +// options.TableName = p.Db.TablePrefix + migrates.DefaultConfig.TableName +// return ctx, nil +// }, +// Commands: []*cli.Command{ +// { +// Name: "migrate", +// Usage: "do migrate", +// Aliases: []string{"m"}, +// Action: func(ctx context.Context, command *cli.Command) error { +// defer recovery.Exit() +// +// p := dix.Inject(di, new(params)) +// m := migrates.New(p.Db.DB, &options, migrate(p.Migrations)) +// if id == "" { +// assert.Must(m.Migrate()) +// } else { +// assert.Must(m.MigrateTo(id)) +// } +// p.Log.Info().Msg("migration ok") +// return nil +// }, +// }, +// { +// Name: "list", +// Usage: "list migrate", +// Aliases: []string{"l"}, +// Action: func(ctx context.Context, command *cli.Command) error { +// defer recovery.Exit() +// +// p := dix.Inject(di, new(params)) +// +// var ids []string +// assert.Must(p.Db.Table(options.TableName).Select("id").Find(&ids).Error) +// +// for _, m := range migrate(p.Migrations) { +// p.Log.Info().Msgf("migration-id=%s %s", m.ID, generic.Ternary(generic.Contains(ids, m.ID), "done", "missing")) +// ids = generic.Delete(ids, m.ID) +// } +// +// for i := range ids { +// p.Log.Info().Msgf("migration-id=%s %s", ids[i], "undo") +// } +// +// time.Sleep(time.Millisecond * 10) +// return nil +// }, +// }, +// { +// Name: "rollback", +// Usage: "do rollback", +// Aliases: []string{"r"}, +// Action: func(ctx context.Context, command *cli.Command) error { +// defer recovery.Recovery(func(err error) { +// if errors.Is(err, migrates.ErrNoRunMigration) { +// return +// } +// +// assert.Exit(err) +// }) +// +// p := dix.Inject(di, new(params)) +// m := migrates.New(p.Db.DB, &options, migrate(p.Migrations)) +// if id == "" { +// assert.Must(m.RollbackLast()) +// } else { +// assert.Must(m.RollbackTo(id)) +// } +// p.Log.Info().Msg("rollback last ok") +// return nil +// }, +// }, +// { +// Name: "gen", +// Usage: "do gen orm model and query code", +// Aliases: []string{"g"}, +// UsageText: "migrate gen [./internal/db]", +// Action: func(ctx context.Context, command *cli.Command) error { +// defer recovery.Exit() +// +// genPath := "./internal/db" +// if command.NArg() > 0 { +// genPath = command.Args().First() +// } +// +// g := gen.NewGenerator(gen.Config{ +// OutPath: filepath.Join(genPath, "query"), +// ModelPkgPath: filepath.Join(genPath, "models"), +// FieldWithTypeTag: true, +// FieldWithIndexTag: true, +// FieldNullable: true, +// FieldCoverable: true, +// Mode: gen.WithQueryInterface | gen.WithDefaultQuery | gen.WithoutContext, +// }) +// +// p := dix.Inject(di, new(params)) +// g.UseDB(p.Db.DB) +// +// g.ApplyBasic(p.Generations(g)...) +// g.Execute() +// +// return nil +// }, +// }, +// }, +// } +//} diff --git a/component/gormclient/migrates/aaa.go b/component/gormclient/migrates/aaa.go index 432d4d9a..73c3eb31 100644 --- a/component/gormclient/migrates/aaa.go +++ b/component/gormclient/migrates/aaa.go @@ -13,7 +13,7 @@ const ( type ( Migrate func() *Migration - Generation func(g *gen.Generator) []interface{} + Generation func(g *gen.Generator) []any ) // MigrateFunc is the func signature for migrating. diff --git a/component/gormclient/migrates/migrate.go b/component/gormclient/migrates/migrate.go index 5faaa9e3..fd68e973 100644 --- a/component/gormclient/migrates/migrate.go +++ b/component/gormclient/migrates/migrate.go @@ -3,9 +3,10 @@ package migrates import ( "fmt" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/merge" + "github.com/samber/lo" "gorm.io/gorm" + + "github.com/pubgo/funk/v2/merge" ) // Migration represents a database migration (a modification to be made on the database). @@ -47,7 +48,7 @@ func (e *DuplicatedIDError) Error() string { // New returns a new GoMigrate. func New(db *gorm.DB, config *Config, migrations []*Migration) *GoMigrate { - config = merge.Struct(generic.Ptr(DefaultConfig), config).Unwrap() + config = merge.Struct(lo.ToPtr(DefaultConfig), config).Must() return &GoMigrate{ db: db, options: config, diff --git a/component/gormclient/ormutil/util.go b/component/gormclient/ormutil/util.go index 24c2b4df..4cc1b200 100644 --- a/component/gormclient/ormutil/util.go +++ b/component/gormclient/ormutil/util.go @@ -28,9 +28,9 @@ type expr struct { expr *clause.Expr } -func RawCond(sql string, args ...interface{}) gen.Condition { +func RawCond(sql string, args ...any) gen.Condition { return expr{expr: &clause.Expr{SQL: sql, Vars: args}} } -func (s expr) BeCond() interface{} { return s.expr } -func (s expr) CondError() error { return nil } +func (s expr) BeCond() any { return s.expr } +func (s expr) CondError() error { return nil } diff --git a/component/gormclient/sqlmock/mock.go b/component/gormclient/sqlmock/mock.go index e79706b6..091732d5 100644 --- a/component/gormclient/sqlmock/mock.go +++ b/component/gormclient/sqlmock/mock.go @@ -21,9 +21,9 @@ type TestingTB interface { // Name Returns current test name. Name() string Cleanup(f func()) - Logf(fmt string, args ...interface{}) - Fatalf(format string, args ...interface{}) - Errorf(message string, args ...interface{}) + Logf(fmt string, args ...any) + Fatalf(format string, args ...any) + Errorf(message string, args ...any) } func NewResult(lastInsertID, rowsAffected int64) driver.Result { @@ -38,7 +38,7 @@ func AnyArgs(n int) (args []driver.Value) { for i := 0; i < n; i++ { args = append(args, sqlmock.AnyArg()) } - return + return args } type AnyTime struct{} diff --git a/component/natsclient/client.go b/component/natsclient/client.go index 1ca3cc27..590fe207 100644 --- a/component/natsclient/client.go +++ b/component/natsclient/client.go @@ -4,10 +4,11 @@ import ( "fmt" "github.com/nats-io/nats.go" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/component/lifecycle" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/running" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/component/lifecycle" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/running" ) type Param struct { @@ -28,7 +29,7 @@ func New(p Param) *Client { nc := assert.Must1(nats.Connect(p.Cfg.Url, func(o *nats.Options) error { o.AllowReconnect = true - o.Name = fmt.Sprintf("%s/%s/%s", running.Hostname, running.Project, running.InstanceID) + o.Name = fmt.Sprintf("%s/%s/%s", running.Hostname, running.Project(), running.InstanceID) return nil })) diff --git a/config/aaa.go b/config/aaa.go index bbe763fe..c8f0c668 100644 --- a/config/aaa.go +++ b/config/aaa.go @@ -6,12 +6,12 @@ type NamedConfig interface { } type Resources struct { - // Resources resource config file must exist + // Resources resource config file or dir must exist Resources []string `yaml:"resources"` - // PatchResources resource config not required to exist + // PatchResources resource config file or dir not required to exist PatchResources []string `yaml:"patch_resources"` - // PatchEnvs config file or path, not required to exist + // PatchEnvs env config file or dir not required to exist PatchEnvs []string `yaml:"patch_envs"` } diff --git a/config/config.go b/config/config.go index 52bd4b00..b8c10635 100644 --- a/config/config.go +++ b/config/config.go @@ -10,18 +10,19 @@ import ( "strings" "github.com/a8m/envsubst" + "github.com/rs/zerolog" "github.com/samber/lo" "gopkg.in/yaml.v3" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/pathutil" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/recovery" - "github.com/pubgo/funk/result" - "github.com/pubgo/funk/typex" - "github.com/pubgo/funk/vars" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/log/logfields" + "github.com/pubgo/funk/v2/pathutil" + "github.com/pubgo/funk/v2/pretty" + "github.com/pubgo/funk/v2/recovery" + "github.com/pubgo/funk/v2/result" + "github.com/pubgo/funk/v2/typex" + "github.com/pubgo/funk/v2/vars" ) const ( @@ -36,59 +37,99 @@ var ( ) func init() { - vars.RegisterValue("config", map[string]any{ - "config_type": defaultConfigType, - "config_name": defaultConfigName, - "config_path": configPath, - "config_dir": configDir, + vars.Register("config", func() any { + return map[string]any{ + "config_type": defaultConfigType, + "config_name": defaultConfigName, + "config_path": configPath, + "config_dir": configDir, + } }) } +func GetConfigDir() string { + return configDir +} + +func GetConfigPath() string { + return configPath +} + +func SetConfigPath(confPath string) { + assert.If(confPath == "", "config path is null") + configPath = confPath +} + func GetConfigData(cfgPath string) (_ []byte, gErr error) { var configBytes []byte - defer recovery.Err(&gErr, func(err error) error { + defer result.RecoveryErr(&gErr, func(err error) error { log.Err(err).Str("config_path", cfgPath).Msgf("config: %s", configBytes) return err }) - configBytes = result.Of(os.ReadFile(cfgPath)).Expect("failed to read config data: %s", cfgPath) + configBytes = result.Wrap(os.ReadFile(cfgPath)).Expect("failed to read config data: %s", cfgPath) configBytes = cfgFormat(configBytes, &config{workDir: filepath.Dir(cfgPath)}) - configBytes = result.Of(envsubst.Bytes(configBytes)).Expect("failed to handler config env data: %s", cfgPath) + configBytes = result.Wrap(envsubst.Bytes(configBytes)).Expect("failed to handler config env data: %s", cfgPath) return configBytes, nil } -func LoadEnvConfigMap(cfgPath string) EnvConfigMap { return loadEnvConfigMap(cfgPath) } +func LoadEnvMap(cfgPath string) EnvSpecMap { return loadEnvConfigMap(cfgPath) } + +func loadEnvConfigMap(cfgPath string) EnvSpecMap { + defer recovery.Exit(func(err error) error { + log.Err(err).Str("path", cfgPath).Msg("load env config map error") + return err + }) -func loadEnvConfigMap(cfgPath string) EnvConfigMap { var res Resources - configBytes := result.Of(os.ReadFile(cfgPath)).Expect("failed to read config data: %s", cfgPath) + configBytes := result.Wrap(os.ReadFile(cfgPath)).Expect("failed to read config data: %s", cfgPath) assert.Must(yaml.Unmarshal(configBytes, &res), "failed to unmarshal resource config") parentDir := filepath.Dir(cfgPath) - var envCfgMap EnvConfigMap + var envSpecMap EnvSpecMap for _, envPath := range res.PatchEnvs { envPath = filepath.Join(parentDir, envPath) if pathutil.IsNotExist(envPath) { - log.Warn().Str("env_path", envPath).Msg("env config cfgPath not found") + log.Warn().Str("env_path", envPath).Msg("env config path not found") continue } - pathList := listAllPath(envPath).Expect("failed to list envPath: %s", envPath) + pathList := listAllPath(envPath).Expect("failed to list env config path: %s", envPath) for _, p := range pathList { - envConfigBytes := result.Of(os.ReadFile(p)).Expect("failed to handler env config data, path=%s", p) - envConfigBytes = bytes.TrimSpace(envConfigBytes) + if !strings.HasSuffix(p, "."+defaultConfigType) { + continue + } + + envConfigBytes := result.Wrap(os.ReadFile(p)). + Map(bytes.TrimSpace). + Must(func(e *zerolog.Event) { + e.Str("env_path", p) + e.Str(logfields.Msg, "failed to handler env config data") + }) if len(envConfigBytes) == 0 { continue } - assert.MustF(yaml.Unmarshal(envConfigBytes, &envCfgMap), "failed to unmarshal env config, data=%s path=%s", envConfigBytes, p) + envConfigBytes = cfgFormat(envConfigBytes, &config{workDir: filepath.Dir(cfgPath)}) + envConfigBytes = result.Wrap(envsubst.Bytes(envConfigBytes)). + Must(func(e *zerolog.Event) { + e.Str("env_path", p) + e.Str("env_data", string(envConfigBytes)) + e.Str(logfields.Msg, "failed to handler config env") + }) + result.ErrOf(yaml.Unmarshal(envConfigBytes, &envSpecMap)). + Must(func(e *zerolog.Event) { + e.Str("env_data", string(envConfigBytes)) + e.Str("env_path", p) + e.Str(logfields.Msg, "failed to unmarshal env config") + }) } } - initEnv(envCfgMap) - return envCfgMap + initEnv(envSpecMap) + return envSpecMap } -func LoadFromPath[T any](val *T, cfgPath string) EnvConfigMap { +func LoadFromPath[T any](val *T, cfgPath string) EnvSpecMap { defer recovery.Exit(func(err error) error { log.Err(err).Str("config_path", cfgPath).Msg("failed to load config") return err @@ -109,9 +150,9 @@ func LoadFromPath[T any](val *T, cfgPath string) EnvConfigMap { Msg("config type not correct") } - var envCfgMap = loadEnvConfigMap(cfgPath) + envCfgMap := loadEnvConfigMap(cfgPath) - configBytes := result.Of(GetConfigData(cfgPath)).Expect("failed to handler config data") + configBytes := result.Wrap(GetConfigData(cfgPath)).Expect("failed to handler config data") defer recovery.Exit(func(err error) error { log.Err(err). Str("config_path", cfgPath). @@ -140,23 +181,22 @@ func LoadFromPath[T any](val *T, cfgPath string) EnvConfigMap { } // skip .*.yaml and cfg.other - var cfgFilter = func(item string, index int) bool { + cfgFilter := func(item string, index int) bool { return strings.HasSuffix(item, "."+defaultConfigType) && !strings.HasPrefix(item, ".") } resPaths = lo.Filter(resPaths, cfgFilter) return lo.Uniq(resPaths) } getCfg := func(resPath string) T { - resBytes := result.Of(GetConfigData(resPath)).Expect("failed to handler config data") + resBytes := result.Wrap(GetConfigData(resPath)).Expect("failed to handler config data") var cfg1 T - result.Err[any](yaml.Unmarshal(resBytes, &cfg1)). - Unwrap(func(err error) error { - fmt.Println("res_path", resPath) - fmt.Println("config_data", string(resBytes)) - assert.Exit(os.WriteFile(resPath+".err.yml", resBytes, 0666)) - return errors.Wrap(err, "failed to unmarshal config") - }) + result.ErrOf(yaml.Unmarshal(resBytes, &cfg1)).Must(func(e *zerolog.Event) { + fmt.Println("res_path", resPath) + fmt.Println("config_data", string(resBytes)) + assert.Exit(os.WriteFile(resPath+".err.yml", resBytes, 0o666)) + e.Str(logfields.Msg, "failed to unmarshal config") + }) return cfg1 } @@ -166,7 +206,7 @@ func LoadFromPath[T any](val *T, cfgPath string) EnvConfigMap { var cfgList []T cfgList = append(cfgList, typex.DoBlock1(func() []T { - var resPathList = getRealPath(res.Resources) + resPathList := getRealPath(res.Resources) sort.Strings(resPathList) var pathList []T @@ -181,7 +221,7 @@ func LoadFromPath[T any](val *T, cfgPath string) EnvConfigMap { return pathList })...) cfgList = append(cfgList, typex.DoBlock1(func() []T { - var patchResPathList = getRealPath(res.PatchResources) + patchResPathList := getRealPath(res.PatchResources) sort.Strings(patchResPathList) var pathList []T @@ -208,7 +248,7 @@ func LoadFromPath[T any](val *T, cfgPath string) EnvConfigMap { type Cfg[T any] struct { T T P *T - EnvCfg *EnvConfigMap + EnvCfg *EnvSpecMap } func Load[T any]() Cfg[T] { diff --git a/config/configs/assets/assets.yaml b/config/configs/assets/assets.yaml index e6ea108a..bdff3f08 100644 --- a/config/configs/assets/assets.yaml +++ b/config/configs/assets/assets.yaml @@ -2,4 +2,5 @@ assets: test_md: test_abc: secret: ${{embed("test.md")}} - path_dir: ${{path_dir()}} + path_dir: ${{config_dir()}} + env_var: ${{env.TEST_ABC}} diff --git a/config/envs.go b/config/envs.go index bec1490d..7587d511 100644 --- a/config/envs.go +++ b/config/envs.go @@ -1,32 +1,46 @@ package config import ( + "fmt" "strings" - "github.com/pubgo/funk/env" "github.com/samber/lo" + + "github.com/pubgo/funk/v2/env" + "github.com/pubgo/funk/v2/strutil" ) -type EnvConfigMap map[string]*EnvConf +type EnvSpecMap map[string]*EnvSpec + +type EnvSpec struct { + // Name of the environment variable. + Name string `yaml:"name"` -type EnvConf struct { - Name string `yaml:"name"` + // Description Deprecated: use Desc instead. Description string `yaml:"description"` + Desc string `yaml:"desc"` Default string `yaml:"default"` + Value string `yaml:"value"` Required bool `yaml:"required"` Example string `yaml:"example"` - Versions string `yaml:"versions"` - Tags string `yaml:"tags"` } -func initEnv(envMap EnvConfigMap) { +func (e EnvSpec) GetValue() string { + return strings.TrimSpace(strutil.FirstNotEmpty(env.Get(e.Name), e.Value, e.Default)) +} + +func (e EnvSpec) Validate() error { + if e.Required && e.GetValue() == "" { + return fmt.Errorf("env:%s is required", e.Name) + } + return nil +} + +func initEnv(envMap EnvSpecMap) { for name, cfg := range envMap { - envData := env.Get(name) - envData = strings.TrimSpace(lo.Ternary(envData != "", envData, cfg.Default)) - if cfg.Required && envData == "" { - panic("env " + cfg.Name + " is required") - } + cfg.Name = name - env.Set(name, envData).Must() + lo.Must0(cfg.Validate()) + env.Set(name, cfg.GetValue()).Must() } } diff --git a/config/types.go b/config/types.go index a1dbd53f..32e50d48 100644 --- a/config/types.go +++ b/config/types.go @@ -4,8 +4,9 @@ import ( "encoding/base64" "encoding/json" - "github.com/pubgo/funk/log" "gopkg.in/yaml.v3" + + "github.com/pubgo/funk/v2/log" ) var ( @@ -22,7 +23,7 @@ func (c *Node) YamlNode() *yaml.Node { return c.value } -func (c *Node) MarshalYAML() (interface{}, error) { +func (c *Node) MarshalYAML() (any, error) { return c.value, nil } @@ -87,7 +88,7 @@ var ( type Base64File string -func (b *Base64File) MarshalYAML() (interface{}, error) { +func (b *Base64File) MarshalYAML() (any, error) { if b == nil || len(*b) == 0 { return nil, nil } diff --git a/config/util.go b/config/util.go index 10e01f0d..eaa00915 100644 --- a/config/util.go +++ b/config/util.go @@ -17,22 +17,14 @@ import ( "github.com/valyala/fasttemplate" "gopkg.in/yaml.v3" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/env" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/pathutil" - "github.com/pubgo/funk/result" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/env" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/pathutil" + "github.com/pubgo/funk/v2/result" ) -func GetConfigDir() string { - return configDir -} - -func GetConfigPath() string { - return configPath -} - func getConfigPath(name, typ string, configDir ...string) (string, string) { if len(configDir) == 0 { configDir = append(configDir, "./", defaultConfigPath) @@ -73,24 +65,19 @@ func getPathList() (paths []string) { paths = append(paths, wd) wd = filepath.Dir(wd) } - return + return paths } -func SetConfigPath(confPath string) { - assert.If(confPath == "", "config path is null") - configPath = confPath -} - -func MergeR[A any, B any | *any](dst *A, src ...B) (ret result.Result[*A]) { +func MergeR[A any, B any | *any](dst *A, src ...B) (r result.Result[*A]) { if len(src) == 0 { - return ret.WithVal(dst) + return r.WithValue(dst) } err := Merge(dst, src...) if err != nil { - return ret.WithErr(err) + return r.WithErr(err) } - return ret.WithVal(dst) + return r.WithValue(dst) } func Merge[A any, B any | *any](dst *A, src ...B) error { @@ -138,7 +125,7 @@ func (s *transformer) Transformer(t reflect.Type) func(dst, src reflect.Value) e for i := 0; i < src.Len(); i++ { c := src.Index(i).Interface() - var uniqueName = c.(NamedConfig).ConfigUniqueName() + uniqueName := c.(NamedConfig).ConfigUniqueName() if dstMap[uniqueName] == nil { dstMap[uniqueName] = c continue @@ -158,7 +145,7 @@ func (s *transformer) Transformer(t reflect.Type) func(dst, src reflect.Value) e } } - var data = lo.MapToSlice(dstMap, func(key string, value any) reflect.Value { return reflect.ValueOf(value) }) + data := lo.MapToSlice(dstMap, func(key string, value any) reflect.Value { return reflect.ValueOf(value) }) dst.Set(makeList(dst.Type().Elem(), data)) return nil } @@ -182,11 +169,11 @@ func unmarshalOneOrList[T any](list *[]T, value *yaml.Node) error { func listAllPath(dirOrPath string) (ret result.Result[[]string]) { if !pathutil.IsDir(dirOrPath) { - return ret.WithVal([]string{dirOrPath}) + return ret.WithValue([]string{dirOrPath}) } var paths []string - var walk = func(path string, info fs.FileInfo, err error) error { + walk := func(path string, info fs.FileInfo, err error) error { if err != nil { return err } @@ -202,11 +189,11 @@ func listAllPath(dirOrPath string) (ret result.Result[[]string]) { if err != nil { return ret.WithErr(err) } - return ret.WithVal(paths) + return ret.WithValue(paths) } func makeList(typ reflect.Type, data []reflect.Value) reflect.Value { - val := reflect.MakeSlice(reflect.SliceOf(typ), 0, 0) + val := reflect.MakeSlice(reflect.SliceOf(typ), 0, len(data)) return reflect.Append(val, data...) } @@ -226,10 +213,7 @@ func RegisterExpr(name string, expr any) { func getEnvData(cfg *config) map[string]any { exprEnv := map[string]any{ "env": env.Map(), - "get_path_dir": func() string { - return cfg.workDir - }, - "path_dir": func() string { + "config_dir": func() string { return cfg.workDir }, "embed": func(name string) string { @@ -237,8 +221,8 @@ func getEnvData(cfg *config) map[string]any { return "" } - var path = filepath.Join(cfg.workDir, name) - var d, err = os.ReadFile(path) + path := filepath.Join(cfg.workDir, name) + d, err := os.ReadFile(path) if err != nil { log.Panic().Err(err). Str("path", path). diff --git a/config/util_test.go b/config/util_test.go index a3ef1dc0..75e9e5b6 100644 --- a/config/util_test.go +++ b/config/util_test.go @@ -9,9 +9,10 @@ import ( "testing" "github.com/a8m/envsubst" - "github.com/pubgo/funk/env" "github.com/stretchr/testify/assert" "gopkg.in/yaml.v3" + + "github.com/pubgo/funk/v2/env" ) type testCfg struct { @@ -34,9 +35,9 @@ func TestExpr(t *testing.T) { assert.Equal(t, string(cfgFormat([]byte("${{env.TEST_ABC}}"), &config{})), "hello") assert.Equal(t, string(cfgFormat([]byte(`${{embed("configs/assets/secret")}}`), &config{})), strings.TrimSpace(`MTIzNDU2CjEyMzQ1NgoxMjM0NTYKMTIzNDU2CjEyMzQ1NgoxMjM0NTYKMTIzNDU2CjEyMzQ1Ng==`)) - var dd, err = os.ReadFile("configs/assets/assets.yaml") + dd, err := os.ReadFile("configs/assets/assets.yaml") assert.NoError(t, err) - var dd1 = bytes.TrimSpace(cfgFormat(dd, &config{workDir: "configs/assets"})) + dd1 := bytes.TrimSpace(cfgFormat(dd, &config{workDir: "configs/assets"})) var cfg testCfg assert.NoError(t, yaml.Unmarshal(dd1, &cfg)) @@ -53,10 +54,6 @@ func TestEnv(t *testing.T) { data, err = envsubst.String("${hello:-abc}") assert.Nil(t, err) assert.Equal(t, data, "abc") - - data, err = envsubst.String("${{hello:-abc}}") - assert.Nil(t, err) - assert.Equal(t, data, "${{hello:-abc}}") } func TestConfigPath(t *testing.T) { diff --git a/convert/copy.go b/convert/copy.go index 008304d9..4cc526bd 100644 --- a/convert/copy.go +++ b/convert/copy.go @@ -39,7 +39,7 @@ func BtoU4(b []byte) (i []uint32) { I.Data = B.Data I.Len = B.Len >> 2 I.Cap = I.Len - return + return i } // U4toB converts integer slice to byte slice @@ -49,7 +49,7 @@ func U4toB(i []uint32) (b []byte) { B.Data = I.Data B.Len = I.Len << 2 B.Cap = B.Len - return + return b } // U4toU8 converts uint32 slice to uint64 slice @@ -59,7 +59,7 @@ func U4toU8(i []uint32) (k []uint64) { K.Data = I.Data K.Len = I.Len >> 1 K.Cap = K.Len - return + return k } // U8toU4 converts uint64 slice to uint32 slice @@ -69,7 +69,7 @@ func U8toU4(i []uint64) (k []uint32) { K.Data = I.Data K.Len = I.Len << 1 K.Cap = K.Len - return + return k } // BtoU8 converts byte slice to integer slice @@ -79,7 +79,7 @@ func BtoU8(b []byte) (i []uint64) { I.Data = B.Data I.Len = B.Len >> 3 I.Cap = I.Len - return + return i } // U8toB converts integer slice to byte slice @@ -89,7 +89,7 @@ func U8toB(i []uint64) (b []byte) { B.Data = I.Data B.Len = I.Len << 3 B.Cap = B.Len - return + return b } // StoU4 converts string to integer slice @@ -99,7 +99,7 @@ func StoU4(s string) (i []uint32) { I.Data = S.Data I.Len = S.Len >> 2 I.Cap = I.Len - return + return i } // U4toS converts integer slice to string @@ -108,7 +108,7 @@ func U4toS(i []uint32) (s string) { S := (*String)(unsafe.Pointer(&s)) S.Data = I.Data S.Len = I.Len << 2 - return + return s } // StoU8 converts string to integer slice @@ -118,7 +118,7 @@ func StoU8(s string) (i []uint64) { I.Data = S.Data I.Len = S.Len >> 3 I.Cap = I.Len - return + return i } // U8toS converts integer slice to string @@ -127,5 +127,5 @@ func U8toS(i []uint64) (s string) { S := (*String)(unsafe.Pointer(&s)) S.Data = I.Data S.Len = I.Len << 3 - return + return s } diff --git a/convert/unsafe.go b/convert/unsafe.go index 5d7c14f6..7eb71630 100644 --- a/convert/unsafe.go +++ b/convert/unsafe.go @@ -18,7 +18,7 @@ func BtoS(b []byte) (s string) { S := (*String)(unsafe.Pointer(&s)) S.Data = B.Data S.Len = B.Len - return + return s } // StoB converts string to byte slice @@ -28,5 +28,5 @@ func StoB(s string) (b []byte) { B.Data = S.Data B.Len = S.Len B.Cap = B.Len - return + return b } diff --git a/cryptoutil/util.go b/cryptoutil/util.go index f28fd885..bf3b3bf1 100644 --- a/cryptoutil/util.go +++ b/cryptoutil/util.go @@ -13,10 +13,11 @@ import ( "io" "strings" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/result" "golang.org/x/crypto/bcrypt" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/result" ) // SecureKey generates a random 256-bit key for Encrypt() and @@ -67,7 +68,7 @@ func AesCBCEncrypt(orig, key string) result.Result[string] { cryted := make([]byte, len(origData)) // 加密 blockMode.CryptBlocks(cryted, origData) - return val.WithVal(base64.StdEncoding.EncodeToString(cryted)) + return val.WithValue(base64.StdEncoding.EncodeToString(cryted)) } func AesCBCDecrypt(cryted, key string) result.Result[string] { @@ -76,7 +77,7 @@ func AesCBCDecrypt(cryted, key string) result.Result[string] { // 转成字节数组 crytedByte, err := base64.StdEncoding.DecodeString(cryted) if err != nil { - return result.Err[string](err) + return result.Fail[string](err) } k := []byte(key) @@ -96,7 +97,7 @@ func AesCBCDecrypt(cryted, key string) result.Result[string] { blockMode.CryptBlocks(orig, crytedByte) // 去补全码 orig = PKCS7UnPadding(orig) - return val.WithVal(string(orig)) + return val.WithValue(string(orig)) } // PKCS7Padding 补码 diff --git a/ctxutil/util_test.go b/ctxutil/util_test.go index 892445f9..c3ec691e 100644 --- a/ctxutil/util_test.go +++ b/ctxutil/util_test.go @@ -4,8 +4,9 @@ import ( "context" "testing" - "github.com/pubgo/funk/ctxutil" "github.com/stretchr/testify/assert" + + "github.com/pubgo/funk/v2/ctxutil" ) func TestClone(t *testing.T) { diff --git a/env/env.go b/env/env.go index f41da03a..de21ad00 100644 --- a/env/env.go +++ b/env/env.go @@ -2,128 +2,202 @@ package env import ( "fmt" - "log/slog" "os" "strconv" "strings" "github.com/a8m/envsubst" "github.com/joho/godotenv" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/pathutil" - "github.com/pubgo/funk/v2/result" + "github.com/rs/zerolog" "github.com/samber/lo" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/log/logfields" + "github.com/pubgo/funk/v2/pathutil" + "github.com/pubgo/funk/v2/result" ) +const Name = "env" + func Set(key, value string) result.Error { - return result.ErrOf(os.Setenv(KeyHandler(key), value)) + return result.ErrOf(os.Setenv(keyHandler(key), value)). + Log(func(e *zerolog.Event) { + e.Str("key", key) + e.Str("value", value) + e.Str(logfields.Msg, "env_set_error") + }) } -func GetDefault(name string, defaultVal string) string { - val := Get(name) - return lo.If(val != "", val).Else(defaultVal) -} +func MustSet(key, value string) { Set(key, value).Must() } func Get(names ...string) string { var val string - GetVal(&val, names...) - return trim(val) + getVal(&val, names...) + return val } func MustGet(names ...string) string { - var val string - GetVal(&val, names...) - assert.If(val == "", "env not found, names=%q", names) - return trim(val) + val := Get(names...) + assert.If(val == "", "env value not set, names=%q", names) + return val +} + +func GetOr(name, defaultVal string) string { + val := Get(name) + return lo.If(val != "", val).Else(defaultVal) } -func GetVal(val *string, names ...string) { +func GetWith(val *string, names ...string) { getVal(val, names...) } + +func getVal(val *string, names ...string) { for _, name := range names { - env, ok := Lookup(name) - env = trim(env) - if ok && env != "" { - *val = trim(env) - break + env := trim(os.Getenv(keyHandler(name))) + if env == "" { + continue } + + *val = env + break } } -func GetBoolVal(val *bool, names ...string) { - dt := trim(Get(names...)) - if dt == "" { - return +func GetBool(names ...string) bool { + var val string + getVal(&val, names...) + if val == "" { + return false } - v, err := strconv.ParseBool(dt) + v, err := strconv.ParseBool(val) if err != nil { - slog.Error(fmt.Sprintf("env: failed to parse string to bool, keys=%q value=%s err=%v", names, dt, err)) - return + getLog().Error("failed to parse string to bool", "keys", names, "value", val, "err", err) + return false } - *val = v + return v } -func GetIntVal(val *int, names ...string) { - dt := trim(Get(names...)) - if dt == "" { - return +func GetInt(names ...string) int { + var val string + getVal(&val, names...) + if val == "" { + return -1 } - v, err := strconv.Atoi(dt) + v, err := strconv.Atoi(val) if err != nil { - slog.Error(fmt.Sprintf("env: failed to parse string to int, keys=%q value=%s err=%v", names, dt, err)) - return + getLog().Error("failed to parse string to int", "keys", names, "value", val, "err", err) + return -1 } - *val = v + return v } -func GetFloatVal(val *float64, names ...string) { - dt := trim(Get(names...)) - if dt == "" { - return +func GetFloat(names ...string) float64 { + var val string + getVal(&val, names...) + if val == "" { + return -1 } - v, err := strconv.ParseFloat(dt, 64) + v, err := strconv.ParseFloat(val, 64) if err != nil { - slog.Error(fmt.Sprintf("env: failed to parse string to float, keys=%q value=%s err=%v", names, dt, err)) - return + getLog().Error("failed to parse string to float", "keys", names, "value", val, "err", err) + return -1 } - *val = v + return v } -func Lookup(key string) (string, bool) { - return os.LookupEnv(Key(key)) -} +func Lookup(key string) (string, bool) { return os.LookupEnv(keyHandler(key)) } func Delete(key string) result.Error { - return result.ErrOf(os.Unsetenv(Key(key))) + return result.ErrOf(os.Unsetenv(keyHandler(key))). + Log(func(e *zerolog.Event) { + e.Str("key", key) + e.Str(logfields.Msg, "env_delete_error") + }) } +func MustDelete(key string) { Delete(key).Must() } + func Expand(value string) result.Result[string] { - return result.Wrap(envsubst.String(value)) + return result.Wrap(envsubst.String(value)). + Log(func(e *zerolog.Event) { + e.Str("value", value) + e.Str(logfields.Msg, "env_expand_error") + }) } func Map() map[string]string { data := make(map[string]string, len(os.Environ())) for _, env := range os.Environ() { envs := strings.SplitN(env, "=", 2) - data[envs[0]] = envs[1] + if len(envs) != 2 { + continue + } + + data[keyHandler(envs[0])] = envs[1] } return data } func Key(key string) string { - return KeyHandler(key) + return keyHandler(key) } func LoadFiles(files ...string) (r result.Error) { files = lo.Filter(files, func(item string, index int) bool { return pathutil.IsExist(item) }) - if result.CatchErr(&r, godotenv.Load(files...)) { - return + if len(files) == 0 { + return r + } + + var needReloadEnv bool + for _, file := range files { + data := result.Wrap(os.ReadFile(file)). + Log(func(e *zerolog.Event) { + e.Str(logfields.Msg, fmt.Sprintf("failed to read file:%s", file)) + }). + Unwrap(&r) + if r.IsErr() { + return r + } + + dataMap := result.Wrap(godotenv.UnmarshalBytes(data)). + Log(func(e *zerolog.Event) { + e.Str(logfields.Msg, fmt.Sprintf("failed to parse env file:%s", file)) + }). + Unwrap(&r) + if r.IsErr() { + return r + } + + for k, v := range dataMap { + if k == "" || v == "" { + continue + } + + if Set(k, v).Catch(&r) { + return r + } + + needReloadEnv = true + } + } + + if needReloadEnv { + loadEnv() + } + + return r +} + +// Normalize a-b=>a_b, a.b=>a_b, a/b=>a_b +func Normalize(key string) (string, bool) { + key = trim(key) + if key == "" || strings.HasPrefix(key, "_") || strings.HasPrefix(key, "=") { + return key, false } - loadEnv() - return + return keyHandler(key), true } diff --git a/env/reload.go b/env/reload.go index 9c4cb993..64810a18 100644 --- a/env/reload.go +++ b/env/reload.go @@ -1,55 +1,44 @@ package env import ( + "fmt" + "log/slog" "os" "strings" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" + "github.com/pubgo/funk/v2/assert" ) func Reload() { loadEnv() } -// Init reload env -// Deprecated: use Reload instead. -func Init() { - loadEnv() -} - // 环境变量处理, key转大写, 同时把`-./`转换为`_` // a-b=>a_b, a.b=>a_b, a/b=>a_b func loadEnv() { - envPrefix := getEnvPrefix() - logger := log.With().Str("operation", "reload_env").Logger() - envPrefixEventFn := func(e *zerolog.Event) { - e.Dict("env_prefix", zerolog.Dict().Str("key", PrefixKey).Str("value", envPrefix)) - } - logRecord(logger.Info(), envPrefixEventFn).Msg("reload env") + logger := getLog() + logger.Info("reload env") for _, env := range os.Environ() { kvs := strings.SplitN(env, "=", 2) if len(kvs) != 2 { - logRecord(logger.Error()).Msg("split env error") - continue - } - - envKey := trim(kvs[0]) - _ = os.Unsetenv(envKey) - - if envKey == "" || - strings.HasPrefix(envKey, "_") || - strings.HasPrefix(envKey, "=") || - !hasEnvPrefix(envKey, envPrefix) { - logRecord(logger.Warn()).Msgf("unset env, key=%s", envKey) + logger.Error("split env error", slog.String("env", env)) continue } - key, ok := Normalize(envKey) + oldKey := trim(kvs[0]) + newKey, ok := Normalize(oldKey) if ok { - setOk := os.Setenv(key, kvs[1]) == nil - logRecord(logger.Info()).Msgf("reset env, old_key=%s new_key=%s set_ok=%v", envKey, key, setOk) + if newKey == oldKey { + continue + } + + assert.Exit(os.Unsetenv(oldKey)) + assert.Exit(os.Setenv(newKey, kvs[1])) + logger.Info(fmt.Sprintf("reset env, old_key=%s new_key=%s", oldKey, newKey)) + } else { + logger.Warn(fmt.Sprintf("unset env, key=%s", oldKey)) + assert.Exit(os.Unsetenv(oldKey)) } } } diff --git a/env/util.go b/env/util.go index ca2f5544..48860465 100644 --- a/env/util.go +++ b/env/util.go @@ -1,64 +1,31 @@ package env import ( - "os" + "log/slog" "strings" + "sync" "github.com/ettle/strcase" - "github.com/rs/zerolog" - - "github.com/pubgo/funk/log/logfields" - "github.com/pubgo/funk/log/logutil" ) -var logFn = func(e *zerolog.Event) { - e.Str(logfields.Module, "env") -} - -const PrefixKey = "ENV_PREFIX" - -func hasEnvPrefix(key string, prefix string) bool { - return strings.HasPrefix(strings.ToUpper(key), strings.ToUpper(prefix)) -} - -func getEnvPrefix() string { - prefix := strings.TrimSpace(os.Getenv(PrefixKey)) - if prefix != "" { - prefix = strings.ReplaceAll(prefix+"_", "__", "_") - } - return strings.ToUpper(prefix) -} - -var trim = strings.TrimSpace -var replacer = strcase.NewCaser( - true, - map[string]bool{"SSL": true, "HTML": false}, - strcase.NewSplitFn( - []rune{'*', '.', ',', '-', '/'}, - strcase.SplitCase, - strcase.SplitAcronym, - strcase.PreserveNumberFormatting, - )) - -func KeyHandler(key string) string { - key = strings.ToUpper(replacer.ToSNAKE(key)) - envPrefix := getEnvPrefix() - if envPrefix != "" { - key = envPrefix + "_" + strings.TrimPrefix(key, envPrefix) - } - return strings.ToUpper(trim(strings.ReplaceAll(key, "__", "_"))) -} - -// Normalize a-b=>a_b, a.b=>a_b, a/b=>a_b -func Normalize(key string) (string, bool) { - key = trim(key) - if key == "" || strings.HasPrefix(key, "_") || strings.HasPrefix(key, "=") { - return key, false - } +var ( + trim = strings.TrimSpace + replacer = strcase.NewCaser( + true, + map[string]bool{"SSL": true, "HTML": false}, + strcase.NewSplitFn( + []rune{'*', '.', ',', '-', '/'}, + strcase.SplitCase, + strcase.SplitAcronym, + strcase.PreserveNumberFormatting, + )) +) - return KeyHandler(key), true +func keyHandler(key string) string { + key = strings.ReplaceAll(replacer.ToSNAKE(key), "__", "_") + return strings.ToUpper(trim(key)) } -func logRecord(evt *zerolog.Event, funcs ...func(e *zerolog.Event)) *zerolog.Event { - return logutil.Record(evt, append(funcs, logFn)...) -} +var getLog = sync.OnceValue(func() *slog.Logger { + return slog.Default().WithGroup(Name) +}) diff --git a/env/util_test.go b/env/util_test.go index b231df49..25521809 100644 --- a/env/util_test.go +++ b/env/util_test.go @@ -1,18 +1,27 @@ package env_test import ( + "log/slog" "os" - "strings" "testing" - "github.com/pubgo/funk/env" - "github.com/pubgo/funk/pretty" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "github.com/samber/lo" "github.com/stretchr/testify/assert" + + "github.com/pubgo/funk/v2/env" + "github.com/pubgo/funk/v2/log" ) +func init() { + slog.SetDefault(slog.New(log.NewSlog(log.GetLogger("")))) +} + +func TestResetEnv(t *testing.T) { + assert.NoError(t, os.Setenv("abc", "1")) + assert.Equal(t, os.Getenv("abc"), "1") + assert.NoError(t, os.Setenv("abc", "2")) + assert.Equal(t, os.Getenv("abc"), "2") +} + func TestNormalize(t *testing.T) { k, ok := env.Normalize("aA-bS3_AK/c.d") assert.True(t, ok) @@ -20,20 +29,11 @@ func TestNormalize(t *testing.T) { } func TestEnvPrefix(t *testing.T) { - log.Logger = log.Hook(zerolog.HookFunc(func(e *zerolog.Event, level zerolog.Level, message string) { - if strings.HasPrefix(message, "unset not match env") { - e.Discard() - } - })) - env.Reload() - pretty.Println("env_keys", lo.Keys(env.Map())) - env.Set(env.PrefixKey, "test").Must() - env.Set("test_hello", "world").Must() + env.MustSet("test_hello", "world") env.Reload() envMap := env.Map() assert.Equal(t, envMap["TEST_HELLO"], "world") - pretty.Println(os.Environ()) } diff --git a/errors/aaa.go b/errors/aaa.go index 5fe40d0d..aa81e6d4 100644 --- a/errors/aaa.go +++ b/errors/aaa.go @@ -1,15 +1,17 @@ package errors import ( - "github.com/pubgo/funk/errors/errinter" + "github.com/pubgo/funk/v2/internal/errors/errinter" ) -type Maps = errinter.Maps -type Tags = errinter.Tags -type Tag = errinter.Tag -type ErrIs = errinter.ErrIs -type ErrAs = errinter.ErrAs -type ErrUnwrap = errinter.ErrUnwrap -type Error = errinter.Error -type ErrorProto = errinter.ErrorProto -type GRPCStatus = errinter.GRPCStatus +type ( + Maps = errinter.Maps + Tags = errinter.Tags + Tag = errinter.Tag + ErrIs = errinter.ErrIs + ErrAs = errinter.ErrAs + ErrUnwrapper = errinter.ErrUnwrapper + Error = errinter.Error + ErrorProto = errinter.ErrorProto + GRPCStatus = errinter.GRPCStatus +) diff --git a/errors/err_code.go b/errors/err_code.go index 819fdec4..be3aebea 100644 --- a/errors/err_code.go +++ b/errors/err_code.go @@ -7,13 +7,14 @@ import ( "fmt" "strings" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/proto/errorpb" - "github.com/pubgo/funk/stack" "github.com/samber/lo" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" + + "github.com/pubgo/funk/v2/internal/errors/errinter" + + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/proto/errorpb" ) func NewCodeErrWithMap(code *errorpb.ErrCode, details ...map[string]any) error { @@ -22,7 +23,7 @@ func NewCodeErrWithMap(code *errorpb.ErrCode, details ...map[string]any) error { return nil } - var detailMaps = make(map[string]any) + detailMaps := make(map[string]any) for _, detail := range details { for k, v := range detail { detailMaps[k] = v @@ -51,7 +52,7 @@ func NewCodeErrWithMsg(code *errorpb.ErrCode, msg string, details ...proto.Messa func NewCodeErr(code *errorpb.ErrCode, details ...proto.Message) error { code = cloneAndCheck(code) - if generic.IsNil(code) { + if funk.IsNil(code) { return nil } @@ -61,7 +62,7 @@ func NewCodeErr(code *errorpb.ErrCode, details ...proto.Message) error { if len(details) > 0 { for _, p := range details { - if p == nil || generic.IsNil(p) { + if p == nil || funk.IsNil(p) { continue } @@ -91,13 +92,10 @@ func WrapCode(err error, code *errorpb.ErrCode) error { } code.Details = append(code.Details, MustProtoToAny(ParseErrToPb(err))) - return &ErrWrap{ - err: &ErrCode{pb: code, err: errors.New(code.Message)}, - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(code), - }, - } + return newErrWrap( + &ErrCode{pb: code, err: errors.New(code.Message)}, + Tags{Kv("msg", err.Error())}, + ) } var ( @@ -126,10 +124,9 @@ func (t *ErrCode) Is(err error) bool { return true } - var check = func(err2 *ErrCode) bool { - return err2.pb.Code == t.pb.Code && err2.pb.Name == t.pb.Name + check := func(errCode *ErrCode) bool { + return errCode.pb.Code == t.pb.Code && errCode.pb.Name == t.pb.Name } - if err1, ok := err.(*ErrCode); ok && check(err1) { return true } diff --git a/errors/err_msg.go b/errors/err_msg.go index 47856902..5a293bb7 100644 --- a/errors/err_msg.go +++ b/errors/err_msg.go @@ -6,16 +6,16 @@ import ( "errors" "fmt" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/proto/errorpb" - "github.com/pubgo/funk/stack" "github.com/samber/lo" "google.golang.org/protobuf/proto" + + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/internal/errors/errinter" + "github.com/pubgo/funk/v2/proto/errorpb" ) func NewMsgErr(msg *errorpb.ErrMsg) error { - if generic.IsNil(msg) { + if funk.IsNil(msg) { return nil } @@ -39,13 +39,10 @@ func WrapMsg(err error, msg *errorpb.ErrMsg) error { msg.Id = lo.ToPtr(getErrorId(err)) } - return &ErrWrap{ - err: &ErrMsg{pb: msg, err: handleGrpcError(err)}, - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(msg), - }, - } + return newErrWrap( + &ErrMsg{pb: msg, err: handleGrpcError(err)}, + Tags{Kv("msg", err.Error())}, + ) } var ( diff --git a/errors/err_simple.go b/errors/err_simple.go index 466ef887..31524730 100644 --- a/errors/err_simple.go +++ b/errors/err_simple.go @@ -5,16 +5,17 @@ import ( "encoding/json" "fmt" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/proto/errorpb" "github.com/rs/xid" "github.com/samber/lo" "google.golang.org/protobuf/proto" + + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/internal/errors/errinter" + "github.com/pubgo/funk/v2/proto/errorpb" ) func NewErr(msg *Err) error { - if generic.IsNil(msg) { + if funk.IsNil(msg) { return nil } diff --git a/errors/err_wrap.go b/errors/err_wrap.go index 8ff546cb..2c829373 100644 --- a/errors/err_wrap.go +++ b/errors/err_wrap.go @@ -5,9 +5,13 @@ import ( "encoding/json" "fmt" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/proto/errorpb" + "github.com/samber/lo" "google.golang.org/protobuf/proto" + + "github.com/pubgo/funk/v2/internal/errors/errinter" + + "github.com/pubgo/funk/v2/proto/errorpb" + "github.com/pubgo/funk/v2/stack" ) var ( @@ -15,23 +19,44 @@ var ( _ fmt.Formatter = (*ErrWrap)(nil) ) -type ErrWrap struct { - err error - id string - pb *errorpb.ErrWrap +func newErrWrapStack(err error, tags Tags) *ErrWrap { + if err == nil { + return nil + } + + pb := &errorpb.ErrWrap{ + Caller: stack.Caller(2).String(), + Stacks: lo.Map(getStack(), func(item *stack.Frame, index int) string { return item.String() }), + Error: MustProtoToAny(ParseErrToPb(err)), + Tags: tags.ToMap(), + Id: lo.ToPtr(getErrorId(err)), + } + + return &ErrWrap{err: err, pb: pb} } -func (e *ErrWrap) ID() string { - if e.id != "" { - return e.id +func newErrWrap(err error, tags Tags, callers ...int) *ErrWrap { + if err == nil { + return nil + } + + pb := &errorpb.ErrWrap{ + Caller: stack.Caller(2 + lo.FirstOrEmpty(callers)).String(), + Error: MustProtoToAny(ParseErrToPb(err)), + Tags: tags.ToMap(), + Id: lo.ToPtr(getErrorId(err)), } - e.id = getErrorId(e.err) - return e.id + return &ErrWrap{err: handleGrpcError(err), pb: pb} } -func (e *ErrWrap) Proto() proto.Message { - return e.pb + +type ErrWrap struct { + err error + pb *errorpb.ErrWrap } + +func (e *ErrWrap) ID() string { return e.pb.GetId() } +func (e *ErrWrap) Proto() proto.Message { return e.pb } func (e *ErrWrap) Format(f fmt.State, verb rune) { strFormat(f, verb, e) } func (e *ErrWrap) Unwrap() error { return e.err } func (e *ErrWrap) Kind() string { return "err_wrap" } diff --git a/errors/errcheck/check.go b/errors/errcheck/check.go deleted file mode 100644 index 59253c3e..00000000 --- a/errors/errcheck/check.go +++ /dev/null @@ -1,107 +0,0 @@ -package errcheck - -import ( - "context" - "fmt" - - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log" - "github.com/samber/lo" -) - -func RecoveryAndCheck(setter *error, callbacks ...func(err error) error) { - if setter == nil { - errMust(fmt.Errorf("setter is nil")) - return - } - - err := errors.Parse(recover()) - gErr := *setter - if err == nil && gErr == nil { - return - } - - if err == nil { - err = gErr - } - - for _, fn := range callbacks { - err = fn(err) - if err == nil { - return - } - } - - *setter = errors.WrapCaller(err, 1) -} - -func Check(errSetter *error, err error, contexts ...context.Context) bool { - if errSetter == nil { - errMust(fmt.Errorf("errSetter is nil")) - return false - } - - if err == nil { - return false - } - - if (*errSetter) != nil { - log.Err(*errSetter).Msgf("errcheck: setter is not nil, err=%v", *errSetter) - return true - } - - var ctx = lo.FirstOr(contexts, context.Background()) - for _, fn := range GetCheckersFromCtx(ctx) { - err = fn(ctx, err) - if err == nil { - return false - } - } - - *errSetter = errors.WrapCaller(err, 1) - return true -} - -func Expect(err error, format string, args ...any) { - if err == nil { - return - } - - err = errors.WrapCaller(err, 1) - err = errors.Wrapf(err, format, args...) - errMust(err) -} - -func Map(err error, fn func(err error) error) error { - if err == nil { - return nil - } - - return errors.WrapCaller(fn(err), 1) -} - -func Inspect(err error, fn func(err error)) { - if err == nil { - return - } - - fn(err) -} - -func InspectLog(err error, fn func(logger *log.Event), contexts ...context.Context) { - if err == nil { - return - } - - fn(log.Err(err, contexts...)) -} - -func LogErr(err error, contexts ...context.Context) { - if err == nil { - return - } - - log.Err(err, contexts...). - CallerSkipFrame(1). - Msg(err.Error()) -} diff --git a/errors/errcheck/context.go b/errors/errcheck/context.go deleted file mode 100644 index 32835ef9..00000000 --- a/errors/errcheck/context.go +++ /dev/null @@ -1,39 +0,0 @@ -package errcheck - -import ( - "context" - - "github.com/samber/lo" -) - -type checkCtx struct{} - -type ErrChecker func(context.Context, error) error - -func CreateCtx(ctx context.Context, errChecks []ErrChecker, upsert ...bool) context.Context { - if ctx == nil { - ctx = context.Background() - } - - if lo.FirstOrEmpty(upsert) { - checkers, ok := ctx.Value(checkCtx{}).([]ErrChecker) - if ok { - errChecks = append(errChecks, checkers...) - } - } - - return context.WithValue(ctx, checkCtx{}, errChecks) -} - -func GetCheckersFromCtx(ctx context.Context) []ErrChecker { - if ctx == nil { - return nil - } - - checkers, ok := ctx.Value(checkCtx{}).([]ErrChecker) - if !ok { - return nil - } - - return checkers -} diff --git a/errors/errcheck/util.go b/errors/errcheck/util.go deleted file mode 100644 index 0f061e57..00000000 --- a/errors/errcheck/util.go +++ /dev/null @@ -1,21 +0,0 @@ -package errcheck - -import ( - "fmt" - - "github.com/pubgo/funk/errors" -) - -func errMust(err error, args ...any) { - if err == nil { - return - } - - if len(args) > 0 { - err = errors.Wrap(err, fmt.Sprint(args...)) - } - - err = errors.WrapStack(err) - errors.Debug(err) - panic(err) -} diff --git a/errors/errinter/color_name.go b/errors/errinter/color_name.go deleted file mode 100644 index c360bf64..00000000 --- a/errors/errinter/color_name.go +++ /dev/null @@ -1,36 +0,0 @@ -package errinter - -import ( - "strings" - - "github.com/pubgo/funk/internal/color" -) - -var width = 11 - -func Get(name string) string { - if width-len(name) < 0 { - return name - } - return strings.Repeat(" ", width-len(name)) + name -} - -var ( - ColorKind = color.Green.Str(Get("kind")) - ColorMsg = color.Green.Str(Get("msg")) - ColorService = color.Green.Str(Get("service")) - ColorOperation = color.Green.Str(Get("operation")) - ColorId = color.Green.Str(Get("id")) - ColorDetail = color.Green.Str(Get("detail")) - ColorTags = color.Green.Str(Get("tags")) - ColorErrMsg = color.Red.Str(Get("err_msg")) - ColorErrDetail = color.Red.Str(Get("err_detail")) - ColorCaller = color.Green.Str(Get("caller")) - ColorCode = color.Green.Str(Get("code")) - ColorMessage = color.Green.Str(Get("message")) - ColorBiz = color.Green.Str(Get("biz_code")) - ColorStatusCode = color.Green.Str(Get("status_code")) - ColorName = color.Green.Str(Get("name")) - ColorStack = color.Green.Str(Get("stack")) - ColorVersion = color.Green.Str(Get("version")) -) diff --git a/errors/registry.go b/errors/errorcodes/registry.go similarity index 87% rename from errors/registry.go rename to errors/errorcodes/registry.go index 0a48c6a6..fcf6f3bd 100644 --- a/errors/registry.go +++ b/errors/errorcodes/registry.go @@ -1,9 +1,9 @@ -package errors +package errorcodes import ( "fmt" - "github.com/pubgo/funk/proto/errorpb" + "github.com/pubgo/funk/v2/proto/errorpb" ) var codes = make(map[string]*errorpb.ErrCode) diff --git a/errors/errors.go b/errors/errors.go index 1f8768c5..a0fdc614 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -4,16 +4,16 @@ import ( "errors" "fmt" "reflect" - "runtime/debug" "github.com/rs/xid" "github.com/samber/lo" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/proto/errorpb" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2/internal/errors/errinter" + + "github.com/pubgo/funk/v2/proto/errorpb" + "github.com/pubgo/funk/v2/stack" ) func IfErr(err error, fn func(err error) error) error { @@ -28,71 +28,19 @@ func New(msg string, tags ...Tag) error { return WrapCaller(&Err{Msg: msg, id: xid.New().String(), Tags: tags}, 1) } -// NewFmt -// Deprecated: use Errorf instead -func NewFmt(msg string, args ...interface{}) error { - return WrapCaller(&Err{Msg: fmt.Sprintf(msg, args...), id: xid.New().String()}, 1) -} - -// Format -// Deprecated: use Errorf instead -func Format(msg string, args ...interface{}) error { - return WrapCaller(&Err{Msg: fmt.Sprintf(msg, args...), id: xid.New().String()}, 1) -} - -func Errorf(msg string, args ...interface{}) error { +func Errorf(msg string, args ...any) error { return WrapCaller(&Err{Msg: fmt.Sprintf(msg, args...), id: xid.New().String()}, 1) } -func Parse(val interface{}) error { return errinter.ParseError(val) } -func Debug(err error) { errinter.Debug(err) } - +func Parse(val any) error { return errinter.ParseError(val) } +func Debug(err error) { errinter.Debug(err) } func Is(err, target error) bool { return errors.Is(err, target) } func Join(errs ...error) error { return errors.Join(errs...) } - -func UnwrapEach(err error, call func(e error) bool) { - if err == nil { - return - } - - for { - if !call(err) { - return - } - - err1, ok := err.(ErrUnwrap) - if !ok { - return - } - - err = err1.Unwrap() - } -} - func AsA[T any](err error) (*T, bool) { var target T - val := reflect.ValueOf(&target) - typ := val.Type() - if typ.Kind() != reflect.Ptr || val.IsNil() { - panic("errors: target must be a non-nil pointer") - } - - targetType := typ.Elem() - for err != nil { - if reflect.TypeOf(err).AssignableTo(targetType) { - val.Elem().Set(reflect.ValueOf(err)) - return &target, true - } - - if x, ok := err.(ErrAs); ok && x.As(&target) { - return &target, true - } - - err = Unwrap(err) - } - return &target, false + return &target, As(err, &target) } func As(err error, target any) bool { @@ -123,7 +71,7 @@ func As(err error, target any) bool { } func Unwrap(err error) error { - u, ok := err.(ErrUnwrap) + u, ok := err.(ErrUnwrapper) if !ok { return nil } @@ -135,15 +83,8 @@ func WrapStack(err error) error { return nil } - debug.PrintStack() - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Stacks: lo.Map(getStack(), func(item *stack.Frame, index int) string { return item.String() }), - Error: MustProtoToAny(ParseErrToPb(err)), - }, - } + stack.PrintStack() + return newErrWrapStack(err, Tags{T("msg", err.Error())}) } func WrapCaller(err error, skip ...int) error { @@ -151,33 +92,15 @@ func WrapCaller(err error, skip ...int) error { return nil } - depth := 1 - if len(skip) > 0 { - depth += skip[0] - } - - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(depth).String(), - Error: MustProtoToAny(ParseErrToPb(err)), - }, - } + return newErrWrap(err, Tags{T("msg", err.Error())}, lo.FirstOrEmpty(skip)) } -func Wrapf(err error, format string, args ...interface{}) error { +func Wrapf(err error, format string, args ...any) error { if err == nil { return nil } - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(ParseErrToPb(err)), - Tags: Tags{T("msg", fmt.Sprintf(format, args...))}.ToMap(), - }, - } + return newErrWrap(err, Tags{T("msg", fmt.Sprintf(format, args...))}) } func Wrap(err error, msg string) error { @@ -185,14 +108,7 @@ func Wrap(err error, msg string) error { return nil } - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(ParseErrToPb(err)), - Tags: Tags{T("msg", msg)}.ToMap(), - }, - } + return newErrWrap(err, Tags{T("msg", msg)}) } func WrapMapTag(err error, tags Maps) error { @@ -204,14 +120,7 @@ func WrapMapTag(err error, tags Maps) error { return err } - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(ParseErrToPb(err)), - Tags: tags.Tags().ToMap(), - }, - } + return newErrWrap(err, tags.Tags()) } func WrapTag(err error, tags ...Tag) error { @@ -219,14 +128,7 @@ func WrapTag(err error, tags ...Tag) error { return nil } - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(ParseErrToPb(err)), - Tags: Tags(tags).ToMap(), - }, - } + return newErrWrap(err, tags) } func WrapFn(err error, fn func() Tags) error { @@ -234,14 +136,7 @@ func WrapFn(err error, fn func() Tags) error { return nil } - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(ParseErrToPb(err)), - Tags: fn().ToMap(), - }, - } + return newErrWrap(err, fn()) } func WrapKV(err error, key string, value any, kvs ...any) error { @@ -249,25 +144,16 @@ func WrapKV(err error, key string, value any, kvs ...any) error { return nil } - var tags = Tags{T(key, value)} + tags := Tags{T(key, value)} for i := 0; i < len(kvs); i += 2 { tags = append(tags, Tag{K: kvs[i].(string), V: kvs[i+1]}) } - return &ErrWrap{ - err: handleGrpcError(err), - pb: &errorpb.ErrWrap{ - Caller: stack.Caller(1).String(), - Error: MustProtoToAny(ParseErrToPb(err)), - Tags: Tags{T(key, value)}.ToMap(), - }, - } -} - -func T(k string, v any) Tag { - return Tag{K: k, V: v} + return newErrWrap(err, tags) } +func Kv(k string, v any) Tag { return Tag{K: k, V: v} } +func T(k string, v any) Tag { return Tag{K: k, V: v} } func MustTagsToAny(tags ...*errorpb.Tag) []*anypb.Any { return errinter.MustTagsToAny(tags...) } func MustStructToAny(p map[string]any) *anypb.Any { return errinter.MustStructToAny(p) } func MustProtoToAny(p proto.Message) *anypb.Any { return errinter.MustProtoToAny(p) } diff --git a/errors/errutil/retryable.go b/errors/errutil/retryable.go index e6831faa..e096a317 100644 --- a/errors/errutil/retryable.go +++ b/errors/errutil/retryable.go @@ -10,7 +10,7 @@ import ( // type, in string form, for optional logging and metrics use. func IsRetryableHTTP(err error) (retryType string, isRetryable bool) { if retryType, isRetryable = IsRetryableNetwork(err); isRetryable { - return + return retryType, isRetryable } errStr := err.Error() diff --git a/errors/errutil/util.go b/errors/errutil/util.go index 7e9a7571..02d47820 100644 --- a/errors/errutil/util.go +++ b/errors/errutil/util.go @@ -2,32 +2,30 @@ package errutil import ( "context" + "encoding/json" "fmt" "io" "net/http" "os" "strings" - jjson "github.com/goccy/go-json" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/anypb" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/proto/errorpb" - "github.com/pubgo/funk/version" + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/pretty" + "github.com/pubgo/funk/v2/proto/errorpb" ) func Json(err error) []byte { - if generic.IsNil(err) { + if err == nil { return nil } - err = errors.Parse(err) - data, err := jjson.Marshal(err) + data, err := json.Marshal(err) if err != nil { log.Err(err).Stack().Str("err_stack", pretty.SimplePrint(err)).Msg("failed to marshal error") panic(fmt.Errorf("failed to marshal error, err=%w", err)) @@ -36,12 +34,12 @@ func Json(err error) []byte { } func JsonPretty(err error) []byte { - if generic.IsNil(err) { + if err == nil { return nil } err = errors.Parse(err) - data, err := jjson.MarshalIndent(err, " ", " ") + data, err := json.MarshalIndent(err, " ", " ") if err != nil { log.Err(err).Stack().Str("err_stack", pretty.SimplePrint(err)).Msg("failed to marshal error") panic(fmt.Errorf("failed to marshal error, err=%w", err)) @@ -173,22 +171,18 @@ func GrpcCodeToHTTP(code codes.Code) int { } // ConvertErr2Status 内部转换,为了让err=nil的时候,监控数据里有OK信息 -func ConvertErr2Status(err *errorpb.Error) *status.Status { - if generic.IsNil(err) { +func ConvertErr2Status(errCode *errorpb.ErrCode) *status.Status { + if funk.IsNil(errCode) { return status.New(codes.OK, "OK") } - if err.Code == nil { - return status.New(codes.OK, "OK") + if (errCode.Name != "" || errCode.Code != 0) && errCode.StatusCode == 0 { + errCode.StatusCode = errorpb.Code_Internal } - if (err.Code.Name != "" || err.Code.Code != 0) && err.Code.StatusCode == 0 { - err.Code.StatusCode = errorpb.Code_Internal - } - - st := status.New(codes.Code(err.Code.StatusCode), err.Msg.Msg) - if st1, err1 := st.WithDetails(err); err1 != nil { - log.Err(err1).Any("lava-error", err).Msg("failed to convert error to grpc status") + st := status.New(codes.Code(errCode.StatusCode), errCode.Message) + if st1, err1 := st.WithDetails(errCode); err1 != nil { + log.Err(err1).Any("lava-error", errCode).Msg("failed to convert error to grpc status") return st } else { return st1 @@ -197,7 +191,7 @@ func ConvertErr2Status(err *errorpb.Error) *status.Status { // ParseError try to convert an error to *Error. // It supports wrapped errors. -func ParseError(err error) *errorpb.Error { +func ParseError(err error) *errorpb.ErrCode { if err == nil { return nil } @@ -211,27 +205,17 @@ func ParseError(err error) *errorpb.Error { details := gs.GRPCStatus().Details() if len(details) > 0 && details[0] != nil { - if e, ok := details[0].(*errorpb.Error); ok && e != nil { + if e, ok := details[0].(*errorpb.ErrCode); ok && e != nil { return e } } - return &errorpb.Error{ - Code: &errorpb.ErrCode{ - Message: gs.GRPCStatus().Message(), - StatusCode: errorpb.Code(gs.GRPCStatus().Code()), - Code: int32(GrpcCodeToHTTP(gs.GRPCStatus().Code())), - Name: "lava.grpc.status", - Details: gs.GRPCStatus().Proto().Details, - }, - Trace: &errorpb.ErrTrace{ - Service: version.Project(), - Version: version.Version(), - }, - Msg: &errorpb.ErrMsg{ - Msg: err.Error(), - Detail: fmt.Sprintf("%v", gs.GRPCStatus().Details()), - }, + return &errorpb.ErrCode{ + Message: gs.GRPCStatus().Message(), + StatusCode: errorpb.Code(gs.GRPCStatus().Code()), + Code: int32(GrpcCodeToHTTP(gs.GRPCStatus().Code())), + Name: "lava.grpc.status", + Details: gs.GRPCStatus().Proto().Details, } } @@ -242,34 +226,14 @@ func ParseError(err error) *errorpb.Error { pb.Message = err.Error() } - return &errorpb.Error{ - Code: pb, - Trace: &errorpb.ErrTrace{ - Service: version.Project(), - Version: version.Version(), - }, - Msg: &errorpb.ErrMsg{ - Msg: err.Error(), - Detail: fmt.Sprintf("%v", err), - }, - } + return pb } - return &errorpb.Error{ - Code: &errorpb.ErrCode{ - Message: err.Error(), - StatusCode: errorpb.Code_Unknown, - Code: 500, - Name: "lava.error.unknown", - Details: []*anypb.Any{errors.MustProtoToAny(errors.ParseErrToPb(err))}, - }, - Trace: &errorpb.ErrTrace{ - Service: version.Project(), - Version: version.Version(), - }, - Msg: &errorpb.ErrMsg{ - Msg: err.Error(), - Detail: fmt.Sprintf("%v", err), - }, + return &errorpb.ErrCode{ + Message: err.Error(), + StatusCode: errorpb.Code_Unknown, + Code: 500, + Name: "lava.error.unknown", + Details: []*anypb.Any{errors.MustProtoToAny(errors.ParseErrToPb(err))}, } } diff --git a/errors/errutil/util_test.go b/errors/errutil/util_test.go index b363a44f..4ae84599 100644 --- a/errors/errutil/util_test.go +++ b/errors/errutil/util_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/errors/errutil" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/errors/errutil" ) func TestJson(t *testing.T) { diff --git a/errors/must.go b/errors/must.go deleted file mode 100644 index f7e9a259..00000000 --- a/errors/must.go +++ /dev/null @@ -1,63 +0,0 @@ -package errors - -import ( - "fmt" - "os" -) - -func Must(err error, args ...interface{}) { - if err == nil { - return - } - - err = WrapStack(Wrap(err, fmt.Sprint(args...))) - Debug(err) - panic(err) -} - -func MustF(err error, msg string, args ...interface{}) { - if err == nil { - return - } - - err = WrapStack(Wrap(err, fmt.Sprintf(msg, args...))) - Debug(err) - panic(err) -} - -func Must1[T any](ret T, err error) T { - if err != nil { - err = WrapStack(err) - Debug(err) - panic(err) - } - - return ret -} - -func Exit(err error, args ...interface{}) { - if err == nil { - return - } - - Debug(WrapStack(Wrap(err, fmt.Sprint(args...)))) - os.Exit(1) -} - -func ExitF(err error, msg string, args ...interface{}) { - if err == nil { - return - } - - Debug(WrapStack(Wrapf(err, msg, args...))) - os.Exit(1) -} - -func Exit1[T any](ret T, err error) T { - if err != nil { - Debug(WrapStack(err)) - os.Exit(1) - } - - return ret -} diff --git a/errors/stack_filters.go b/errors/stack_filters.go deleted file mode 100644 index 022cdea8..00000000 --- a/errors/stack_filters.go +++ /dev/null @@ -1,25 +0,0 @@ -package errors - -import ( - "github.com/pubgo/funk/stack" -) - -var stackFilters []func(frame *stack.Frame) bool - -// RegStackPkgFilter filter fn , pkg -func RegStackPkgFilter(filters ...func(frame *stack.Frame) bool) { - if len(filters) == 0 { - return - } - - stackFilters = append(stackFilters, filters...) -} - -func filterStack(frame *stack.Frame) bool { - for _, filter := range stackFilters { - if filter(frame) { - return true - } - } - return false -} diff --git a/errors/util.go b/errors/util.go index 275938c7..9f8b26e6 100644 --- a/errors/util.go +++ b/errors/util.go @@ -10,10 +10,10 @@ import ( "github.com/samber/lo" "google.golang.org/protobuf/proto" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/proto/errorpb" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2/internal/errors/errinter" + "github.com/pubgo/funk/v2/pretty" + "github.com/pubgo/funk/v2/proto/errorpb" + "github.com/pubgo/funk/v2/stack" ) func cloneAndCheck(code *errorpb.ErrCode) *errorpb.ErrCode { @@ -22,7 +22,9 @@ func cloneAndCheck(code *errorpb.ErrCode) *errorpb.ErrCode { } code = proto.Clone(code).(*errorpb.ErrCode) - if code.Name != "" && code.StatusCode == 0 { + if code.Code == 0 { + code.StatusCode = errorpb.Code_OK + } else if code.StatusCode == errorpb.Code_OK { code.StatusCode = errorpb.Code_Internal } @@ -106,24 +108,7 @@ func strFormat(f fmt.State, verb rune, err Error) { } func getStack() []*stack.Frame { - var ss []*stack.Frame - for i := 0; ; i++ { - cc := stack.Caller(1 + i) - if cc == nil { - break - } - - if cc.IsRuntime() { - continue - } - - if filterStack(cc) { - continue - } - - ss = append(ss, cc) - } - return ss + return lo.Filter(stack.Trace(), func(item *stack.Frame, index int) bool { return !item.IsRuntime() }) } func newErrorId() *string { diff --git a/errors/z_code_test.go b/errors/z_code_test.go index 16be6e5e..f1a65869 100644 --- a/errors/z_code_test.go +++ b/errors/z_code_test.go @@ -4,18 +4,26 @@ import ( "fmt" "testing" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/proto/errorpb" "github.com/stretchr/testify/assert" + + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/proto/errorpb" ) func TestWrapCaller(t *testing.T) { err := fmt.Errorf("test") - var ff = func() error { + assert.Contains(t, fmt.Sprint(err), "test") + + ff := func() error { return errors.WrapCaller(err, 1) } - assert.Contains(t, fmt.Sprint(ff()), "z_code_test.go:18 TestWrapCaller") + err = ff() + assert.Contains(t, fmt.Sprint(err), "z_code_test.go:20 TestWrapCaller") + + err = errors.WrapKV(err, "key", "value") + errors.Debug(err) + assert.Contains(t, fmt.Sprint(err), "z_code_test.go:20 TestWrapCaller") } func TestCodeErr(t *testing.T) { diff --git a/errors/z_err_code_test.go b/errors/z_err_code_test.go index 8ab09ff8..d5d76b29 100644 --- a/errors/z_err_code_test.go +++ b/errors/z_err_code_test.go @@ -3,9 +3,9 @@ package errors_test import ( "testing" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/proto/errorpb" - "github.com/pubgo/funk/proto/testcodepb" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/proto/errorpb" + "github.com/pubgo/funk/v2/proto/testcodepb" ) func TestErrCode(t *testing.T) { diff --git a/errors/z_error_stack_test.go b/errors/z_error_stack_test.go index ade03b24..d85d3e9e 100644 --- a/errors/z_error_stack_test.go +++ b/errors/z_error_stack_test.go @@ -3,9 +3,9 @@ package errors_test import ( "testing" - "github.com/pubgo/funk/errors" + "github.com/pubgo/funk/v2/errors" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2/stack" ) func TestStack(t *testing.T) { diff --git a/errors/z_error_test.go b/errors/z_error_test.go index 06466973..5d83afee 100644 --- a/errors/z_error_test.go +++ b/errors/z_error_test.go @@ -6,13 +6,13 @@ import ( "google.golang.org/protobuf/encoding/protojson" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/proto/errorpb" - "github.com/pubgo/funk/proto/testcodepb" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/proto/errorpb" + "github.com/pubgo/funk/v2/proto/testcodepb" ) func TestFormat(t *testing.T) { - //err := errors.WrapCaller(fmt.Errorf("test error, err=%w", errors.New("hello error"))) + // err := errors.WrapCaller(fmt.Errorf("test error, err=%w", errors.New("hello error"))) err := errors.WrapCaller(errors.New("hello error")) err = errors.Wrap(err, "next error") err = errors.WrapTag(err, errors.T("event", "test event"), errors.T("test123", 123), errors.T("test", "hello")) diff --git a/features/_.go b/features/_.go new file mode 100644 index 00000000..1a1fa68d --- /dev/null +++ b/features/_.go @@ -0,0 +1,6 @@ +package features + +// 用于程序启动之后对程序内部进行控制的参数, 一般是全局性质的控制 +// 比如 stack 控制, 控制 panic 的时候或者遇到 error 的时候是否打印堆栈 +// 比如 某个新功能是否开启 +// 比如 临时调整阈值等 diff --git a/features/example/main.go b/features/example/main.go new file mode 100644 index 00000000..0ac392bf --- /dev/null +++ b/features/example/main.go @@ -0,0 +1,79 @@ +// main.go +package main + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "time" + + "github.com/pubgo/funk/v2/features" +) + +type Data struct { + Name string +} + +func main() { + // 创建带 Tags 的元数据 + status := features.String("app_status", "ok", "Current application status", + map[string]any{ + "group": "health", + "mutable": true, + }) + + replicas := features.Int("replicas", 1, "Number of replicas", + map[string]any{ + "group": "scaling", + "min": 1, + "max": 10, + }) + + _ = features.String("api_key", "sk-xxxx", "API authentication key", + map[string]any{ + "sensitive": true, + "group": "security", + }) + + _ = features.Json("json_key", &Data{}, "API authentication key", + map[string]any{ + "sensitive": true, + "group": "security", + }) + + // 模拟更新 + go func() { + time.Sleep(2 * time.Second) + status.Set("degraded") + + time.Sleep(2 * time.Second) + replicas.Set(fmt.Sprintf("%v", replicas.GetValue()+2)) + + time.Sleep(2 * time.Second) + }() + + // HTTP handler:只输出非敏感字段 + http.HandleFunc("/metadata", func(w http.ResponseWriter, r *http.Request) { + data := extractPublicMetadata() + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(data) + }) + + log.Println("Feature server listening on :8181") + log.Fatal(http.ListenAndServe(":8181", nil)) +} + +// extractPublicMetadata 导出所有非敏感元数据 +func extractPublicMetadata() map[string]any { + m := make(map[string]any) + features.VisitAll(func(e *features.Flag) { + // 跳过敏感字段 + if sensitive, ok := e.Tags["sensitive"].(bool); ok && sensitive { + m[e.Name] = "******" + return + } + m[e.Name] = e + }) + return m +} diff --git a/features/featureflags/flags.go b/features/featureflags/flags.go new file mode 100644 index 00000000..c6f81af4 --- /dev/null +++ b/features/featureflags/flags.go @@ -0,0 +1,81 @@ +package featureflags + +import ( + "context" + "fmt" + + "github.com/urfave/cli/v3" + + "github.com/pubgo/funk/v2/env" + "github.com/pubgo/funk/v2/features" +) + +func GetFlags() []cli.Flag { + var flags []cli.Flag + features.VisitAll(func(flag *features.Flag) { + envVar := cli.EnvVars(env.Key("feature." + flag.Name)) + const category = "feature" + switch flag.Value.Type() { + case features.BoolType: + flags = append(flags, &cli.BoolFlag{ + Name: flag.Name, + Usage: flag.Usage, + Value: flag.Value.Get().(bool), + Category: category, + Sources: envVar, + Local: true, + Action: func(ctx context.Context, command *cli.Command, b bool) error { + return flag.Value.Set(fmt.Sprintf("%v", b)) + }, + }) + case features.StringType: + flags = append(flags, &cli.StringFlag{ + Name: flag.Name, + Usage: flag.Usage, + Value: flag.Value.Get().(string), + Category: category, + Sources: envVar, + Local: true, + Action: func(ctx context.Context, command *cli.Command, s string) error { + return flag.Value.Set(s) + }, + }) + + case features.JsonType: + flags = append(flags, &cli.StringFlag{ + Category: category, + Usage: flag.Usage, + Value: flag.Value.String(), + Local: true, + Sources: envVar, + Action: func(ctx context.Context, command *cli.Command, s string) error { + return flag.Value.Set(s) + }, + }) + case features.IntType: + flags = append(flags, &cli.IntFlag{ + Category: category, + Usage: flag.Usage, + Value: flag.Value.Get().(int), + Local: true, + Sources: envVar, + Action: func(ctx context.Context, command *cli.Command, i int) error { + return flag.Value.Set(fmt.Sprintf("%d", i)) + }, + }) + case features.FloatType: + flags = append(flags, &cli.Float64Flag{ + Category: category, + Usage: flag.Usage, + Value: flag.Value.Get().(float64), + Local: true, + Sources: envVar, + Action: func(ctx context.Context, command *cli.Command, f float64) error { + return flag.Value.Set(fmt.Sprintf("%f", f)) + }, + }) + } + }) + + return flags +} diff --git a/features/features.go b/features/features.go new file mode 100644 index 00000000..fb7721e8 --- /dev/null +++ b/features/features.go @@ -0,0 +1,117 @@ +package features + +import ( + "fmt" + "sync" +) + +type ValueType string + +func (typ ValueType) String() string { + switch typ { + case StringType: + return "string" + case IntType: + return "int" + case FloatType: + return "float" + case BoolType: + return "bool" + case JsonType: + return "json" + default: + return "unknown" + } +} + +const ( + StringType ValueType = "string" + IntType ValueType = "int" + FloatType ValueType = "float" + BoolType ValueType = "bool" + JsonType ValueType = "json" +) + +type Value interface { + String() string + Type() ValueType + Set(string) error + Get() any +} + +type Flag struct { + Name string + Usage string + Value Value + Deprecated bool + Tags map[string]any +} + +type Feature struct { + mutex sync.RWMutex + flags map[string]*Flag +} + +// NewFeature creates a new Feature instance +func NewFeature() *Feature { + return &Feature{ + flags: make(map[string]*Flag), + } +} + +// AddFunc registers a new value with getter, setter, usage, and optional tags +func (m *Feature) AddFunc(name, usage string, value Value, tags ...map[string]any) *Flag { + m.mutex.Lock() + defer m.mutex.Unlock() + + if m.flags[name] != nil { + panic(fmt.Sprintf("flag already exists, name:%s", name)) + } + + ff := &Flag{Name: name, Usage: usage, Value: value, Tags: mergeTags(tags...)} + m.flags[name] = ff + return ff +} + +// Lookup returns the entry by name +func (m *Feature) Lookup(name string) *Flag { + m.mutex.RLock() + defer m.mutex.RUnlock() + return m.flags[name] +} + +// VisitAll calls fn for each entry +func (m *Feature) VisitAll(fn func(*Flag)) { + m.mutex.RLock() + defer m.mutex.RUnlock() + for _, e := range m.flags { + fn(e) + } +} + +var defaultFeature = NewFeature() + +func Register(name, usage string, value Value, tags ...map[string]any) { + defaultFeature.AddFunc(name, usage, value, tags...) +} + +func Lookup(name string) *Flag { + return defaultFeature.Lookup(name) +} + +func VisitAll(fn func(*Flag)) { defaultFeature.VisitAll(fn) } + +// mergeTags safely copies optional tags +func mergeTags(maps ...map[string]any) map[string]any { + if len(maps) == 0 || maps[0] == nil { + return make(map[string]any) + } + + m := make(map[string]any) + for _, mm := range maps { + for k, v := range mm { + m[k] = v + } + } + return m +} diff --git a/features/types.go b/features/types.go new file mode 100644 index 00000000..140c3c11 --- /dev/null +++ b/features/types.go @@ -0,0 +1,161 @@ +package features + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/k0kubun/pp/v3" +) + +var _ Value = (*baseValue[any])(nil) + +func newBase[T any](f *Feature, name string, value T, usage string, typ ValueType, tags []map[string]any, set func(s string) (T, error), getString func(val T) string) *baseValue[T] { + base := &baseValue[T]{val: value, set: set, getString: getString, typ: typ} + base.ff = f.AddFunc(name, usage, base, tags...) + return base +} + +type baseValue[T any] struct { + ff *Flag + typ ValueType + val T + set func(s string) (T, error) + getString func(val T) string +} + +func (b *baseValue[T]) Name() string { return b.ff.Name } +func (b *baseValue[T]) Type() ValueType { return b.typ } +func (b *baseValue[T]) Get() any { return b.val } +func (b *baseValue[T]) GetValue() T { return b.val } +func (b *baseValue[T]) Set(s string) error { + val, err := b.set(s) + if err != nil { + return fmt.Errorf("faield to set value, value=%s err=%w", s, err) + } + + b.val = val + return nil +} + +func (b *baseValue[T]) String() string { + if b.getString == nil { + return fmt.Sprintf("%v", b.val) + } + + return b.getString(b.val) +} + +type StringValue struct { + *baseValue[string] +} + +func String(name, value, usage string, tags ...map[string]any) StringValue { + base := newBase( + defaultFeature, + name, + value, + usage, + StringType, + tags, + func(s string) (string, error) { return s, nil }, + func(val string) string { return val }, + ) + return StringValue{baseValue: base} +} + +type IntValue struct { + *baseValue[int64] +} + +func Int(name string, value int64, usage string, tags ...map[string]any) IntValue { + base := newBase( + defaultFeature, + name, + value, + usage, + IntType, + tags, + func(s string) (val int64, err error) { + _, err = fmt.Sscanf(s, "%d", &val) + return val, err + }, + nil, + ) + return IntValue{baseValue: base} +} + +type FloatValue struct { + *baseValue[float64] +} + +func Float(name string, value float64, usage string, tags ...map[string]any) FloatValue { + base := newBase( + defaultFeature, + name, + value, + usage, + FloatType, + tags, + func(s string) (val float64, err error) { + _, err = fmt.Sscanf(s, "%f", &val) + return val, err + }, + func(val float64) string { return fmt.Sprintf("%f", val) }, + ) + return FloatValue{baseValue: base} +} + +type BoolValue struct { + *baseValue[bool] +} + +func Bool(name string, value bool, usage string, tags ...map[string]any) BoolValue { + base := newBase( + defaultFeature, + name, + value, + usage, + BoolType, + tags, + func(s string) (val bool, err error) { + switch strings.ToLower(s) { + case "true", "1", "on", "yes": + return true, nil + case "false", "0", "off", "no": + return false, nil + default: + return len(s) > 0, nil + } + }, + func(val bool) string { return fmt.Sprintf("%v", val) }, + ) + return BoolValue{baseValue: base} +} + +type JsonValue[T any] struct { + *baseValue[T] +} + +func Json[T any](name string, value T, usage string, tags ...map[string]any) JsonValue[T] { + base := newBase[T]( + defaultFeature, + name, + value, + usage, + JsonType, + tags, + func(s string) (val T, err error) { + return val, json.Unmarshal([]byte(s), &val) + }, + func(val T) string { + data, err := json.Marshal(val) + if err != nil { + _, _ = pp.Println(val) + return err.Error() + } + return string(data) + }, + ) + return JsonValue[T]{baseValue: base} +} diff --git a/funk.go b/funk.go index 0675bbe6..f0bbb2c7 100644 --- a/funk.go +++ b/funk.go @@ -1,12 +1,17 @@ package funk import ( + "cmp" + _ "embed" "reflect" "unsafe" - - "golang.org/x/exp/constraints" ) +//go:embed .version +var releaseVersion string + +func ReleaseVersion() string { return releaseVersion } + func AppendOf[T any](v T, vv ...T) []T { return append(append(make([]T, 0, len(vv)+1), v), vv...) } @@ -16,7 +21,7 @@ func ListOf[T any](args ...T) []T { } func Zero[T any]() (ret T) { - return + return ret } // Equals wraps the '==' operator for comparable types. @@ -25,13 +30,13 @@ func Equals[T comparable](a, b T) bool { } func Nil[T any]() (t *T) { - return + return t } //go:inline func FromPtr[T any](v *T) (r T) { if v == nil { - return + return r } return *v @@ -44,7 +49,7 @@ func ToPtr[T any](v T) *T { func Last[T any](args []T) (t T) { if len(args) == 0 { - return + return t } return args[len(args)-1] @@ -64,10 +69,10 @@ func TernaryFn[T any](ok bool, a, b func() T) T { return b() } -func Map[T, V any](data []T, handle func(i int, d T) V) []V { +func Map[T, V any](data []T, handle func(d T) V) []V { vv := make([]V, 0, len(data)) for i := range data { - vv = append(vv, handle(i, data[i])) + vv = append(vv, handle(data[i])) } return vv } @@ -120,33 +125,33 @@ func DeleteAll[T comparable](set []T, value T) []T { } // Max returns the max of the 2 passed values. -func Max[T constraints.Ordered](a, b T) (r T) { +func Max[T cmp.Ordered](a, b T) (r T) { if a < b { r = b } else { r = a } - return + return r } // Min returns the min of the 2 passed values. -func Min[T constraints.Ordered](a, b T) (r T) { +func Min[T cmp.Ordered](a, b T) (r T) { if a < b { r = a } else { r = b } - return + return r } // isNilValue copy from -func isNilValue(i interface{}) bool { +func isNilValue(i any) bool { return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0 } -func IsNil(err interface{}) bool { +func IsNil(err any) bool { if err == nil { return true } @@ -156,10 +161,6 @@ func IsNil(err interface{}) bool { } v := reflect.ValueOf(err) - if !v.IsValid() { - return true - } - switch v.Kind() { case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer, reflect.Slice, reflect.Interface: return v.IsNil() @@ -168,11 +169,45 @@ func IsNil(err interface{}) bool { } } -func Init(fn func()) error { +func Init(fn func()) Void { fn() - return nil + return Void{} +} + +func DoFunc[T any](fn func() T) T { return fn() } +func Call[T any](fn func() T) T { return fn() } + +func DoSelf[T any](t T, fn func(t T)) T { + fn(t) + return t +} + +type Void struct{} + +type Ctx[T any] map[string]T + +func (c Ctx[T]) ToTuple() Tuple[T] { + tt := make(Tuple[T], 0, len(c)) + for k := range c { + tt = append(tt, KV[T]{K: k, V: c[k]}) + } + return tt +} + +type ( + List[T any] []T + Tuple[T any] []KV[T] +) + +func (t Tuple[T]) ToCtx() Ctx[T] { + ctx := make(Ctx[T], len(t)) + for i := range t { + ctx[t[i].K] = t[i].V + } + return ctx } -func DoFunc[T any](fn func() T) T { - return fn() +type KV[T any] struct { + K string `json:"key"` + V T `json:"value"` } diff --git a/generic/util_test.go b/funk_test.go similarity index 87% rename from generic/util_test.go rename to funk_test.go index 1cde7508..efe65bf8 100644 --- a/generic/util_test.go +++ b/funk_test.go @@ -1,4 +1,4 @@ -package generic +package funk import ( "strconv" @@ -7,8 +7,7 @@ import ( "github.com/stretchr/testify/assert" ) -type err1 struct { -} +type err1 struct{} func (e err1) Error() string { return "" @@ -17,7 +16,7 @@ func (e err1) Error() string { func TestMap(t *testing.T) { data := []int{1, 2, 3, 4} t.Log(Map(data, func(i int) string { - return strconv.Itoa(data[i]) + return strconv.Itoa(i) })) } diff --git a/generic/aaa.go b/generic/aaa.go deleted file mode 100644 index 009525f6..00000000 --- a/generic/aaa.go +++ /dev/null @@ -1,29 +0,0 @@ -package generic - -type Ctx[T any] map[string]T - -func (c Ctx[T]) ToTuple() Tuple[T] { - tt := make(Tuple[T], 0, len(c)) - for k := range c { - tt = append(tt, KV[T]{K: k, V: c[k]}) - } - return tt -} - -type ( - List[T any] []T - Tuple[T any] []KV[T] -) - -func (t Tuple[T]) ToCtx() Ctx[T] { - ctx := make(Ctx[T], len(t)) - for i := range t { - ctx[t[i].K] = t[i].V - } - return ctx -} - -type KV[T any] struct { - K string `json:"key"` - V T `json:"value"` -} diff --git a/generic/util.go b/generic/util.go deleted file mode 100644 index 4a09d8ed..00000000 --- a/generic/util.go +++ /dev/null @@ -1,163 +0,0 @@ -package generic - -import ( - "github.com/pubgo/funk" - "golang.org/x/exp/constraints" -) - -func AppendOf[T any](v T, vv ...T) []T { - return funk.AppendOf(v, vv...) -} - -func ListOf[T any](args ...T) []T { - return funk.ListOf(args...) -} - -func Zero[T any]() (ret T) { - return funk.Zero[T]() -} - -func Equals[T comparable](a, b T) bool { - return funk.Equals(a, b) -} - -func Nil[T any]() (t *T) { - return funk.Nil[T]() -} - -// DePtr -// Deprecated: use FromPtr -func DePtr[T any](v *T) (r T) { - return funk.FromPtr(v) -} - -func FromPtr[T any](v *T) (r T) { - return funk.FromPtr(v) -} - -//go:inline -func Ptr[T any](v T) *T { - return funk.ToPtr(v) -} - -func Last[T any](args []T) (t T) { - return funk.Last(args) -} - -func Ternary[T any](ok bool, a, b T) T { - return funk.Ternary(ok, a, b) -} - -func TernaryFn[T any](ok bool, a, b func() T) T { - return funk.TernaryFn(ok, a, b) -} - -func Map[T, V any](data []T, handle func(i int) V) []V { - vv := make([]V, 0, len(data)) - for i := range data { - vv = append(vv, handle(i)) - } - return vv -} - -// ExtractFrom extracts a nested object of type E from type T. -// -// This function is useful if we have a set of type `T` nad we want to -// extract the type E from any T. -func ExtractFrom[T, E any](set []T, fn func(T) E) []E { - r := make([]E, len(set)) - for i := range set { - r[i] = fn(set[i]) - } - return r -} - -// Contains returns whether `vs` contains the element `e` by comparing vs[i] == e. -func Contains[T comparable](vs []T, e T) bool { - for _, v := range vs { - if v == e { - return true - } - } - - return false -} - -// Filter iterates over `set` and gets the values that match `criteria`. -// -// Filter will return a new allocated slice. -func Filter[T any](set []T, criteria func(T) bool) []T { - r := make([]T, 0) - for i := range set { - if criteria(set[i]) { - r = append(r, set[i]) - } - } - return r -} - -// FilterInPlace filters the contents of `set` using `criteria`. -// -// FilterInPlace returns `set`. -func FilterInPlace[T any](set []T, criteria func(T) bool) []T { - for i := 0; i < len(set); i++ { - if !criteria(set[i]) { - set = append(set[:i], set[i+1:]...) - i-- - } - } - return set -} - -// Delete the first occurrence of a type from a set. -func Delete[T comparable](set []T, value T) []T { - for i := 0; i < len(set); i++ { - if set[i] == value { - set = append(set[:i], set[i+1:]...) - break - } - } - return set -} - -// DeleteAll occurrences from a set. -func DeleteAll[T comparable](set []T, value T) []T { - for i := 0; i < len(set); i++ { - if set[i] == value { - set = append(set[:i], set[i:]...) - i-- - } - } - return set -} - -// Max returns the max of the 2 passed values. -func Max[T constraints.Ordered](a, b T) (r T) { - if a < b { - r = b - } else { - r = a - } - - return -} - -// Min returns the min of the 2 passed values. -func Min[T constraints.Ordered](a, b T) (r T) { - if a < b { - r = a - } else { - r = b - } - - return -} - -func IsNil(err interface{}) bool { - return funk.IsNil(err) -} - -func Init(fn func()) any { - fn() - return nil -} diff --git a/go.mod b/go.mod index fa4733f5..ebed5da0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ -module github.com/pubgo/funk +module github.com/pubgo/funk/v2 -go 1.23.0 +go 1.24 require ( dario.cat/mergo v1.0.0 @@ -10,10 +10,10 @@ require ( github.com/bradleyjkemp/memviz v0.2.3 github.com/dave/jennifer v1.7.0 github.com/deckarep/golang-set/v2 v2.6.0 - github.com/dustin/go-humanize v1.0.0 + github.com/dustin/go-humanize v1.0.1 github.com/ettle/strcase v0.2.0 github.com/expr-lang/expr v1.17.5 - github.com/goccy/go-json v0.10.2 + github.com/google/go-cmp v0.7.0 github.com/gopherjs/gopherjs v1.17.2 github.com/hashicorp/go-version v1.6.0 github.com/huandu/go-clone v1.5.1 @@ -23,16 +23,15 @@ require ( github.com/joho/godotenv v1.5.1 github.com/k0kubun/pp/v3 v3.5.0 github.com/mattn/go-isatty v0.0.20 - github.com/mattn/go-sqlite3 v1.14.16 + github.com/mattn/go-sqlite3 v1.14.22 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/term v0.5.0 - github.com/nats-io/nats.go v1.37.0 + github.com/nats-io/nats.go v1.47.0 github.com/open2b/scriggo v0.56.1 - github.com/panjf2000/ants/v2 v2.10.0 + github.com/panjf2000/ants/v2 v2.11.3 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/phuslu/goid v1.0.0 github.com/projectdiscovery/machineid v0.0.0-20250715113114-c77eb3567582 - github.com/pubgo/dix v0.3.15 github.com/rs/xid v1.5.0 github.com/rs/zerolog v1.33.0 github.com/samber/lo v1.51.0 @@ -42,30 +41,31 @@ require ( github.com/testcontainers/testcontainers-go/modules/postgres v0.30.0 github.com/tidwall/gjson v1.17.1 github.com/tidwall/match v1.1.1 - github.com/urfave/cli/v3 v3.3.8 + github.com/urfave/cli/v3 v3.4.1 github.com/valyala/fastrand v1.1.0 github.com/valyala/fasttemplate v1.2.2 go.etcd.io/bbolt v1.3.7 - go.etcd.io/etcd/client/v3 v3.5.9 + go.etcd.io/etcd/client/v3 v3.6.5 go.uber.org/atomic v1.10.0 golang.org/x/crypto v0.38.0 - golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb + golang.org/x/mod v0.25.0 golang.org/x/sys v0.33.0 golang.org/x/text v0.26.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.1 - google.golang.org/protobuf v1.34.3-0.20240816073751-94ecbc261689 + google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb + google.golang.org/grpc v1.71.1 + google.golang.org/protobuf v1.36.5 gopkg.in/yaml.v3 v3.0.1 - gorm.io/driver/mysql v1.4.5 - gorm.io/driver/postgres v1.4.1 - gorm.io/driver/sqlite v1.4.4 - gorm.io/gen v0.3.21 - gorm.io/gorm v1.24.5 + gorm.io/driver/mysql v1.6.0 + gorm.io/driver/postgres v1.5.0 + gorm.io/driver/sqlite v1.6.0 + gorm.io/gen v0.3.27 + gorm.io/gorm v1.31.0 modernc.org/sqlite v1.18.0 ) require ( ariga.io/atlas v0.21.1 // indirect + filippo.io/edwards25519 v1.1.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect @@ -74,7 +74,7 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -83,30 +83,25 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/inflect v0.19.0 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/hcl/v2 v2.13.0 // indirect github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.3 // indirect - github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.3 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgtype v1.14.0 // indirect - github.com/jackc/pgx/v4 v4.18.3 // indirect + github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/pgx/v5 v5.5.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.17.7 // indirect - github.com/kr/pretty v0.3.1 // indirect + github.com/klauspost/compress v1.18.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.14 // indirect @@ -115,7 +110,7 @@ require ( github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.1.0 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nkeys v0.4.11 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect @@ -123,7 +118,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -133,25 +127,25 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/zclconf/go-cty v1.8.0 // indirect - go.etcd.io/etcd/api/v3 v3.5.9 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect + go.etcd.io/etcd/api/v3 v3.6.5 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.5 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect - go.opentelemetry.io/otel/metric v1.26.0 // indirect - go.opentelemetry.io/otel/sdk v1.26.0 // indirect - go.opentelemetry.io/otel/trace v1.26.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.2.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.17.0 // indirect - golang.org/x/mod v0.25.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb // indirect golang.org/x/net v0.40.0 // indirect golang.org/x/sync v0.15.0 // indirect golang.org/x/tools v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect - gorm.io/datatypes v1.0.7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect + gorm.io/datatypes v1.2.4 // indirect gorm.io/hints v1.1.0 // indirect - gorm.io/plugin/dbresolver v1.3.0 // indirect + gorm.io/plugin/dbresolver v1.6.2 // indirect lukechampine.com/uint128 v1.1.1 // indirect modernc.org/cc/v3 v3.36.0 // indirect modernc.org/ccgo/v3 v3.16.6 // indirect diff --git a/go.sum b/go.sum index 657141dd..f869b10e 100644 --- a/go.sum +++ b/go.sum @@ -4,18 +4,14 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= entgo.io/ent v0.13.1 h1:uD8QwN1h6SNphdCCzmkMN3feSUzNnVvV/WIkHKMbzOE= entgo.io/ent v0.13.1/go.mod h1:qCEmo+biw3ccBn9OyL4ZK5dfpwg++l1Gxwac5B1206A= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= @@ -32,21 +28,16 @@ github.com/bradleyjkemp/memviz v0.2.3 h1:8fqKnV1xQz4NQkDy5Gklhm9fGtUK+R3oW0z1unB github.com/bradleyjkemp/memviz v0.2.3/go.mod h1:meU694rvawW7NqtNLtlg+TEU+UqAjrbJayEPZQUSOBs= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -57,54 +48,41 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= -github.com/denisenkom/go-mssqldb v0.12.2 h1:1OcPn5GBIobjWNd+8yjfHNIaFX14B1pWI3F9HZy5KXw= -github.com/denisenkom/go-mssqldb v0.12.2/go.mod h1:lnIw1mZukFRZDJYQ0Pb833QS2IaC3l5HkEfra2LJ+sk= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE= github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= github.com/expr-lang/expr v1.17.5 h1:i1WrMvcdLF249nSNlpQZN1S6NXuW9WaOfF5tPi3aw3k= github.com/expr-lang/expr v1.17.5/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -115,17 +93,16 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl/v2 v2.13.0 h1:0Apadu1w6M11dyGFxWnmhhcMjkbAiKCv7G1r/2QgCNc= @@ -140,71 +117,22 @@ github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHL github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy770So= github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= -github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= -github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= -github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= -github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= -github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= -github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= -github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= -github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -216,48 +144,38 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -270,13 +188,12 @@ github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE= -github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= -github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= -github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nats.go v1.47.0 h1:YQdADw6J/UfGUd2Oy6tn4Hq6YHxCaJrVKayxxFqYrgM= +github.com/nats-io/nats.go v1.47.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g= +github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0= +github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE= 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/open2b/scriggo v0.56.1 h1:h3IVNM0OEvszbtdmukaJj9lPo/xSvHPclYm/RqQqUxY= @@ -285,15 +202,12 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/panjf2000/ants/v2 v2.10.0 h1:zhRg1pQUtkyRiOFo2Sbqwjp0GfBNo9cUY2/Grpx1p+8= -github.com/panjf2000/ants/v2 v2.10.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= +github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg= +github.com/panjf2000/ants/v2 v2.11.3/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/phuslu/goid v1.0.0 h1:Cgcvd/R54UO1fCtyt+iKXAi+yZQ/KWlAm6MmZNizCLM= github.com/phuslu/goid v1.0.0/go.mod h1:txc2fUIdrdnn+v9Vq+QpiPQ3dnrXEchjoVDgic+r+L0= -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -302,26 +216,19 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/projectdiscovery/machineid v0.0.0-20250715113114-c77eb3567582 h1:eR+0HE//Ciyfwy3HC7fjRyKShSJHYoX2Pv7pPshjK/Q= github.com/projectdiscovery/machineid v0.0.0-20250715113114-c77eb3567582/go.mod h1:3G3BRKui7nMuDFAZKR/M2hiOLtaOmyukT20g88qRQjI= -github.com/pubgo/dix v0.3.15 h1:DLjXfnyhcxT3skM1pZi60i/QgnUEg9nM6CI8wom7gVc= -github.com/pubgo/dix v0.3.15/go.mod h1:0j+i8YYn4vJnsJQCsyHXUGovR+Mgkh3uZPRhacw09us= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI= github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= github.com/samber/slog-common v0.19.0 h1:fNcZb8B2uOLooeYwFpAlKjkQTUafdjfqKcwcC89G9YI= github.com/samber/slog-common v0.19.0/go.mod h1:dTz+YOU76aH007YUU0DffsXNsGFQRQllPQh9XyNoA3M= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= @@ -330,27 +237,20 @@ github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -368,8 +268,8 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E= -github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +github.com/urfave/cli/v3 v3.4.1 h1:1M9UOCy5bLmGnuu1yn3t3CB4rG79Rtoxuv1sPhnm6qM= +github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= @@ -380,116 +280,94 @@ github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+ github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= -go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= -go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= -go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= -go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= -go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= +go.etcd.io/etcd/api/v3 v3.6.5 h1:pMMc42276sgR1j1raO/Qv3QI9Af/AuyQUW6CBAWuntA= +go.etcd.io/etcd/api/v3 v3.6.5/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ= +go.etcd.io/etcd/client/pkg/v3 v3.6.5 h1:Duz9fAzIZFhYWgRjp/FgNq2gO1jId9Yae/rLn3RrBP8= +go.etcd.io/etcd/client/pkg/v3 v3.6.5/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk= +go.etcd.io/etcd/client/v3 v3.6.5 h1:yRwZNFBx/35VKHTcLDeO7XVLbCBFbPi+XV4OC3QJf2U= +go.etcd.io/etcd/client/v3 v3.6.5/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= -go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= -go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= -go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= -go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= -go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= -go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA= golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -497,95 +375,73 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= -google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= -google.golang.org/protobuf v1.34.3-0.20240816073751-94ecbc261689 h1:hNwajDgT0MlsxZzlUajZVmUYFpts8/CYe4BSNx503ZE= -google.golang.org/protobuf v1.34.3-0.20240816073751-94ecbc261689/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.0.7 h1:8NhJN4+annFjwV1WufDhFiPjdUvV1lSGUdg1UCjQIWY= -gorm.io/datatypes v1.0.7/go.mod h1:l9qkCuy0CdzDEop9HKUdcnC9gHC2sRlaFtHkTzsZRqg= -gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= -gorm.io/driver/mysql v1.4.5 h1:u1lytId4+o9dDaNcPCFzNv7h6wvmc92UjNk3z8enSBU= -gorm.io/driver/mysql v1.4.5/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= -gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= -gorm.io/driver/postgres v1.4.1 h1:DutsKq2LK2Ag65q/+VygWth0/L4GAVOp+sCtg6WzZjs= -gorm.io/driver/postgres v1.4.1/go.mod h1:whNfh5WhhHs96honoLjBAMwJGYEuA3m1hvgUbNXhPCw= +gorm.io/datatypes v1.2.4 h1:uZmGAcK/QZ0uyfCuVg0VQY1ZmV9h1fuG0tMwKByO1z4= +gorm.io/datatypes v1.2.4/go.mod h1:f4BsLcFAX67szSv8svwLRjklArSHAvHLeE3pXAS5DZI= +gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= +gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= +gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= +gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8= -gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= -gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc= -gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= -gorm.io/driver/sqlserver v1.3.1/go.mod h1:w25Vrx2BG+CJNUu/xKbFhaKlGxT/nzRkhWCCoptX8tQ= -gorm.io/driver/sqlserver v1.4.0 h1:3fjbsNkr/YqocSBW5CP16Lq6+APjRrWMzu7NbkXr9QU= -gorm.io/driver/sqlserver v1.4.0/go.mod h1:P8BSbBwkdzXURYx3pWUSEAABRQU0vxbd6xk5+53pg7g= -gorm.io/gen v0.3.21 h1:t8329wT4tW1ZZWOm7vn4LV6OIrz8a5zCg+p78ezt+rA= -gorm.io/gen v0.3.21/go.mod h1:aWgvoKdG9f8Des4TegSa0N5a+gwhGsFo0JJMaLwokvk= +gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= +gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= +gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= +gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= +gorm.io/gen v0.3.27 h1:ziocAFLpE7e0g4Rum69pGfB9S6DweTxK8gAun7cU8as= +gorm.io/gen v0.3.27/go.mod h1:9zquz2xD1f3Eb/eHq4oLn2z6vDVvQlCY5S3uMBLv4EA= gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= -gorm.io/gorm v1.24.5 h1:g6OPREKqqlWq4kh/3MCQbZKImeB9e6Xgc4zD+JgNZGE= -gorm.io/gorm v1.24.5/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= +gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY= +gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= gorm.io/hints v1.1.0 h1:Lp4z3rxREufSdxn4qmkK3TLDltrM10FLTHiuqwDPvXw= gorm.io/hints v1.1.0/go.mod h1:lKQ0JjySsPBj3uslFzY3JhYDtqEwzm+G1hv8rWujB6Y= -gorm.io/plugin/dbresolver v1.3.0 h1:uFDX3bIuH9Lhj5LY2oyqR/bU6pqWuDgas35NAPF4X3M= -gorm.io/plugin/dbresolver v1.3.0/go.mod h1:Pr7p5+JFlgDaiM6sOrli5olekJD16YRunMyA2S7ZfKk= +gorm.io/plugin/dbresolver v1.6.2 h1:F4b85TenghUeITqe3+epPSUtHH7RIk3fXr5l83DF8Pc= +gorm.io/plugin/dbresolver v1.6.2/go.mod h1:tctw63jdrOezFR9HmrKnPkmig3m5Edem9fdxk9bQSzM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.36.0 h1:0kmRkTmqNidmu3c7BNDSdVHCxXCkWLmWmCIVX4LUboo= diff --git a/internal/anyhow/aherrcheck/context.go b/internal/anyhow/aherrcheck/context.go deleted file mode 100644 index 2e8db73e..00000000 --- a/internal/anyhow/aherrcheck/context.go +++ /dev/null @@ -1,29 +0,0 @@ -package aherrcheck - -import ( - "context" -) - -type checkCtx struct{} - -type ErrChecker func(context.Context, error) error - -func CreateCtx(ctx context.Context, errChecks []ErrChecker) context.Context { - if ctx == nil { - ctx = context.Background() - } - return context.WithValue(ctx, checkCtx{}, errChecks) -} - -func GetCheckersFromCtx(ctx context.Context) []ErrChecker { - if ctx == nil { - return nil - } - - checkers, ok := ctx.Value(checkCtx{}).([]ErrChecker) - if !ok { - return nil - } - - return checkers -} diff --git a/internal/anyhow/aherrcheck/errcheck.go b/internal/anyhow/aherrcheck/errcheck.go deleted file mode 100644 index 607d0993..00000000 --- a/internal/anyhow/aherrcheck/errcheck.go +++ /dev/null @@ -1,47 +0,0 @@ -package aherrcheck - -import ( - "context" - "reflect" - - "github.com/pubgo/funk/stack" -) - -var errChecks []ErrChecker - -func RegisterErrCheck(f ErrChecker) bool { - var checkFrame = stack.CallerWithFunc(f) - for _, errFunc := range errChecks { - if reflect.DeepEqual(checkFrame, stack.CallerWithFunc(errFunc)) { - return false - } - } - - errChecks = append(errChecks, f) - return true -} - -func GetErrChecks() []ErrChecker { return errChecks } - -func GetErrCheckStacks() []*stack.Frame { - var frames []*stack.Frame - for _, err := range errChecks { - frames = append(frames, stack.CallerWithFunc(err)) - } - return frames -} - -func RemoveErrCheck(f func(context.Context, error) error) { - var checkFrame = stack.CallerWithFunc(f) - var index = -1 - for idx, errFunc := range errChecks { - if reflect.DeepEqual(checkFrame, stack.CallerWithFunc(errFunc)) { - index = idx - break - } - } - - if index != -1 { - errChecks = append(errChecks[:index], errChecks[index+1:]...) - } -} diff --git a/internal/anyhow/aherrcheck/errcheck_test.go b/internal/anyhow/aherrcheck/errcheck_test.go deleted file mode 100644 index 7702d955..00000000 --- a/internal/anyhow/aherrcheck/errcheck_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package aherrcheck - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" -) - -func errCheck1(ctx context.Context, err error) error { - return err -} - -func TestErrCheck(t *testing.T) { - assert.Equal(t, len(GetErrCheckStacks()), 0) - - assert.Equal(t, RegisterErrCheck(errCheck1), true) - assert.Equal(t, len(GetErrCheckStacks()), 1) - - assert.Equal(t, RegisterErrCheck(errCheck1), false) - assert.Equal(t, len(GetErrCheckStacks()), 1) - assert.Equal(t, GetErrCheckStacks()[0].Short(), "aherrcheck/errcheck_test.go:10 errCheck1") - - RemoveErrCheck(errCheck1) - assert.Equal(t, len(GetErrCheckStacks()), 0) -} diff --git a/internal/anyhow/anyhow.go b/internal/anyhow/anyhow.go deleted file mode 100644 index 730a313e..00000000 --- a/internal/anyhow/anyhow.go +++ /dev/null @@ -1,154 +0,0 @@ -package anyhow - -import ( - "context" - "fmt" - "time" - - "github.com/pubgo/funk/errors" -) - -func All[T any](results ...Result[T]) Result[[]T] { - values := make([]T, 0, len(results)) - for _, result := range results { - if result.IsErr() { - return Fail[[]T](result.GetErr()) - } - values = append(values, result.getValue()) - } - return OK(values) -} - -func Recovery(setter *error, callbacks ...func(err error) error) { - errRecovery( - setter, - func() bool { return *setter != nil }, - func() error { return *setter }, - func(err error) error { return err }, - callbacks..., - ) -} - -func RecoveryErr(setter *Error, callbacks ...func(err error) error) { - errRecovery( - setter, - func() bool { return setter.IsErr() }, - func() error { return setter.GetErr() }, - func(err error) Error { return newError(err) }, - callbacks..., - ) -} - -func ErrorOf(msg string, args ...any) Error { - return newError(errors.WrapCaller(fmt.Errorf(msg, args...), 1)) -} - -func ErrOf(err error) Error { - if err == nil { - return Error{} - } - - err = errors.WrapCaller(err, 1) - return newError(err) -} - -func ErrOfFn(fn func() error) Error { - var err = try(fn) - if err == nil { - return Error{} - } - - err = errors.WrapCaller(err, 1) - return newError(err) -} - -func OK[T any](v T) Result[T] { - return Result[T]{v: &v} -} - -func Fail[T any](err error) Result[T] { - if err == nil { - return Result[T]{} - } - - err = errors.WrapCaller(err, 1) - return Result[T]{Err: err} -} - -func Wrap[T any](v T, err error) Result[T] { - if err == nil { - return Result[T]{v: &v} - } - - err = errors.WrapCaller(err, 1) - return Result[T]{Err: err} -} - -func WrapFn[T any](fn func() (T, error)) Result[T] { - v, err := try1(fn) - if err == nil { - return Result[T]{v: &v} - } - - err = errors.WrapCaller(err, 1) - return Result[T]{Err: err} -} - -func CatchErr(setter *Error, err error, contexts ...context.Context) bool { - return catchErr(newError(err), setter, nil, contexts...) -} - -func Catch(rawSetter *error, err error, contexts ...context.Context) bool { - return catchErr(newError(err), nil, rawSetter, contexts...) -} - -func Try[T any](fn func() (T, error)) (r Result[T]) { - if fn == nil { - err := errors.WrapCaller(errors.New("function is nil"), 1) - return Fail[T](err) - } - - defer Recovery(&r.Err) - return Wrap(fn()) -} - -func MapTo[T, U any](r Result[T], fn func(T) U) Result[U] { - if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - return Fail[U](err) - } - - return OK(fn(r.getValue())) -} - -func FlatMapTo[T, U any](r Result[T], fn func(T) Result[U]) Result[U] { - if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - return Fail[U](err) - } - - return fn(r.getValue()) -} - -// RetryWith retries a function with exponential backoff -func RetryWith[T any](fn func() (T, error), attempts int) Result[T] { - if attempts <= 0 { - return Fail[T](errors.New("retry attempts must be positive")) - } - - var lastErr error - for i := 0; i < attempts; i++ { - result := Try(fn) - if result.IsOK() { - return result - } - lastErr = result.GetErr() - - // Simple backoff - in production you might want exponential backoff - if i < attempts-1 { - time.Sleep(time.Duration(i+1) * 100 * time.Millisecond) - } - } - - return Fail[T](errors.Wrapf(lastErr, "failed after %d attempts", attempts)) -} diff --git a/internal/anyhow/error.go b/internal/anyhow/error.go deleted file mode 100644 index 5455f28e..00000000 --- a/internal/anyhow/error.go +++ /dev/null @@ -1,128 +0,0 @@ -package anyhow - -import ( - "context" - "fmt" - - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/errors/errutil" - "github.com/pubgo/funk/log" -) - -var _ Catchable = new(Error) -var _ Checkable = new(Error) - -func newError(err error) Error { - return Error{err: err} -} - -type Error struct { - _ [0]func() // disallow == - - err error -} - -func (e Error) Unwrap() error { return e.err } - -func (e Error) Map(fn func(error) error) Error { - if e.IsOK() { - return e - } - - err := e.getErr() - err = errors.WrapCaller(fn(err), 1) - return Error{err: err} -} - -func (e Error) RecordLog(contexts ...context.Context) Error { - if e.IsErr() { - log.Err(e.err, contexts...). - CallerSkipFrame(1). - Msg(e.err.Error()) - } - - return e -} - -func (e Error) InspectLog(fn func(logger *log.Event), contexts ...context.Context) Error { - if e.IsErr() { - fn(log.Err(e.err, contexts...)) - } - - return e -} - -func (e Error) Inspect(fn func(error)) Error { - if e.IsErr() { - err := e.getErr() - fn(err) - } - - return e -} - -func (e Error) Catch(setter *error, ctx ...context.Context) bool { - return catchErr(e, nil, setter, ctx...) -} - -func (e Error) CatchErr(setter *Error, ctx ...context.Context) bool { - return catchErr(e, setter, nil, ctx...) -} - -func (e Error) IsErr() bool { return e.getErr() != nil } - -func (e Error) IsOK() bool { return e.getErr() == nil } - -func (e Error) GetErr() error { - if e.IsOK() { - return nil - } - - return errors.WrapCaller(e.getErr(), 1) -} - -func (e Error) Must() { - if e.IsOK() { - return - } - - errMust(errors.WrapCaller(e.getErr(), 1)) -} - -func (e Error) Expect(format string, args ...any) { - if e.IsOK() { - return - } - - err := errors.WrapCaller(e.getErr(), 1) - err = errors.Wrapf(err, format, args...) - errMust(err) -} - -func (e Error) String() string { - if e.IsOK() { - return "Ok" - } - - return fmt.Sprintf("Error(%v)", e.err) -} - -func (e Error) MarshalJSON() ([]byte, error) { - if e.IsErr() { - return nil, errors.WrapCaller(e.err, 1) - } - - return errutil.Json(e.err), nil -} - -func (e Error) OrElse(fn func(error) Error) Error { - if e.IsOK() { - return e - } - - err := e.getErr() - err = errors.WrapCaller(err, 1) - return fn(err) -} - -func (e Error) getErr() error { return e.err } diff --git a/internal/anyhow/error_test.go b/internal/anyhow/error_test.go deleted file mode 100644 index e547b29c..00000000 --- a/internal/anyhow/error_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package anyhow - -import ( - "testing" - - "github.com/pubgo/funk/errors" -) - -func TestErrorLog(t *testing.T) { - ErrOf(errors.New("test")).RecordLog() -} diff --git a/internal/anyhow/interface.go b/internal/anyhow/interface.go deleted file mode 100644 index 947b4d5d..00000000 --- a/internal/anyhow/interface.go +++ /dev/null @@ -1,16 +0,0 @@ -package anyhow - -import "context" - -type Catchable interface { - Catch(err *error, contexts ...context.Context) bool - CatchErr(err *Error, contexts ...context.Context) bool -} - -// Checkable defines types that can be checked for Ok/Error state -type Checkable interface { - IsOK() bool - IsErr() bool - GetErr() error - String() string -} diff --git a/internal/anyhow/result.go b/internal/anyhow/result.go deleted file mode 100644 index cfad9469..00000000 --- a/internal/anyhow/result.go +++ /dev/null @@ -1,212 +0,0 @@ -package anyhow - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/pubgo/funk" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log" - "github.com/samber/lo" -) - -var _ Catchable = new(Result[any]) -var _ Checkable = new(Result[any]) - -type Result[T any] struct { - _ [0]func() // disallow == - - v *T - Err error -} - -func (r Result[T]) GetValue() T { - if r.IsErr() { - errMust(errors.WrapCaller(r.getErr(), 1)) - } - - return r.getValue() -} - -func (r Result[T]) SetValue(v T) Result[T] { - if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - return Result[T]{Err: err} - } - - return OK(v) -} - -func (r Result[T]) ValueTo(v *T) Error { - if r.IsErr() { - return newError(errors.WrapCaller(r.getErr(), 1)) - } - - if v == nil { - return newError(errors.WrapStack(errors.New("v params is nil"))) - } - - *v = r.getValue() - return newError(nil) -} - -func (r Result[T]) Expect(format string, args ...any) T { - if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - errMust(errors.Wrapf(err, format, args...)) - } - - return r.getValue() -} - -func (r Result[T]) Must() T { - if r.IsErr() { - errMust(errors.WrapCaller(r.getErr(), 1)) - } - - return r.getValue() -} - -func (r Result[T]) Catch(setter *error, ctx ...context.Context) bool { - return catchErr(newError(r.Err), nil, setter, ctx...) -} - -func (r Result[T]) CatchErr(setter *Error, ctx ...context.Context) bool { - return catchErr(newError(r.Err), setter, nil, ctx...) -} - -func (r Result[T]) IsErr() bool { return r.getErr() != nil } - -func (r Result[T]) IsOK() bool { return r.getErr() == nil } - -func (r Result[T]) Filter(predicate func(T) bool, errorMsg string) Result[T] { - if r.IsErr() { - return r - } - - if predicate(r.getValue()) { - return r - } - - return Fail[T](errors.New(errorMsg)) -} - -func (r Result[T]) InspectErr(fn func(error)) Result[T] { - if r.IsErr() { - fn(r.getErr()) - } - return r -} - -func (r Result[T]) Inspect(fn func(T)) Result[T] { - if r.IsOK() { - fn(r.getValue()) - } - return r -} - -func (r Result[T]) RecordLog(contexts ...context.Context) Result[T] { - if r.IsErr() { - log.Err(r.Err, contexts...). - CallerSkipFrame(1). - Msg(r.Err.Error()) - } - - return r -} - -func (r Result[T]) InspectLog(fn func(logger *log.Event), contexts ...context.Context) Result[T] { - if r.IsErr() { - fn(log.Err(r.getErr(), contexts...)) - } - return r -} - -func (r Result[T]) Map(fn func(T) T) Result[T] { - if r.IsOK() { - return r - } - return OK(fn(r.getValue())) -} - -func (r Result[T]) FlatMap(fn func(T) Result[T]) Result[T] { - if r.IsOK() { - return r - } - return fn(r.getValue()) -} - -func (r Result[T]) MapErr(fn func(error) error) Result[T] { - if r.IsOK() { - return r - } - return Fail[T](fn(r.getErr())) -} - -func (r Result[T]) GetErr() error { - if r.IsOK() { - return nil - } - - err := r.getErr() - return errors.WrapCaller(err, 1) -} - -func (r Result[T]) String() string { - if r.IsOK() { - return fmt.Sprintf("Ok(%v)", r.getValue()) - } - return fmt.Sprintf("Error(%v)", r.getErr()) -} - -func (r Result[T]) SetErr(err error) Result[T] { - if err == nil { - return r - } - - err = errors.WrapCaller(err, 1) - return Result[T]{Err: err} -} - -func (r Result[T]) Unwrap(setter *error, contexts ...context.Context) T { - ret, err := unwrapErr(r, setter, nil, contexts...) - if err != nil { - *setter = errors.WrapCaller(err, 1) - } - return ret -} - -func (r Result[T]) UnwrapErr(setter *Error, contexts ...context.Context) T { - ret, err := unwrapErr(r, nil, setter, contexts...) - if err != nil { - *setter = newError(errors.WrapCaller(err, 1)) - } - return ret -} - -func (r Result[T]) OrElse(fn func(error) T) Result[T] { - if r.IsOK() { - return r - } - return OK(fn(r.getErr())) -} - -func (r Result[T]) UnwrapOr(defaultValue T) T { - if r.IsOK() { - return r.getValue() - } - return defaultValue -} - -func (r Result[T]) MarshalJSON() ([]byte, error) { - if r.IsErr() { - return nil, errors.WrapCaller(r.Err, 1) - } - - return json.Marshal(funk.FromPtr(r.v)) -} - -func (r Result[T]) getValue() T { return lo.FromPtr(r.v) } - -func (r Result[T]) getErr() error { return r.Err } diff --git a/internal/anyhow/result_test.go b/internal/anyhow/result_test.go deleted file mode 100644 index 86da95de..00000000 --- a/internal/anyhow/result_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package anyhow_test - -import ( - "context" - "encoding/json" - "fmt" - "testing" - - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/internal/anyhow" - "github.com/pubgo/funk/internal/anyhow/aherrcheck" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/recovery" -) - -type hello struct { - Name string `json:"name"` -} - -func TestName(t *testing.T) { - defer recovery.DebugPrint() - ok := &hello{Name: "abc"} - okBytes := anyhow.Wrap(json.Marshal(&ok)) - data := string(okBytes.Expect("failed to encode json data")) - t.Log(data) - if data != `{"name":"abc"}` { - t.Log(data) - t.Fatal("not match") - } -} - -func TestResultDo(t *testing.T) { - ok := anyhow.OK(&hello{Name: "abc"}) - ok.Inspect(func(v *hello) { - assert.If(v.Name != "abc", "not match") - }).Inspect(func(v *hello) { - assert.If(v.Name != "abc", "not match") - }) - ok.InspectErr(func(err error) { - t.Log(err) - }) -} - -func TestErrOf(t *testing.T) { - var ctx = log.UpdateEventCtx(context.Background(), log.Map{"test": "ok"}) - aherrcheck.RegisterErrCheck(log.RecordErr()) - - var err anyhow.Error - if fn1().CatchErr(&err, ctx) { - errors.Debug(err.GetErr()) - } -} - -func fn1() (r anyhow.Result[string]) { - if fn3().Catch(&r.Err) { - return - } - - var vv = fn2() - if vv.Catch(&r.Err) { - return - } - - return vv -} - -func fn2() (r anyhow.Result[string]) { - ret := fn3().Map(func(err error) error { - return errors.Wrap(err, "test error") - }) - - if ret.Catch(&r.Err) { - return - } - - return r.SetValue("ok") -} - -func fn3() anyhow.Error { - return anyhow.ErrOf(fmt.Errorf("error test, this is error")). - Inspect(func(err error) { - log.Err(err).Msg("ddd") - }). - InspectLog(func(evt *log.Event) { - evt.Msg("test log") - }). - RecordLog() -} diff --git a/internal/anyhow/util.go b/internal/anyhow/util.go deleted file mode 100644 index f3b3c155..00000000 --- a/internal/anyhow/util.go +++ /dev/null @@ -1,207 +0,0 @@ -package anyhow - -import ( - "context" - "fmt" - "runtime/debug" - - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/internal/anyhow/aherrcheck" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/stack" - "github.com/samber/lo" -) - -var errFnIsNil = errors.New("[fn] is nil") - -func try(fn func() error) (gErr error) { - if fn == nil { - gErr = errors.WrapStack(errFnIsNil) - return - } - - defer func() { - if err := errors.Parse(recover()); !generic.IsNil(err) { - gErr = errors.WrapStack(err) - debug.PrintStack() - errors.Debug(gErr) - } - - gErr = errors.WrapKV(gErr, "fn_stack", stack.CallerWithFunc(fn).String()) - }() - - gErr = fn() - return -} - -func try1[T any](fn func() (T, error)) (t T, gErr error) { - if fn == nil { - return t, errors.WrapStack(errFnIsNil) - } - - defer func() { - if err := errors.Parse(recover()); !generic.IsNil(err) { - gErr = errors.WrapStack(err) - debug.PrintStack() - errors.Debug(gErr) - } - - if gErr != nil { - gErr = errors.WrapKV(gErr, "fn_stack", stack.CallerWithFunc(fn)) - } - }() - - t, gErr = fn() - return -} - -func errMust(err error, args ...any) { - if generic.IsNil(err) { - return - } - - if len(args) > 0 { - err = errors.Wrap(err, fmt.Sprint(args...)) - } - - err = errors.WrapStack(err) - errors.Debug(err) - panic(err) -} - -func catchErr(r Error, setter *Error, rawSetter *error, contexts ...context.Context) bool { - if setter == nil && rawSetter == nil { - errMust(errors.Errorf("error setter is nil")) - } - - if r.IsOK() { - return false - } - - var isErr = func() bool { - if setter != nil { - return (*setter).IsErr() - } - - if rawSetter != nil { - return (*rawSetter) != nil - } - - return false - } - - var getErr = func() error { - if setter != nil { - return (*setter).getErr() - } - - if rawSetter != nil { - return *rawSetter - } - - return nil - } - - var setErr = func(err error) { - if setter != nil { - *setter = newError(err) - } - - if rawSetter != nil { - *rawSetter = err - } - } - - // err No checking, repeat setting - if isErr() { - err := getErr() - log.Err(err).Msgf("error setter is has value, err=%s", err.Error()) - } - - var ctx = context.Background() - for i := range contexts { - if contexts[i] == nil { - continue - } - ctx = contexts[i] - break - } - - checkers := append(aherrcheck.GetErrChecks(), aherrcheck.GetCheckersFromCtx(ctx)...) - var err = r.getErr() - for _, fn := range checkers { - err = fn(ctx, err) - if err == nil { - return false - } - } - - setErr(errors.WrapCaller(err, 2)) - - return true -} - -func errRecovery[T any](setter *T, isErr func() bool, getErr func() error, newErr func(err error) T, callbacks ...func(err error) error) { - if setter == nil { - errMust(errors.Errorf("setter is nil")) - } - - err := errors.Parse(recover()) - if err == nil && !isErr() { - return - } - - if err == nil { - err = getErr() - } - - for _, fn := range callbacks { - err = fn(err) - if err == nil { - return - } - } - - err = errors.WrapCaller(err, 1) - *setter = newErr(err) -} - -func unwrapErr[T any](r Result[T], setter1 *error, setter2 *Error, contexts ...context.Context) (T, error) { - if setter1 == nil && setter2 == nil { - debug.PrintStack() - panic("Unwrap: error setter is nil") - } - - var ret = r.getValue() - if r.IsOK() { - return ret, nil - } - - var ctx = context.Background() - if len(contexts) > 0 { - ctx = contexts[0] - } - - getSetterErr := func() error { - err := lo.FromPtr(setter1) - if err == nil { - err = lo.FromPtr(setter2).getErr() - } - return err - } - setterErr := getSetterErr() - if setterErr != nil { - log.Error(ctx).Msgf("Unwrap: error setter has value, err=%v", setterErr) - } - - var err = r.getErr() - for _, fn := range aherrcheck.GetErrChecks() { - err = fn(ctx, err) - if err == nil { - return ret, nil - } - } - - return ret, err -} diff --git a/internal/color/color.go b/internal/color/color.go index 4a6b4c73..2358c28d 100644 --- a/internal/color/color.go +++ b/internal/color/color.go @@ -19,7 +19,7 @@ const ( ) // P adds the coloring to the given string. -func (c Color) P(s string, args ...interface{}) string { +func (c Color) P(s string, args ...any) string { return fmt.Sprintf("\x1b[%dm%s\x1b[0m", uint8(c), fmt.Sprintf(s, args...)) } diff --git a/errors/errinter/aaa.go b/internal/errors/errinter/aaa.go similarity index 83% rename from errors/errinter/aaa.go rename to internal/errors/errinter/aaa.go index f40f718c..e7fc604e 100644 --- a/errors/errinter/aaa.go +++ b/internal/errors/errinter/aaa.go @@ -9,18 +9,19 @@ import ( ) type Error interface { + error ID() string Kind() string - Error() string String() string MarshalJSON() ([]byte, error) } -type ErrUnwrap interface { +type ErrUnwrapper interface { Unwrap() error } type ErrorProto interface { + error Proto() proto.Message } @@ -28,6 +29,14 @@ type GRPCStatus interface { GRPCStatus() *status.Status } +type ErrIs interface { + Is(error) bool +} + +type ErrAs interface { + As(any) bool +} + var ( _ json.Marshaler = (Tags)(nil) _ fmt.Formatter = (Tags)(nil) @@ -43,6 +52,14 @@ func (t Maps) Tags() Tags { return tags } +func (t Maps) ToMapString() map[string]string { + data := make(map[string]string, len(t)) + for key, value := range t { + data[key] = fmt.Sprintf("%v", value) + } + return data +} + type Tags []Tag func (t Tags) Format(f fmt.State, verb rune) { @@ -60,7 +77,7 @@ func (t Tags) Format(f fmt.State, verb rune) { } func (t Tags) ToMap() map[string]string { - var data = make(map[string]string, len(t)) + data := make(map[string]string, len(t)) for _, tag := range t { data[tag.K] = fmt.Sprintf("%v", tag.V) } @@ -83,11 +100,3 @@ type Tag struct { func (t Tag) String() string { return fmt.Sprintf("%s: %v", t.K, t.V) } - -type ErrIs interface { - Is(error) bool -} - -type ErrAs interface { - As(any) bool -} diff --git a/internal/errors/errinter/colorfield.go b/internal/errors/errinter/colorfield.go new file mode 100644 index 00000000..4bcc7170 --- /dev/null +++ b/internal/errors/errinter/colorfield.go @@ -0,0 +1,36 @@ +package errinter + +import ( + "strings" + + "github.com/pubgo/funk/v2/internal/color" +) + +var width = 11 + +func getColorErrField(name string) string { + if width-len(name) < 0 { + return name + } + return strings.Repeat(" ", width-len(name)) + name +} + +var ( + ColorKind = color.Green.Str(getColorErrField("kind")) + ColorMsg = color.Green.Str(getColorErrField("msg")) + ColorService = color.Green.Str(getColorErrField("service")) + ColorOperation = color.Green.Str(getColorErrField("operation")) + ColorId = color.Green.Str(getColorErrField("id")) + ColorDetail = color.Green.Str(getColorErrField("detail")) + ColorTags = color.Green.Str(getColorErrField("tags")) + ColorErrMsg = color.Red.Str(getColorErrField("err_msg")) + ColorErrDetail = color.Red.Str(getColorErrField("err_detail")) + ColorCaller = color.Green.Str(getColorErrField("caller")) + ColorCode = color.Green.Str(getColorErrField("code")) + ColorMessage = color.Green.Str(getColorErrField("message")) + ColorBiz = color.Green.Str(getColorErrField("biz_code")) + ColorStatusCode = color.Green.Str(getColorErrField("status_code")) + ColorName = color.Green.Str(getColorErrField("name")) + ColorStack = color.Green.Str(getColorErrField("stack")) + ColorVersion = color.Green.Str(getColorErrField("version")) +) diff --git a/errors/errinter/utils.go b/internal/errors/errinter/utils.go similarity index 79% rename from errors/errinter/utils.go rename to internal/errors/errinter/utils.go index e407a674..d547e7d4 100644 --- a/errors/errinter/utils.go +++ b/internal/errors/errinter/utils.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" "os" - "strings" "sync" "github.com/k0kubun/pp/v3" + "github.com/rs/xid" "github.com/rs/zerolog/log" "github.com/samber/lo" "google.golang.org/protobuf/encoding/prototext" @@ -16,13 +16,12 @@ import ( "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/structpb" - "github.com/pubgo/funk" - "github.com/pubgo/funk/log/logutil" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/proto/errorpb" + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/log/logutil" + "github.com/pubgo/funk/v2/proto/errorpb" ) -func ParseError(val interface{}) error { +func ParseError(val any) error { if funk.IsNil(val) { return nil } @@ -36,42 +35,23 @@ func ParseError(val interface{}) error { return errors.New(v) case []byte: return errors.New(string(v)) + case proto.Message: + return errors.New(prototext.Format(v)) default: - return errors.New(SimplePrint(v)) + return errors.New(errPretty().Sprint(v)) } } -var Simple = sync.OnceValue(func() *pp.PrettyPrinter { - printer := pp.New() - printer.SetColoringEnabled(false) - printer.SetExportedOnly(false) - printer.SetOmitEmpty(true) - printer.SetMaxDepth(3) - return printer -}) - -func SimplePrint(v interface{}) string { - return strings.ReplaceAll(Simple().Sprint(v), "\n", "") -} - func GetErrorId(err error) string { - if err == nil { - return "" - } - - for err != nil { - if v, ok := err.(Error); ok { - return v.ID() - } - - err = Unwrap(err) + if v, ok := lo.ErrorsAs[Error](err); ok && v != nil { + return v.ID() } - return "" + return xid.New().String() } func Unwrap(err error) error { - u, ok := err.(ErrUnwrap) + u, ok := err.(ErrUnwrapper) if !ok { return nil } @@ -103,8 +83,7 @@ func Debug(err error) { return } - pretty.SetDefaultMaxDepth(20) - pretty.Println(err) + DebugPretty().Println(err) } func MustTagsToAny(tags ...*errorpb.Tag) []*anypb.Any { @@ -171,3 +150,21 @@ func MustProtoToAny(p proto.Message) *anypb.Any { return pb } + +var errPretty = sync.OnceValue(func() *pp.PrettyPrinter { + printer := pp.New() + printer.SetColoringEnabled(false) + printer.SetExportedOnly(false) + printer.SetOmitEmpty(true) + printer.SetMaxDepth(3) + return printer +}) + +var DebugPretty = sync.OnceValue(func() *pp.PrettyPrinter { + printer := pp.New() + printer.SetColoringEnabled(true) + printer.SetExportedOnly(false) + printer.SetOmitEmpty(true) + printer.SetMaxDepth(5) + return printer +}) diff --git a/internal/errors/errinter/z_util_test.go b/internal/errors/errinter/z_util_test.go new file mode 100644 index 00000000..485c5eb9 --- /dev/null +++ b/internal/errors/errinter/z_util_test.go @@ -0,0 +1,42 @@ +package errinter_test + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/encoding/prototext" + + "github.com/pubgo/funk/v2/internal/errors/errinter" + + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/proto/errorpb" +) + +func TestGetErrorId(t *testing.T) { + err := errors.New("test error id") + pbTxt := prototext.Format(errinter.ParseErrToPb(err)) + errId := errinter.GetErrorId(err) + assert.NotEmpty(t, errId) + assert.Contains(t, pbTxt, errId) +} + +func TestParseError(t *testing.T) { + assert.Equal(t, errinter.ParseError(nil), nil) + assert.Equal(t, errinter.ParseError("hello").Error(), "hello") + assert.Equal(t, errinter.ParseError(fmt.Errorf("err test")).Error(), "err test") + + errMsg := errinter.ParseError(prototext.Format(errinter.MustProtoToAny(&errorpb.ErrMsg{Msg: "test msg error"}))).Error() + assert.Equal(t, + strings.ReplaceAll(errMsg, " ", " "), + "[type.googleapis.com/errors.ErrMsg]: {\n msg: \"test msg error\"\n}\n", + ) + + ctx := context.WithValue(context.Background(), "hello", "world") + assert.Equal(t, + errinter.ParseError(ctx).Error(), + "&context.valueCtx{\n Context: context.backgroundCtx{},\n key: \"hello\",\n val: \"world\",\n}", + ) +} diff --git a/internal/example/app/main.go b/internal/example/app/main.go deleted file mode 100644 index f3547aa5..00000000 --- a/internal/example/app/main.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/pubgo/funk/recovery" -) - -// 应用的集成开发, 在最后扑捉panic - -func A() string { - panic("未知错误") -} - -func B() string { - return A() -} - -func C() string { - a := A() - if a == "" { - return B() - } - return "" -} - -func main() { - defer recovery.Exit() - - fmt.Println(C()) -} diff --git a/internal/example/env/main.go b/internal/example/env/main.go deleted file mode 100644 index ab54ce9f..00000000 --- a/internal/example/env/main.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "os" - - "github.com/pubgo/funk/env" - "github.com/pubgo/funk/pretty" -) - -func main() { - pretty.Println(os.Environ()) - pretty.Println(env.Map()) -} diff --git a/internal/example/errors/main.go b/internal/example/errors/main.go index 56a55ada..6e192142 100644 --- a/internal/example/errors/main.go +++ b/internal/example/errors/main.go @@ -1,9 +1,9 @@ package main import ( - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/recovery" ) // 单个pkg的error处理 diff --git a/internal/example/log/main.go b/internal/example/log/main.go index eba04422..e9641c91 100644 --- a/internal/example/log/main.go +++ b/internal/example/log/main.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "github.com/pubgo/funk/log" + "github.com/pubgo/funk/v2/log" ) var dd = log.GetLogger("dd") diff --git a/langx/parse.go b/langx/parse.go new file mode 100644 index 00000000..662ca6ad --- /dev/null +++ b/langx/parse.go @@ -0,0 +1,17 @@ +package langx + +import ( + "golang.org/x/text/language" + + "github.com/pubgo/funk/v2/log" +) + +func ParseTags(lang string) []language.Tag { + tags, _, err := language.ParseAcceptLanguage(lang) + if err != nil { + log.Err(err).Str("lang", lang).Msg("parse accept-language failed") + return []language.Tag{language.Chinese} + } + + return tags +} diff --git a/langx/parse_test.go b/langx/parse_test.go new file mode 100644 index 00000000..94ccc9bd --- /dev/null +++ b/langx/parse_test.go @@ -0,0 +1,42 @@ +package langx + +import ( + "reflect" + "testing" + + "golang.org/x/text/language" +) + +func TestParseTags(t *testing.T) { + type args struct { + lang string + } + tests := []struct { + name string + args args + want []language.Tag + }{ + { + name: "testChinese", + args: args{lang: "zh"}, + want: []language.Tag{language.Chinese}, + }, + { + name: "testEn", + args: args{lang: "en"}, + want: []language.Tag{language.English}, + }, + { + name: "testWrong", + args: args{lang: "one two"}, + want: []language.Tag{language.Chinese}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ParseTags(tt.args.lang); !reflect.DeepEqual(got, tt.want) { + t.Errorf("ParseTags() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/log/aaa.go b/log/aaa.go index c4468d64..7dcc4f5e 100644 --- a/log/aaa.go +++ b/log/aaa.go @@ -18,7 +18,6 @@ type Logger interface { WithName(name string) Logger WithFields(m Map) Logger WithCallerSkip(skip int) Logger - WithEvent(evt *Event) Logger WithLevel(lvl Level) Logger Debug(ctx ...context.Context) *Event diff --git a/log/context.go b/log/context.go index 6b2ffdec..2a43ee15 100644 --- a/log/context.go +++ b/log/context.go @@ -28,7 +28,7 @@ func GetFromCtx(ctx context.Context, loggers ...Logger) Logger { return defaultLog } -func CreateCtxWithLogger(ctx context.Context, ll Logger) context.Context { +func CreateCtx(ctx context.Context, ll Logger) context.Context { if ll == nil || ctx == nil { panic("ctx or log param is nil") } @@ -53,7 +53,7 @@ func UpdateEventCtx(ctx context.Context, fields Map) context.Context { return ctx } - var evt = NewEvent() + evt := NewEvent() if e := getEventFromCtx(ctx); e != nil { evt = e } else { diff --git a/log/event.go b/log/event.go index 823be722..8d2528d0 100644 --- a/log/event.go +++ b/log/event.go @@ -60,6 +60,16 @@ func GetEventBuf(evt *Event) []byte { return append(convertEvent(evt).buf, '}') } +func cloneEvent(target *Event) *Event { + if target == nil { + return nil + } + + newTarget := zerolog.Dict() + convertEvent(newTarget).buf = bytes.Clone(convertEvent(target).buf) + return newTarget +} + func mergeEvent(target *Event, from ...*Event) *Event { if len(from) == 0 { return target diff --git a/log/global.go b/log/global.go index 13b8f506..2412f80b 100644 --- a/log/global.go +++ b/log/global.go @@ -7,12 +7,13 @@ import ( "os" "time" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/generic" - "github.com/rs/zerolog" zlog "github.com/rs/zerolog/log" + "github.com/samber/lo" + + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/internal/errors/errinter" ) var ( @@ -36,7 +37,7 @@ var ( e.Discard() }) - _ = generic.Init(func() { + _ = funk.Init(func() { zerolog.SetGlobalLevel(zerolog.DebugLevel) zerolog.ErrorMarshalFunc = func(err error) any { if err == nil { @@ -54,7 +55,7 @@ var ( }) // stdZeroLog default zerolog for debug - stdZeroLog = generic.Ptr( + stdZeroLog = lo.ToPtr( zerolog.New(os.Stderr). Level(zerolog.DebugLevel). With().Timestamp(). @@ -65,8 +66,8 @@ var ( })).Hook(logGlobalHook), ) - _ = generic.Init(func() { - zlog.Logger = generic.FromPtr(stdZeroLog) + _ = funk.Init(func() { + zlog.Logger = lo.FromPtr(stdZeroLog) }) // stdLog is the global logger. @@ -85,7 +86,7 @@ func GetLogger(names ...string) Logger { func SetLogger(log *zerolog.Logger) { assert.If(log == nil, "[log] should not be nil") - log = generic.Ptr(log.Hook(logGlobalHook)) + log = lo.ToPtr(log.Hook(logGlobalHook)) stdZeroLog = log zlog.Logger = *log @@ -164,7 +165,7 @@ func Printf(format string, v ...any) { } func Output(w io.Writer) Logger { - return New(generic.Ptr(stdZeroLog.Output(w))) + return New(lo.ToPtr(stdZeroLog.Output(w))) } type writerFunc func(p []byte) (n int, err error) @@ -174,5 +175,5 @@ func (w writerFunc) Write(p []byte) (n int, err error) { } func OutputWriter(w func(p []byte) (n int, err error)) Logger { - return New(generic.Ptr(stdZeroLog.Output(writerFunc(w)))) + return New(lo.ToPtr(stdZeroLog.Output(writerFunc(w)))) } diff --git a/log/impl.log.go b/log/impl.log.go index eadb07da..74263dbb 100644 --- a/log/impl.log.go +++ b/log/impl.log.go @@ -3,12 +3,13 @@ package log import ( "context" "fmt" + "maps" "strings" "github.com/rs/zerolog" - "github.com/pubgo/funk/errors/errinter" - "github.com/pubgo/funk/log/logfields" + "github.com/pubgo/funk/v2/internal/errors/errinter" + "github.com/pubgo/funk/v2/log/logfields" ) var _ Logger = (*loggerImpl)(nil) @@ -152,7 +153,7 @@ func (l *loggerImpl) Err(err error, ctxL ...context.Context) *zerolog.Event { return nil } - var fn = func(e *zerolog.Event) { + fn := func(e *zerolog.Event) { if err == nil { return } @@ -194,8 +195,14 @@ func (l *loggerImpl) enabled(ctx context.Context, lvl zerolog.Level) bool { } func (l *loggerImpl) copy() *loggerImpl { - log := *l - return &log + return &loggerImpl{ + log: l.log, + content: cloneEvent(l.content), + fields: maps.Clone(l.fields), + lvl: l.lvl, + name: l.name, + callerSkip: l.callerSkip, + } } func (l *loggerImpl) getLog() *zerolog.Logger { @@ -206,19 +213,24 @@ func (l *loggerImpl) getLog() *zerolog.Logger { } func (l *loggerImpl) newEvent(ctx context.Context, e *zerolog.Event) *zerolog.Event { - if l.name != "" { - e = e.Str(logfields.Logger, l.name) + name := l.name + if m, ok := l.fields[logfields.Module].(string); ok { + name = m + } + + if name != "" { + e = e.Str(logfields.Logger, name) } if l.callerSkip != 0 { e = e.CallerSkipFrame(l.callerSkip) } - if l.fields != nil && len(l.fields) > 0 { + if len(l.fields) > 0 { e = e.Fields(l.fields) } - e = e.Ctx(createFieldCtx(ctx, &fieldMap{name: l.name, fields: l.fields})) + e = e.Ctx(createFieldCtx(ctx, &fieldMap{name: name, fields: l.fields})) return mergeEvent(e, getEventFromCtx(ctx), l.content) } diff --git a/log/impl.slog.go b/log/impl.slog.go index 508d1912..de1eb432 100644 --- a/log/impl.slog.go +++ b/log/impl.slog.go @@ -6,6 +6,8 @@ import ( "github.com/rs/zerolog" slogcommon "github.com/samber/slog-common" + + "github.com/pubgo/funk/v2/log/slogutil" ) func NewSlog(log Logger) slog.Handler { @@ -18,6 +20,20 @@ var logLevels = map[slog.Level]zerolog.Level{ slog.LevelWarn: zerolog.WarnLevel, slog.LevelError: zerolog.ErrorLevel, } + +func convertSlog(lvl slog.Level) slog.Level { + switch { + case lvl < slog.LevelInfo: + return slog.LevelDebug + case lvl < slog.LevelWarn: + return slog.LevelInfo + case lvl < slog.LevelError: + return slog.LevelWarn + default: + return slog.LevelError + } +} + var _ slog.Handler = (*slogImpl)(nil) type slogImpl struct { @@ -25,25 +41,22 @@ type slogImpl struct { } func (s slogImpl) Enabled(ctx context.Context, level slog.Level) bool { - return s.l.(*loggerImpl).enabled(ctx, logLevels[level]) + return s.l.(*loggerImpl).enabled(ctx, logLevels[convertSlog(level)]) } func (s slogImpl) Handle(ctx context.Context, r slog.Record) error { - if r.Level < 0 { - r.Level = slog.LevelDebug - } - - logger := s.l.WithLevel(logLevels[r.Level]) + level := convertSlog(r.Level) + logger := s.l.WithLevel(logLevels[level]) var evt *Event - switch r.Level { + switch level { case slog.LevelDebug: evt = logger.Debug(ctx) case slog.LevelInfo: evt = logger.Info(ctx) case slog.LevelWarn: evt = logger.Warn(ctx) - case slog.LevelError: + default: evt = logger.Error(ctx) } @@ -51,12 +64,20 @@ func (s slogImpl) Handle(ctx context.Context, r slog.Record) error { return nil } + if isLogDisabled(ctx) { + return nil + } + if !r.Time.IsZero() { evt.Time(zerolog.TimestampFieldName, r.Time) } r.Attrs(func(attr slog.Attr) bool { - evt.Any(attr.Key, attr.Value.Any()) + if fn, ok := attr.Value.Any().(slogutil.LogFunc); ok { + evt.Func(fn) + } else { + evt.Any(attr.Key, attr.Value.Any()) + } return true }) diff --git a/log/logfields/fields.go b/log/logfields/fields.go index 7e46499e..c4124e35 100644 --- a/log/logfields/fields.go +++ b/log/logfields/fields.go @@ -1,10 +1,14 @@ package logfields const ( - Module = "module" - Msg = "log_msg" - Logger = "logger" + Module = "module" + Operation = "operation" + Action = "action" + Msg = "log_msg" + Logger = "logger" + Error = "error" ErrorDetail = "error_detail" ErrorStack = "error_stack" + ErrorID = "error_id" ) diff --git a/log/slogutil/util.go b/log/slogutil/util.go new file mode 100644 index 00000000..b89e4456 --- /dev/null +++ b/log/slogutil/util.go @@ -0,0 +1,13 @@ +package slogutil + +import ( + "log/slog" + + "github.com/rs/zerolog" +) + +type LogFunc func(evt *zerolog.Event) + +func Func(fn LogFunc) slog.Attr { + return slog.Any("func", fn) +} diff --git a/log/util.go b/log/util.go index 17f83e0a..51e9cd52 100644 --- a/log/util.go +++ b/log/util.go @@ -3,9 +3,10 @@ package log import ( "context" - "github.com/pubgo/funk/errors/errinter" "github.com/samber/lo" "google.golang.org/protobuf/encoding/prototext" + + "github.com/pubgo/funk/v2/internal/errors/errinter" ) func errDetail(err error) string { @@ -20,7 +21,7 @@ func RecordErr(logs ...Logger) func(ctx context.Context, err error) error { return func(ctx context.Context, err error) error { ctx = lo.If(ctx != nil, ctx).ElseF(context.Background) - var logger = stdLog + logger := stdLog if len(logs) > 0 { logger = logs[0] } diff --git a/log/z_log_std_test.go b/log/z_log_std_test.go index a4e67baf..616fda51 100644 --- a/log/z_log_std_test.go +++ b/log/z_log_std_test.go @@ -3,10 +3,11 @@ package log_test import ( "testing" - "github.com/pubgo/funk/log" + "github.com/pubgo/funk/v2/log" ) func TestStdLog(t *testing.T) { - evt := log.NewEvent().Str("hello", "world").Int("int", 100) - log.NewStd(log.GetLogger("with_event").WithEvent(evt)).Print("dddd") + log.NewStd(log.GetLogger("with_event"). + WithFields(log.Map{"hello": "world", "int": 100})). + Print("dddd") } diff --git a/log/z_log_test.go b/log/z_log_test.go index 1e05d7fd..02c3f7d2 100644 --- a/log/z_log_test.go +++ b/log/z_log_test.go @@ -10,16 +10,22 @@ import ( "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/log/logutil" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/log/logutil" ) +func TestLogLevel(t *testing.T) { + log.Warn().Msg("test warn") + logger := log.GetLogger().WithLevel(zerolog.ErrorLevel) + logger.Warn().Msg("test warn") +} + func TestWithName(t *testing.T) { log.GetLogger("log1"). Debug(). Func(func(e *zerolog.Event) { - var buf = gjson.ParseBytes(log.GetEventBuf(e)) + buf := gjson.ParseBytes(log.GetEventBuf(e)) assert.Equal(t, buf.Get("logger").String(), "log1") }).Msg("hello") @@ -27,13 +33,13 @@ func TestWithName(t *testing.T) { WithName("log2"). Debug(). Func(func(e *zerolog.Event) { - var buf = gjson.ParseBytes(log.GetEventBuf(e)) + buf := gjson.ParseBytes(log.GetEventBuf(e)) assert.Equal(t, buf.Get("logger").String(), "log1.log2") }).Msg("hello") log.Debug(). Func(func(e *zerolog.Event) { - var buf = gjson.ParseBytes(log.GetEventBuf(e)) + buf := gjson.ParseBytes(log.GetEventBuf(e)) assert.Equal(t, buf.Get("logger").String(), "") }).Msg("hello") } @@ -79,11 +85,11 @@ func TestName(t *testing.T) { } func TestEvent(t *testing.T) { - var getEvt = func() *log.Event { + getEvt := func() *log.Event { return log.NewEvent().Str("hello", "world").Int("int", 100).Dict("ddd", log.NewEvent()) } - var getCtx = func(evt *log.Event) context.Context { + getCtx := func(evt *log.Event) context.Context { return log.CreateEventCtx(context.Background(), evt) } @@ -101,8 +107,10 @@ func TestEvent(t *testing.T) { } func TestWithEvent(t *testing.T) { - evt := log.NewEvent().Str("hello", "hello world").Int("int", 100) - ee := log.GetLogger("with_event").WithEvent(evt).Info().Str("info", "abcd") + ee := log.GetLogger("with_event"). + WithFields(log.Map{"hello": "hello world", "int": 100}). + Info(). + Str("info", "abcd") ee.Msg("dddd") } diff --git a/log/z_slog_test.go b/log/z_slog_test.go new file mode 100644 index 00000000..a78705fb --- /dev/null +++ b/log/z_slog_test.go @@ -0,0 +1,19 @@ +package log_test + +import ( + "log/slog" + "testing" + + "github.com/rs/zerolog" + + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/log/slogutil" +) + +func TestSlog(t *testing.T) { + slog.SetDefault(slog.New(log.NewSlog(log.GetLogger("")))) + slog.Info("ok") + slog.Info("ok", slogutil.Func(func(evt *zerolog.Event) { + evt.Str("record", "ok") + })) +} diff --git a/merge/_.go b/merge/_.go new file mode 100644 index 00000000..45ebffed --- /dev/null +++ b/merge/_.go @@ -0,0 +1,3 @@ +package merge + +// https://github.com/TwiN/deepmerge diff --git a/merge/merge.go b/merge/merge.go index 63bbfb34..84382237 100644 --- a/merge/merge.go +++ b/merge/merge.go @@ -4,8 +4,8 @@ import ( "github.com/jinzhu/copier" "github.com/mitchellh/mapstructure" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/result" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/result" ) type Option func(opts *copier.Option) @@ -29,7 +29,7 @@ func Copy[A, B any](dst *A, src *B, opts ...Option) result.Result[*A] { err := copier.CopyWithOption(dst, src, opt) if err != nil { - return result.Err[*A](errH(err)) + return result.Fail[*A](errH(err)) } return result.OK(dst) diff --git a/merge/merge_test.go b/merge/merge_test.go index d9e5ef6b..a863392d 100644 --- a/merge/merge_test.go +++ b/merge/merge_test.go @@ -3,7 +3,7 @@ package merge import ( "testing" - "github.com/pubgo/funk/pretty" + "github.com/pubgo/funk/v2/pretty" ) type dst struct { @@ -27,17 +27,17 @@ func TestStruct(t *testing.T) { rr := &src{Name: "2", Hello: "2"} pretty.Println(Struct(&dd, &rr)) - d1 := map[string]interface{}{"a": src{Name: "2", Hello: "2"}} + d1 := map[string]any{"a": src{Name: "2", Hello: "2"}} d2 := map[string]dst{"a": {Name: "1", Hello: "1"}, "b": {Name: "1", Hello: "1"}} - Copy(&d1, &d2).Unwrap() + Copy(&d1, &d2).Must() } func TestMapStruct(t *testing.T) { - pretty.Println(MapStruct(&dst{name: "1", Hello: "1"}, map[string]interface{}{"name": "2", "hello": "2"})) - pretty.Println(MapStruct(&dst{name: "1", Hello: "1"}, &map[string]interface{}{"name": "2", "hello": "2"})) + pretty.Println(MapStruct(&dst{name: "1", Hello: "1"}, map[string]any{"name": "2", "hello": "2"})) + pretty.Println(MapStruct(&dst{name: "1", Hello: "1"}, &map[string]any{"name": "2", "hello": "2"})) var dd map[string]dst - pretty.Println(MapStruct(&dd, map[string]map[string]interface{}{"name": {"name": "2", "hello": "2"}, "hello": {"name": "2", "hello": "2"}})) + pretty.Println(MapStruct(&dd, map[string]map[string]any{"name": {"name": "2", "hello": "2"}, "hello": {"name": "2", "hello": "2"}})) // var rr = &map[string]interface{}{"name": "2", "hello": "2"} // pretty.Println(MapStruct(&dd, &rr)) // error diff --git a/netutil/conn.go b/netutil/conn.go index 9e484b95..5a140ac0 100644 --- a/netutil/conn.go +++ b/netutil/conn.go @@ -9,8 +9,8 @@ import ( "strconv" "strings" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/recovery" ) type sockOpts struct { @@ -110,12 +110,12 @@ func WithChmod(mask os.FileMode) SockOpt { } } -func MustGetPort(addrOrNet interface{}) int { +func MustGetPort(addrOrNet any) int { return assert.Must1(GetPort(addrOrNet)) } // GetPort returns the port of an endpoint address. -func GetPort(addrOrNet interface{}) (int, error) { +func GetPort(addrOrNet any) (int, error) { var addr string switch addrNet := addrOrNet.(type) { case net.Addr: diff --git a/netutil/conncheck.go b/netutil/conncheck.go index 45a32465..3a8c1592 100644 --- a/netutil/conncheck.go +++ b/netutil/conncheck.go @@ -8,7 +8,7 @@ import ( "net" "syscall" - "github.com/pubgo/funk/errors" + "github.com/pubgo/funk/v2/errors" ) var errUnexpectedRead = errors.New("unexpected read from socket") diff --git a/netutil/util.go b/netutil/util.go index 0d68d89b..d621f3e7 100644 --- a/netutil/util.go +++ b/netutil/util.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/pubgo/funk/assert" + "github.com/pubgo/funk/v2/assert" ) var localIpReg = assert.Exit1(regexp.Compile(`\d+\.\d+\.\d+\.\d+`)) diff --git a/pathutil/file.go b/pathutil/file.go index 2c83a2a0..cf6914ba 100755 --- a/pathutil/file.go +++ b/pathutil/file.go @@ -10,9 +10,9 @@ import ( "regexp" "strings" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/recovery" ) // IsNotExist check if the file exists @@ -34,7 +34,7 @@ func IsNotExistMkDir(src string) (err error) { assert.Must(MkDir(src), "MkDir Error") } - return + return err } // MkDir create a directory @@ -78,7 +78,7 @@ func CopyFile(source, dest string) (err error) { sourceinfo := assert.Must1(os.Stat(source)) assert.Must(os.Chmod(dest, sourceinfo.Mode())) - return + return err } // CopyDir copies the source directory to the dest directory. @@ -105,7 +105,7 @@ func CopyDir(source, dest string) (err error) { } } - return + return err } // GrepFile like command grep -E @@ -114,12 +114,12 @@ func CopyDir(source, dest string) (err error) { func GrepFile(patten, filename string) (lines []string, err error) { re, err := regexp.Compile(patten) if err != nil { - return + return lines, err } fd, err := os.Open(filename) if err != nil { - return + return lines, err } lines = make([]string, 0) reader := bufio.NewReader(fd) @@ -181,7 +181,7 @@ func GetPathDirs(absDir string) (re []string) { } } } - return + return re } // GetPathFiles 获取目录所有文件 @@ -194,7 +194,7 @@ func GetPathFiles(absDir string) (re []string) { } } } - return + return re } // GetModelPath 获取目录地址 diff --git a/pathutil/sys.go b/pathutil/sys.go index 94a99591..301827b4 100644 --- a/pathutil/sys.go +++ b/pathutil/sys.go @@ -29,9 +29,9 @@ func PathExists(path string) (bool, error) { func Search(fileName string, paths ...string) (fullpath string, err error) { for _, path := range paths { if fullpath = filepath.Join(path, fileName); Exist(fullpath) { - return + return fullpath, err } } err = errors.New(fullpath + " not found in paths") - return + return fullpath, err } diff --git a/pkg/gen/cloudjobpb/options.pb.go b/pkg/gen/cloudjobpb/options.pb.go deleted file mode 100644 index 81d71d94..00000000 --- a/pkg/gen/cloudjobpb/options.pb.go +++ /dev/null @@ -1,118 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.35.2 -// protoc v5.29.3 -// source: cloudjobs/options.proto - -package cloudjobpb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - descriptorpb "google.golang.org/protobuf/types/descriptorpb" - reflect "reflect" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -var file_cloudjobs_options_proto_extTypes = []protoimpl.ExtensionInfo{ - { - ExtendedType: (*descriptorpb.ServiceOptions)(nil), - ExtensionType: (*string)(nil), - Field: 10010, - Name: "lava.cloudjobs.job_name", - Tag: "bytes,10010,opt,name=job_name", - Filename: "cloudjobs/options.proto", - }, - { - ExtendedType: (*descriptorpb.MethodOptions)(nil), - ExtensionType: (*string)(nil), - Field: 10011, - Name: "lava.cloudjobs.subject_name", - Tag: "bytes,10011,opt,name=subject_name", - Filename: "cloudjobs/options.proto", - }, -} - -// Extension fields to descriptorpb.ServiceOptions. -var ( - // job name is same with config jobs consumers job name - // - // optional string job_name = 10010; - E_JobName = &file_cloudjobs_options_proto_extTypes[0] -) - -// Extension fields to descriptorpb.MethodOptions. -var ( - // subject name is same with config jobs consumers - // subject name sametime is topic name - // - // optional string subject_name = 10011; - E_SubjectName = &file_cloudjobs_options_proto_extTypes[1] -) - -var File_cloudjobs_options_proto protoreflect.FileDescriptor - -var file_cloudjobs_options_proto_rawDesc = []byte{ - 0x0a, 0x17, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x73, 0x2f, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x6c, 0x61, 0x76, 0x61, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x73, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x3b, 0x0a, 0x08, 0x6a, - 0x6f, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9a, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x42, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9b, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x35, 0x5a, 0x33, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, - 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x70, 0x62, 0x3b, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6a, 0x6f, - 0x62, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var file_cloudjobs_options_proto_goTypes = []any{ - (*descriptorpb.ServiceOptions)(nil), // 0: google.protobuf.ServiceOptions - (*descriptorpb.MethodOptions)(nil), // 1: google.protobuf.MethodOptions -} -var file_cloudjobs_options_proto_depIdxs = []int32{ - 0, // 0: lava.cloudjobs.job_name:extendee -> google.protobuf.ServiceOptions - 1, // 1: lava.cloudjobs.subject_name:extendee -> google.protobuf.MethodOptions - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 0, // [0:2] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_cloudjobs_options_proto_init() } -func file_cloudjobs_options_proto_init() { - if File_cloudjobs_options_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_cloudjobs_options_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 2, - NumServices: 0, - }, - GoTypes: file_cloudjobs_options_proto_goTypes, - DependencyIndexes: file_cloudjobs_options_proto_depIdxs, - ExtensionInfos: file_cloudjobs_options_proto_extTypes, - }.Build() - File_cloudjobs_options_proto = out.File - file_cloudjobs_options_proto_rawDesc = nil - file_cloudjobs_options_proto_goTypes = nil - file_cloudjobs_options_proto_depIdxs = nil -} diff --git a/pkg/gen/cloudjobpb/types.pb.go b/pkg/gen/cloudjobpb/types.pb.go deleted file mode 100644 index efbf403d..00000000 --- a/pkg/gen/cloudjobpb/types.pb.go +++ /dev/null @@ -1,238 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.35.2 -// protoc v5.29.3 -// source: cloudjobs/types.proto - -package cloudjobpb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type PushEventOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The content type for the data (optional). - ContentType *string `protobuf:"bytes,1,opt,name=content_type,json=contentType,proto3,oneof" json:"content_type,omitempty"` - // The metadata passing to pub components - // - // metadata property: - // - key : the key of the message. - Metadata map[string]string `protobuf:"bytes,2,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // The delay duration of the message. - DelayDur *durationpb.Duration `protobuf:"bytes,3,opt,name=delay_dur,json=delayDur,proto3,oneof" json:"delay_dur,omitempty"` - // The message id - MsgId *string `protobuf:"bytes,4,opt,name=msg_id,json=msgId,proto3,oneof" json:"msg_id,omitempty"` -} - -func (x *PushEventOptions) Reset() { - *x = PushEventOptions{} - mi := &file_cloudjobs_types_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PushEventOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PushEventOptions) ProtoMessage() {} - -func (x *PushEventOptions) ProtoReflect() protoreflect.Message { - mi := &file_cloudjobs_types_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PushEventOptions.ProtoReflect.Descriptor instead. -func (*PushEventOptions) Descriptor() ([]byte, []int) { - return file_cloudjobs_types_proto_rawDescGZIP(), []int{0} -} - -func (x *PushEventOptions) GetContentType() string { - if x != nil && x.ContentType != nil { - return *x.ContentType - } - return "" -} - -func (x *PushEventOptions) GetMetadata() map[string]string { - if x != nil { - return x.Metadata - } - return nil -} - -func (x *PushEventOptions) GetDelayDur() *durationpb.Duration { - if x != nil { - return x.DelayDur - } - return nil -} - -func (x *PushEventOptions) GetMsgId() string { - if x != nil && x.MsgId != nil { - return *x.MsgId - } - return "" -} - -type RegisterJobOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - JobName *string `protobuf:"bytes,1,opt,name=job_name,json=jobName,proto3,oneof" json:"job_name,omitempty"` -} - -func (x *RegisterJobOptions) Reset() { - *x = RegisterJobOptions{} - mi := &file_cloudjobs_types_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RegisterJobOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterJobOptions) ProtoMessage() {} - -func (x *RegisterJobOptions) ProtoReflect() protoreflect.Message { - mi := &file_cloudjobs_types_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RegisterJobOptions.ProtoReflect.Descriptor instead. -func (*RegisterJobOptions) Descriptor() ([]byte, []int) { - return file_cloudjobs_types_proto_rawDescGZIP(), []int{1} -} - -func (x *RegisterJobOptions) GetJobName() string { - if x != nil && x.JobName != nil { - return *x.JobName - } - return "" -} - -var File_cloudjobs_types_proto protoreflect.FileDescriptor - -var file_cloudjobs_types_proto_rawDesc = []byte{ - 0x0a, 0x15, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x6c, 0x61, 0x76, 0x61, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x73, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc6, 0x02, 0x0a, 0x10, 0x50, 0x75, 0x73, 0x68, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0c, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x88, 0x01, 0x01, 0x12, 0x4a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x6c, 0x61, 0x76, 0x61, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x73, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x3b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x64, 0x75, 0x72, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x01, - 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x44, 0x75, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, - 0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, - 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x88, 0x01, 0x01, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x64, 0x65, 0x6c, 0x61, - 0x79, 0x5f, 0x64, 0x75, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, - 0x22, 0x41, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x6f, 0x62, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x08, 0x6a, 0x6f, 0x62, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x6a, 0x6f, 0x62, 0x4e, - 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x70, 0x6b, 0x67, - 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x70, 0x62, 0x3b, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6a, 0x6f, 0x62, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_cloudjobs_types_proto_rawDescOnce sync.Once - file_cloudjobs_types_proto_rawDescData = file_cloudjobs_types_proto_rawDesc -) - -func file_cloudjobs_types_proto_rawDescGZIP() []byte { - file_cloudjobs_types_proto_rawDescOnce.Do(func() { - file_cloudjobs_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_cloudjobs_types_proto_rawDescData) - }) - return file_cloudjobs_types_proto_rawDescData -} - -var file_cloudjobs_types_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_cloudjobs_types_proto_goTypes = []any{ - (*PushEventOptions)(nil), // 0: lava.cloudjobs.PushEventOptions - (*RegisterJobOptions)(nil), // 1: lava.cloudjobs.RegisterJobOptions - nil, // 2: lava.cloudjobs.PushEventOptions.MetadataEntry - (*durationpb.Duration)(nil), // 3: google.protobuf.Duration -} -var file_cloudjobs_types_proto_depIdxs = []int32{ - 2, // 0: lava.cloudjobs.PushEventOptions.metadata:type_name -> lava.cloudjobs.PushEventOptions.MetadataEntry - 3, // 1: lava.cloudjobs.PushEventOptions.delay_dur:type_name -> google.protobuf.Duration - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_cloudjobs_types_proto_init() } -func file_cloudjobs_types_proto_init() { - if File_cloudjobs_types_proto != nil { - return - } - file_cloudjobs_types_proto_msgTypes[0].OneofWrappers = []any{} - file_cloudjobs_types_proto_msgTypes[1].OneofWrappers = []any{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_cloudjobs_types_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_cloudjobs_types_proto_goTypes, - DependencyIndexes: file_cloudjobs_types_proto_depIdxs, - MessageInfos: file_cloudjobs_types_proto_msgTypes, - }.Build() - File_cloudjobs_types_proto = out.File - file_cloudjobs_types_proto_rawDesc = nil - file_cloudjobs_types_proto_goTypes = nil - file_cloudjobs_types_proto_depIdxs = nil -} diff --git a/platform/consolecolors/consolecolor_darwin.go b/platform/consolecolors/consolecolor_darwin.go index 18227bb9..05834e31 100644 --- a/platform/consolecolors/consolecolor_darwin.go +++ b/platform/consolecolors/consolecolor_darwin.go @@ -24,7 +24,7 @@ func Red(msg string) string { } // Redf ... -func Redf(msg string, arg interface{}) string { +func Redf(msg string, arg any) string { return fmt.Sprintf("\x1b[31m%s\x1b[0m %+v\n", msg, arg) } @@ -39,6 +39,6 @@ func Green(msg string) string { } // Greenf ... -func Greenf(msg string, arg interface{}) string { +func Greenf(msg string, arg any) string { return fmt.Sprintf("\x1b[32m%s\x1b[0m %+v\n", msg, arg) } diff --git a/platform/systeminfo/disk_darwin.go b/platform/systeminfo/disk_darwin.go index 9a289185..f7fdcd15 100644 --- a/platform/systeminfo/disk_darwin.go +++ b/platform/systeminfo/disk_darwin.go @@ -7,10 +7,10 @@ func DiskUsage(path string) (disk DiskStatus) { fs := syscall.Statfs_t{} err := syscall.Statfs(path, &fs) if err != nil { - return + return disk } disk.All = fs.Blocks * uint64(fs.Bsize) disk.Free = fs.Bfree * uint64(fs.Bsize) disk.Used = disk.All - disk.Free - return + return disk } diff --git a/pretty/pretty.go b/pretty/pretty.go index 18c998f9..67be7c30 100644 --- a/pretty/pretty.go +++ b/pretty/pretty.go @@ -8,31 +8,31 @@ import ( "github.com/k0kubun/pp/v3" ) -func Println(a ...interface{}) { +func Println(a ...any) { _, _ = pp.Println(a...) } -func Printf(format string, a ...interface{}) { +func Printf(format string, a ...any) { _, _ = pp.Printf(format, a...) } -func Sprint(a ...interface{}) string { +func Sprint(a ...any) string { return pp.Sprint(a...) } -func Sprintln(a ...interface{}) string { +func Sprintln(a ...any) string { return pp.Sprintln(a...) } -func Fatal(a ...interface{}) { +func Fatal(a ...any) { pp.Fatal(a...) } -func Fatalln(a ...interface{}) { +func Fatalln(a ...any) { pp.Fatalln(a...) } -func Fatalf(format string, a ...interface{}) { +func Fatalf(format string, a ...any) { pp.Fatalf(format, a...) } @@ -53,6 +53,6 @@ var Simple = sync.OnceValue(func() *pp.PrettyPrinter { return printer }) -func SimplePrint(v interface{}) string { +func SimplePrint(v any) string { return strings.ReplaceAll(Simple().Sprint(v), "\n", "") } diff --git a/proto/cloudevent/options.pb.go b/proto/cloudevent/options.pb.go index c3e5ad1a..1474c5fb 100644 --- a/proto/cloudevent/options.pb.go +++ b/proto/cloudevent/options.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: cloudevent/options.proto package cloudeventpb @@ -72,12 +72,11 @@ var file_cloudevent_options_proto_rawDesc = []byte{ 0x9b, 0x4e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6c, 0x61, 0x76, 0x61, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, + 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, - 0x6e, 0x6b, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x3b, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3b, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_cloudevent_options_proto_goTypes = []any{ diff --git a/proto/cloudevent/options.proto b/proto/cloudevent/options.proto index cb668cc2..fba8542d 100644 --- a/proto/cloudevent/options.proto +++ b/proto/cloudevent/options.proto @@ -5,7 +5,7 @@ package lava.cloudevent; import "google/protobuf/descriptor.proto"; import "cloudevent/types.proto"; -option go_package = "github.com/pubgo/funk/pkg/gen/proto/cloudeventpb;cloudeventpb"; +option go_package = "github.com/pubgo/funk/v2/proto/cloudevent;cloudeventpb"; extend google.protobuf.ServiceOptions { CloudEventServiceOptions job = 10010; diff --git a/proto/cloudevent/types.pb.go b/proto/cloudevent/types.pb.go index c9abf2eb..70ae0c07 100644 --- a/proto/cloudevent/types.pb.go +++ b/proto/cloudevent/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: cloudevent/types.proto package cloudeventpb @@ -284,11 +284,11 @@ var file_cloudevent_types_proto_rawDesc = []byte{ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x70, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x3b, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x3b, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x70, 0x62, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/cloudevent/types.proto b/proto/cloudevent/types.proto index 9068b7e2..b47a2de0 100644 --- a/proto/cloudevent/types.proto +++ b/proto/cloudevent/types.proto @@ -4,7 +4,7 @@ package lava.cloudevent; import "google/protobuf/duration.proto"; -option go_package = "github.com/pubgo/funk/pkg/gen/proto/cloudeventpb;cloudeventpb"; +option go_package = "github.com/pubgo/funk/v2/proto/cloudevent;cloudeventpb"; message RegisterJobOptions { optional string job_name = 1; diff --git a/proto/commonpb/page.pb.go b/proto/commonpb/page.pb.go index f5e03552..c7026cbc 100644 --- a/proto/commonpb/page.pb.go +++ b/proto/commonpb/page.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: commonpb/page.proto package commonpb @@ -92,10 +92,11 @@ var file_commonpb_page_proto_rawDesc = []byte{ 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x3b, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x76, + 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, + 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/proto/commonpb/page.proto b/proto/commonpb/page.proto index 6eaf0628..8dd9791a 100644 --- a/proto/commonpb/page.proto +++ b/proto/commonpb/page.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package common.v1; -option go_package = "github.com/pubgo/funk/proto/commonpb;commonpb"; +option go_package = "github.com/pubgo/funk/v2/proto/commonpb;commonpb"; message PageRequest { uint64 page_size = 1; diff --git a/proto/commonpb/request-info.pb.go b/proto/commonpb/request-info.pb.go index 5172e5fb..8c57e948 100644 --- a/proto/commonpb/request-info.pb.go +++ b/proto/commonpb/request-info.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: commonpb/request-info.proto package commonpb @@ -24,11 +24,11 @@ var File_commonpb_request_info_proto protoreflect.FileDescriptor var file_commonpb_request_info_proto_rawDesc = []byte{ 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, - 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, - 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x70, 0x62, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var file_commonpb_request_info_proto_goTypes = []any{} diff --git a/proto/commonpb/request-info.proto b/proto/commonpb/request-info.proto index 72476c83..5bbac904 100644 --- a/proto/commonpb/request-info.proto +++ b/proto/commonpb/request-info.proto @@ -1,4 +1,4 @@ syntax = "proto3"; package common.v1; -option go_package = "github.com/pubgo/funk/proto/commonpb;commonpb"; \ No newline at end of file +option go_package = "github.com/pubgo/funk/v2/proto/commonpb;commonpb"; \ No newline at end of file diff --git a/proto/commonpb/resource.pb.enum.go b/proto/commonpb/resource.pb.enum.go index f0d288e8..6b0a7504 100644 --- a/proto/commonpb/resource.pb.enum.go +++ b/proto/commonpb/resource.pb.enum.go @@ -1,7 +1,7 @@ -// Code generated by protoc-gen-go-sql. DO NOT EDIT. +// Code generated by protoc-gen-go-enum. DO NOT EDIT. // versions: // - protoc-gen-go-enum v0.0.2 -// - protoc v5.29.3 +// - protoc v6.32.1 // source: commonpb/resource.proto package commonpb diff --git a/proto/commonpb/resource.pb.go b/proto/commonpb/resource.pb.go index 8708d3f3..ff0ba03b 100644 --- a/proto/commonpb/resource.pb.go +++ b/proto/commonpb/resource.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: commonpb/resource.proto package commonpb @@ -158,11 +158,11 @@ var file_commonpb_resource_proto_rawDesc = []byte{ 0x65, 0x49, 0x64, 0x2a, 0x36, 0x0a, 0x0d, 0x56, 0x49, 0x53, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x50, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x4f, 0x4d, 0x41, 0x49, 0x4e, 0x10, 0x01, 0x12, - 0x0a, 0x0a, 0x06, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x02, 0x42, 0x2f, 0x5a, 0x2d, 0x67, + 0x0a, 0x0a, 0x06, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x02, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, - 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x70, 0x62, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/commonpb/resource.proto b/proto/commonpb/resource.proto index 974b933a..f94759d3 100644 --- a/proto/commonpb/resource.proto +++ b/proto/commonpb/resource.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package common.v1; -option go_package = "github.com/pubgo/funk/proto/commonpb;commonpb"; +option go_package = "github.com/pubgo/funk/v2/proto/commonpb;commonpb"; enum VISIABLE_MODE { // 默认Namespace可见 diff --git a/proto/commonpb/response.pb.go b/proto/commonpb/response.pb.go index 2b7c2175..b1d64987 100644 --- a/proto/commonpb/response.pb.go +++ b/proto/commonpb/response.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: commonpb/response.proto package commonpb @@ -146,11 +146,11 @@ var file_commonpb_response_proto_rawDesc = []byte{ 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, - 0x75, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x70, 0x62, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x75, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/commonpb/response.proto b/proto/commonpb/response.proto index a1f4a19a..cf6eb26a 100644 --- a/proto/commonpb/response.proto +++ b/proto/commonpb/response.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package common.v1; -option go_package = "github.com/pubgo/funk/proto/commonpb;commonpb"; +option go_package = "github.com/pubgo/funk/v2/proto/commonpb;commonpb"; import "google/protobuf/any.proto"; diff --git a/proto/errorpb/code.pb.enum.go b/proto/errorpb/code.pb.enum.go index fa039934..2de2ce66 100644 --- a/proto/errorpb/code.pb.enum.go +++ b/proto/errorpb/code.pb.enum.go @@ -1,7 +1,7 @@ -// Code generated by protoc-gen-go-sql. DO NOT EDIT. +// Code generated by protoc-gen-go-enum. DO NOT EDIT. // versions: // - protoc-gen-go-enum v0.0.2 -// - protoc v5.29.3 +// - protoc v6.32.1 // source: errorpb/code.proto package errorpb diff --git a/proto/errorpb/code.pb.go b/proto/errorpb/code.pb.go index 3113c861..b329ddd0 100644 --- a/proto/errorpb/code.pb.go +++ b/proto/errorpb/code.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: errorpb/code.proto package errorpb @@ -139,10 +139,10 @@ var file_errorpb_code_proto_rawDesc = []byte{ 0x4c, 0x6f, 0x73, 0x73, 0x10, 0x0f, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x10, 0x10, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x6f, 0x6f, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x10, 0x11, - 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x3b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x3b, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/errorpb/code.proto b/proto/errorpb/code.proto index 1b5f1f6d..113ae232 100644 --- a/proto/errorpb/code.proto +++ b/proto/errorpb/code.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package errors; -option go_package = "github.com/pubgo/funk/proto/errorpb;errorpb"; +option go_package = "github.com/pubgo/funk/v2/proto/errorpb;errorpb"; enum Code { OK = 0; @@ -23,4 +23,4 @@ enum Code { DataLoss = 15; Unauthenticated = 16; TooManyRequests = 17; -} \ No newline at end of file +} diff --git a/proto/errorpb/errors.pb.go b/proto/errorpb/errors.pb.go index ac6b5529..4c5e3dba 100644 --- a/proto/errorpb/errors.pb.go +++ b/proto/errorpb/errors.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: errorpb/errors.proto package errorpb @@ -167,7 +167,8 @@ type ErrCode struct { Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` // Error detail include request or other user defined information Details []*anypb.Any `protobuf:"bytes,5,rep,name=details,proto3" json:"details,omitempty"` - Id *string `protobuf:"bytes,6,opt,name=id,proto3,oneof" json:"id,omitempty"` + // Error id, which can be used to trace error + Id *string `protobuf:"bytes,6,opt,name=id,proto3,oneof" json:"id,omitempty"` } func (x *ErrCode) Reset() { @@ -242,136 +243,6 @@ func (x *ErrCode) GetId() string { return "" } -type ErrTrace struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` - Operation string `protobuf:"bytes,3,opt,name=operation,proto3" json:"operation,omitempty"` - Service string `protobuf:"bytes,4,opt,name=service,proto3" json:"service,omitempty"` - Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *ErrTrace) Reset() { - *x = ErrTrace{} - mi := &file_errorpb_errors_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ErrTrace) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ErrTrace) ProtoMessage() {} - -func (x *ErrTrace) ProtoReflect() protoreflect.Message { - mi := &file_errorpb_errors_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ErrTrace.ProtoReflect.Descriptor instead. -func (*ErrTrace) Descriptor() ([]byte, []int) { - return file_errorpb_errors_proto_rawDescGZIP(), []int{3} -} - -func (x *ErrTrace) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *ErrTrace) GetOperation() string { - if x != nil { - return x.Operation - } - return "" -} - -func (x *ErrTrace) GetService() string { - if x != nil { - return x.Service - } - return "" -} - -func (x *ErrTrace) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type Error struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Code *ErrCode `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` - Trace *ErrTrace `protobuf:"bytes,2,opt,name=trace,proto3" json:"trace,omitempty"` - Msg *ErrMsg `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` -} - -func (x *Error) Reset() { - *x = Error{} - mi := &file_errorpb_errors_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Error) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Error) ProtoMessage() {} - -func (x *Error) ProtoReflect() protoreflect.Message { - mi := &file_errorpb_errors_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Error.ProtoReflect.Descriptor instead. -func (*Error) Descriptor() ([]byte, []int) { - return file_errorpb_errors_proto_rawDescGZIP(), []int{4} -} - -func (x *Error) GetCode() *ErrCode { - if x != nil { - return x.Code - } - return nil -} - -func (x *Error) GetTrace() *ErrTrace { - if x != nil { - return x.Trace - } - return nil -} - -func (x *Error) GetMsg() *ErrMsg { - if x != nil { - return x.Msg - } - return nil -} - type ErrWrap struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -381,11 +252,13 @@ type ErrWrap struct { Caller string `protobuf:"bytes,2,opt,name=caller,proto3" json:"caller,omitempty"` Stacks []string `protobuf:"bytes,3,rep,name=stacks,proto3" json:"stacks,omitempty"` Error *anypb.Any `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` + // Error id, which can be used to trace error + Id *string `protobuf:"bytes,5,opt,name=id,proto3,oneof" json:"id,omitempty"` } func (x *ErrWrap) Reset() { *x = ErrWrap{} - mi := &file_errorpb_errors_proto_msgTypes[5] + mi := &file_errorpb_errors_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -397,7 +270,7 @@ func (x *ErrWrap) String() string { func (*ErrWrap) ProtoMessage() {} func (x *ErrWrap) ProtoReflect() protoreflect.Message { - mi := &file_errorpb_errors_proto_msgTypes[5] + mi := &file_errorpb_errors_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -410,7 +283,7 @@ func (x *ErrWrap) ProtoReflect() protoreflect.Message { // Deprecated: Use ErrWrap.ProtoReflect.Descriptor instead. func (*ErrWrap) Descriptor() ([]byte, []int) { - return file_errorpb_errors_proto_rawDescGZIP(), []int{5} + return file_errorpb_errors_proto_rawDescGZIP(), []int{3} } func (x *ErrWrap) GetTags() map[string]string { @@ -441,6 +314,13 @@ func (x *ErrWrap) GetError() *anypb.Any { return nil } +func (x *ErrWrap) GetId() string { + if x != nil && x.Id != nil { + return *x.Id + } + return "" +} + var File_errorpb_errors_proto protoreflect.FileDescriptor var file_errorpb_errors_proto_rawDesc = []byte{ @@ -477,37 +357,25 @@ var file_errorpb_errors_proto_rawDesc = []byte{ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, - 0x5f, 0x69, 0x64, 0x22, 0x6c, 0x0a, 0x08, 0x45, 0x72, 0x72, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, - 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x22, 0x76, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x04, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x73, 0x2e, 0x45, 0x72, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, - 0x26, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x45, 0x72, 0x72, 0x54, 0x72, 0x61, 0x63, 0x65, - 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x45, 0x72, - 0x72, 0x4d, 0x73, 0x67, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0xcd, 0x01, 0x0a, 0x07, 0x45, 0x72, - 0x72, 0x57, 0x72, 0x61, 0x70, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x45, 0x72, 0x72, - 0x57, 0x72, 0x61, 0x70, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, - 0x74, 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x63, 0x6b, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, - 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, - 0x3b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x5f, 0x69, 0x64, 0x22, 0xe9, 0x01, 0x0a, 0x07, 0x45, 0x72, 0x72, 0x57, 0x72, 0x61, 0x70, 0x12, + 0x2d, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x45, 0x72, 0x72, 0x57, 0x72, 0x61, 0x70, 0x2e, 0x54, + 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x73, 0x12, 0x2a, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x41, 0x6e, 0x79, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x1a, + 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x64, 0x42, + 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, + 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x3b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -522,33 +390,28 @@ func file_errorpb_errors_proto_rawDescGZIP() []byte { return file_errorpb_errors_proto_rawDescData } -var file_errorpb_errors_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_errorpb_errors_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_errorpb_errors_proto_goTypes = []any{ (*Tag)(nil), // 0: errors.Tag (*ErrMsg)(nil), // 1: errors.ErrMsg (*ErrCode)(nil), // 2: errors.ErrCode - (*ErrTrace)(nil), // 3: errors.ErrTrace - (*Error)(nil), // 4: errors.Error - (*ErrWrap)(nil), // 5: errors.ErrWrap - nil, // 6: errors.ErrMsg.TagsEntry - nil, // 7: errors.ErrWrap.TagsEntry - (Code)(0), // 8: errors.Code - (*anypb.Any)(nil), // 9: google.protobuf.Any + (*ErrWrap)(nil), // 3: errors.ErrWrap + nil, // 4: errors.ErrMsg.TagsEntry + nil, // 5: errors.ErrWrap.TagsEntry + (Code)(0), // 6: errors.Code + (*anypb.Any)(nil), // 7: google.protobuf.Any } var file_errorpb_errors_proto_depIdxs = []int32{ - 6, // 0: errors.ErrMsg.tags:type_name -> errors.ErrMsg.TagsEntry - 8, // 1: errors.ErrCode.status_code:type_name -> errors.Code - 9, // 2: errors.ErrCode.details:type_name -> google.protobuf.Any - 2, // 3: errors.Error.code:type_name -> errors.ErrCode - 3, // 4: errors.Error.trace:type_name -> errors.ErrTrace - 1, // 5: errors.Error.msg:type_name -> errors.ErrMsg - 7, // 6: errors.ErrWrap.tags:type_name -> errors.ErrWrap.TagsEntry - 9, // 7: errors.ErrWrap.error:type_name -> google.protobuf.Any - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 4, // 0: errors.ErrMsg.tags:type_name -> errors.ErrMsg.TagsEntry + 6, // 1: errors.ErrCode.status_code:type_name -> errors.Code + 7, // 2: errors.ErrCode.details:type_name -> google.protobuf.Any + 5, // 3: errors.ErrWrap.tags:type_name -> errors.ErrWrap.TagsEntry + 7, // 4: errors.ErrWrap.error:type_name -> google.protobuf.Any + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_errorpb_errors_proto_init() } @@ -559,13 +422,14 @@ func file_errorpb_errors_proto_init() { file_errorpb_code_proto_init() file_errorpb_errors_proto_msgTypes[1].OneofWrappers = []any{} file_errorpb_errors_proto_msgTypes[2].OneofWrappers = []any{} + file_errorpb_errors_proto_msgTypes[3].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_errorpb_errors_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/errorpb/errors.proto b/proto/errorpb/errors.proto index 0ae55a63..39a4f91c 100644 --- a/proto/errorpb/errors.proto +++ b/proto/errorpb/errors.proto @@ -5,7 +5,7 @@ package errors; import "errorpb/code.proto"; import "google/protobuf/any.proto"; -option go_package = "github.com/pubgo/funk/proto/errorpb;errorpb"; +option go_package = "github.com/pubgo/funk/v2/proto/errorpb;errorpb"; message Tag { string key = 1; @@ -36,25 +36,23 @@ message ErrCode { // Error detail include request or other user defined information repeated google.protobuf.Any details = 5; + + // Error id, which can be used to trace error optional string id = 6; } -message ErrTrace { - string id = 2; - string operation = 3; - string service = 4; - string version = 5; -} - -message Error { - ErrCode code = 1; - ErrTrace trace = 2; - ErrMsg msg = 3; -} +//message ErrTrace { +// string id = 2; +// string operation = 3; +// string service = 4; +// string version = 5; +//} message ErrWrap { map tags = 1; string caller = 2; repeated string stacks = 3; google.protobuf.Any error = 4; + // Error id, which can be used to trace error + optional string id = 5; } diff --git a/proto/errorpb/options.pb.go b/proto/errorpb/options.pb.go index 2908d6f9..53f2fd6a 100644 --- a/proto/errorpb/options.pb.go +++ b/proto/errorpb/options.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: errorpb/options.proto package errorpb @@ -26,9 +26,13 @@ type Options struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Gen bool `protobuf:"varint,1,opt,name=gen,proto3" json:"gen,omitempty"` - DefaultCode Code `protobuf:"varint,2,opt,name=default_code,json=defaultCode,proto3,enum=errors.Code" json:"default_code,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + // gen 是否生成 error code + Gen bool `protobuf:"varint,1,opt,name=gen,proto3" json:"gen,omitempty"` + // default_code 默认的 error code, 可能是 Internal + DefaultCode Code `protobuf:"varint,2,opt,name=default_code,json=defaultCode,proto3,enum=errors.Code" json:"default_code,omitempty"` + // name 是生成的 error code 的变量名前缀 + // 如果 name = Test, 那么 生成的 error code 变量名可能为 `TestErrCodeNotFound` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` } func (x *Options) Reset() { @@ -179,9 +183,9 @@ var File_errorpb_options_proto protoreflect.FileDescriptor var file_errorpb_options_proto_rawDesc = []byte{ 0x0a, 0x15, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, - 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x12, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, + 0x12, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x60, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x67, 0x65, 0x6e, 0x12, 0x2f, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, @@ -202,10 +206,11 @@ var file_errorpb_options_proto_rawDesc = []byte{ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xa1, 0x8d, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, + 0x6f, 0x6e, 0x73, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, 0x67, 0x6f, 0x2f, 0x66, 0x75, - 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, - 0x3b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x70, 0x62, 0x3b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/proto/errorpb/options.proto b/proto/errorpb/options.proto index 6d89d6ca..d8d84f43 100644 --- a/proto/errorpb/options.proto +++ b/proto/errorpb/options.proto @@ -2,13 +2,20 @@ syntax = "proto3"; package errors; -option go_package = "github.com/pubgo/funk/proto/errorpb;errorpb"; -import "google/protobuf/descriptor.proto"; import "errorpb/code.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "github.com/pubgo/funk/v2/proto/errorpb;errorpb"; message Options { + // gen 是否生成 error code bool gen = 1; + + // default_code 默认的 error code, 可能是 Internal Code default_code = 2; + + // name 是生成的 error code 的变量名前缀 + // 如果 name = Test, 那么 生成的 error code 变量名可能为 `TestErrCodeNotFound` string name = 3; } diff --git a/proto/testcodepb/protobuf.plugin.yaml b/proto/testcodepb/protobuf.plugin.yaml index cdcb68be..a9de8496 100644 --- a/proto/testcodepb/protobuf.plugin.yaml +++ b/proto/testcodepb/protobuf.plugin.yaml @@ -1,4 +1,4 @@ plugins: - name: go - name: go-enum - - name: go-errors + - name: go-errors2 diff --git a/proto/testcodepb/test.errors.pb.go b/proto/testcodepb/test.errors.pb.go index c0464007..025df673 100644 --- a/proto/testcodepb/test.errors.pb.go +++ b/proto/testcodepb/test.errors.pb.go @@ -1,14 +1,14 @@ // Code generated by protoc-gen-go-errors. DO NOT EDIT. // versions: // - protoc-gen-go-errors v0.0.7 -// - protoc v5.29.3 +// - protoc v6.32.1 // source: testcodepb/test.proto package testcodepb import ( - errors "github.com/pubgo/funk/errors" - errorpb "github.com/pubgo/funk/proto/errorpb" + errorcodes "github.com/pubgo/funk/v2/errors/errorcodes" + errorpb "github.com/pubgo/funk/v2/proto/errorpb" grpc "google.golang.org/grpc" ) @@ -23,7 +23,7 @@ var TestErrCodeOK = &errorpb.ErrCode{ Name: "demo.test.v1.ok", StatusCode: errorpb.Code_OK, } -var _ = errors.RegisterErrCodes(TestErrCodeOK) +var _ = errorcodes.RegisterErrCodes(TestErrCodeOK) var TestErrCodeNotFound = &errorpb.ErrCode{ Code: int32(100000), @@ -31,7 +31,7 @@ var TestErrCodeNotFound = &errorpb.ErrCode{ Name: "demo.test.v1.not_found", StatusCode: errorpb.Code_NotFound, } -var _ = errors.RegisterErrCodes(TestErrCodeNotFound) +var _ = errorcodes.RegisterErrCodes(TestErrCodeNotFound) var TestErrCodeUnknown = &errorpb.ErrCode{ Code: int32(100001), @@ -39,7 +39,7 @@ var TestErrCodeUnknown = &errorpb.ErrCode{ Name: "demo.test.v1.unknown", StatusCode: errorpb.Code_NotFound, } -var _ = errors.RegisterErrCodes(TestErrCodeUnknown) +var _ = errorcodes.RegisterErrCodes(TestErrCodeUnknown) var TestErrCodeDbConn = &errorpb.ErrCode{ Code: int32(100003), @@ -47,7 +47,7 @@ var TestErrCodeDbConn = &errorpb.ErrCode{ Name: "demo.test.v1.db_conn", StatusCode: errorpb.Code_Internal, } -var _ = errors.RegisterErrCodes(TestErrCodeDbConn) +var _ = errorcodes.RegisterErrCodes(TestErrCodeDbConn) var TestErrCodeUnknownCode = &errorpb.ErrCode{ Code: int32(100004), @@ -55,7 +55,7 @@ var TestErrCodeUnknownCode = &errorpb.ErrCode{ Name: "demo.test.v1.unknown_code", StatusCode: errorpb.Code_Internal, } -var _ = errors.RegisterErrCodes(TestErrCodeUnknownCode) +var _ = errorcodes.RegisterErrCodes(TestErrCodeUnknownCode) var TestErrCodeCustomCode = &errorpb.ErrCode{ Code: int32(100005), @@ -63,4 +63,4 @@ var TestErrCodeCustomCode = &errorpb.ErrCode{ Name: "demo.custom.code", StatusCode: errorpb.Code_OK, } -var _ = errors.RegisterErrCodes(TestErrCodeCustomCode) +var _ = errorcodes.RegisterErrCodes(TestErrCodeCustomCode) diff --git a/proto/testcodepb/test.pb.enum.go b/proto/testcodepb/test.pb.enum.go index c3072f68..f0577385 100644 --- a/proto/testcodepb/test.pb.enum.go +++ b/proto/testcodepb/test.pb.enum.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-sql. DO NOT EDIT. // versions: // - protoc-gen-go-enum v0.0.2 -// - protoc v5.29.3 +// - protoc v6.32.1 // source: testcodepb/test.proto package testcodepb diff --git a/proto/testcodepb/test.pb.go b/proto/testcodepb/test.pb.go index 6d09da69..8a16bf44 100644 --- a/proto/testcodepb/test.pb.go +++ b/proto/testcodepb/test.pb.go @@ -1,13 +1,13 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.29.3 +// protoc v6.32.1 // source: testcodepb/test.proto package testcodepb import ( - _ "github.com/pubgo/funk/proto/errorpb" + _ "github.com/pubgo/funk/v2/proto/errorpb" _ "google.golang.org/genproto/googleapis/api/annotations" httpbody "google.golang.org/genproto/googleapis/api/httpbody" protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -846,11 +846,11 @@ var file_testcodepb_test_proto_rawDesc = []byte{ 0x31, 0x2e, 0x44, 0x6f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x1a, 0x11, 0xca, 0x41, 0x0e, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x30, 0x42, 0x33, - 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, - 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, - 0x73, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x70, 0x62, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x63, 0x6f, 0x64, - 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x30, 0x42, 0x36, + 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x62, + 0x67, 0x6f, 0x2f, 0x66, 0x75, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x74, 0x65, 0x73, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x70, 0x62, 0x3b, 0x74, 0x65, 0x73, 0x74, + 0x63, 0x6f, 0x64, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/testcodepb/test.proto b/proto/testcodepb/test.proto index 5d8ae26b..ef891289 100644 --- a/proto/testcodepb/test.proto +++ b/proto/testcodepb/test.proto @@ -9,7 +9,7 @@ import "google/api/client.proto"; import "google/api/httpbody.proto"; import "google/protobuf/empty.proto"; -option go_package = "github.com/pubgo/funk/proto/testcodepb;testcodepb"; +option go_package = "github.com/pubgo/funk/v2/proto/testcodepb;testcodepb"; enum Code { option (errors.opts).gen = true; diff --git a/protobuf.yaml b/protobuf.yaml index f1921f25..0945bee8 100644 --- a/protobuf.yaml +++ b/protobuf.yaml @@ -1,4 +1,4 @@ -checksum: 0cff806a9bcb71452eac9fa294e6aa308e31cdfe +checksum: 3cdc54c7ecf84134e660deb7ed3272063883eca9 vendor: proto-vendor base: out: proto @@ -13,11 +13,12 @@ deps: path: /google version: v0.0.0-20220224004616-3c171936039b - name: google/protobuf - url: /usr/local/include/google/protobuf + url: /opt/homebrew/include/google/protobuf + optional: true plugins: - name: go - - name: go-errors - - name: go-enum + - name: go-errors2 + - name: go-enum2 linter: rules: included_paths: [] diff --git a/protoutils/ext.go b/protoutils/ext.go index a74f9936..89771546 100644 --- a/protoutils/ext.go +++ b/protoutils/ext.go @@ -1,10 +1,11 @@ package protoutils import ( - "github.com/pubgo/funk/log" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" + + "github.com/pubgo/funk/v2/log" ) func HasExtension(option protoreflect.ProtoMessage, xt protoreflect.ExtensionType) bool { diff --git a/protoutils/util.go b/protoutils/util.go index cc888daa..3747c01e 100644 --- a/protoutils/util.go +++ b/protoutils/util.go @@ -9,11 +9,12 @@ import ( "strings" "unicode" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" options "google.golang.org/genproto/googleapis/api/annotations" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/descriptorpb" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" ) func Append(s *string, args ...string) { @@ -205,7 +206,7 @@ func ExtractAPIOptions(mth *descriptorpb.MethodDescriptorProto) (*options.HttpRu ext := proto.GetExtension(mth.GetOptions(), options.E_Http) opts, ok := ext.(*options.HttpRule) if !ok { - return nil, errors.Format("extension is %T; want an HttpRule", ext) + return nil, errors.Errorf("extension is %T; want an HttpRule", ext) } return opts, nil diff --git a/recovery/recovery.go b/recovery/recovery.go index a2b982e2..57af8606 100644 --- a/recovery/recovery.go +++ b/recovery/recovery.go @@ -5,8 +5,9 @@ import ( "runtime/debug" "testing" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors/errinter" + "github.com/samber/lo" + + "github.com/pubgo/funk/v2/internal/errors/errinter" ) func Err(gErr *error, callbacks ...func(err error) error) { @@ -44,7 +45,7 @@ func Raise(callbacks ...func(err error) error) { } func Recovery(fn func(err error)) { - assert.If(fn == nil, "[fn] should not be nil") + lo.Assert(fn != nil, "[fn] should not be nil") err := errinter.ParseError(recover()) if err == nil { diff --git a/recovery/recovery_test.go b/recovery/recovery_test.go index cc3d080a..a0c0e5ec 100644 --- a/recovery/recovery_test.go +++ b/recovery/recovery_test.go @@ -4,10 +4,10 @@ import ( "fmt" "testing" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/recovery" - "github.com/pubgo/funk/result" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/recovery" + "github.com/pubgo/funk/v2/result" ) func testExit1() { @@ -40,9 +40,9 @@ func TestResult(t *testing.T) { } handler := func() (r result.Result[A]) { - defer recovery.Err(&r.E) + defer result.Recovery(&r) - r = r.WithVal(A{A: "hello"}) + r = r.WithValue(A{A: "hello"}) panic("ok") } diff --git a/reflectx/util.go b/reflectx/util.go index 91ab89d9..b10b0628 100644 --- a/reflectx/util.go +++ b/reflectx/util.go @@ -17,7 +17,7 @@ func Indirect(v reflect.Value) reflect.Value { } } -func New(val interface{}) reflect.Value { +func New(val any) reflect.Value { if val == nil { panic("[val] is nil") } diff --git a/v2/result/api.go b/result/api.go similarity index 63% rename from v2/result/api.go rename to result/api.go index 6995c508..9a726eba 100644 --- a/v2/result/api.go +++ b/result/api.go @@ -4,9 +4,20 @@ import ( "context" "fmt" - "github.com/pubgo/funk/errors" + "github.com/rs/zerolog" + + "github.com/pubgo/funk/v2/errors" ) +func Run(executors ...func() error) Error { + for _, executor := range executors { + if err := executor(); err != nil { + return ErrOf(errors.WrapCaller(err, 1)) + } + } + return Error{} +} + func All[T any](results ...Result[T]) Result[[]T] { values := make([]T, 0, len(results)) for _, result := range results { @@ -18,7 +29,7 @@ func All[T any](results ...Result[T]) Result[[]T] { return OK(values) } -func Recovery(setter *error, callbacks ...func(err error) error) { +func RecoveryErr(setter *error, callbacks ...func(err error) error) { if setter == nil { errNilOrPanic(errors.Errorf("setter is nil")) return @@ -30,7 +41,7 @@ func Recovery(setter *error, callbacks ...func(err error) error) { )) } -func RecoveryErr(setter ErrSetter, callbacks ...func(err error) error) { +func Recovery(setter ErrSetter, callbacks ...func(err error) error) { if setter == nil { errNilOrPanic(errors.Errorf("setter is nil")) return @@ -46,17 +57,12 @@ func Errorf(msg string, args ...any) Error { return newError(errors.WrapCaller(fmt.Errorf(msg, args...), 1)) } -// Deprecated: use Errorf -func ErrorOf(msg string, args ...any) Error { - return newError(errors.WrapCaller(fmt.Errorf(msg, args...), 1)) -} - -func ErrProxyOf(err *error) ErrProxy { +func ErrProxyOf(err *error) ProxyErr { if err == nil { errNilOrPanic(errors.Errorf("err param is nil")) - return ErrProxy{} + return ProxyErr{} } - return ErrProxy{err: err} + return ProxyErr{err: err} } func ErrOf(err error) Error { @@ -69,7 +75,7 @@ func ErrOf(err error) Error { } func ErrOfFn(fn func() error) Error { - var err = try(fn) + err := try(fn) if err == nil { return Error{} } @@ -110,18 +116,17 @@ func WrapFn[T any](fn func() (T, error)) Result[T] { return Result[T]{err: err} } -func CatchErr(setter ErrSetter, err error, contexts ...context.Context) bool { +func Catch(setter ErrSetter, err error, contexts ...context.Context) bool { return catchErr(newError(err), setter, nil, contexts...) } -func Catch(rawSetter *error, err error, contexts ...context.Context) bool { +func CatchErr(rawSetter *error, err error, contexts ...context.Context) bool { return catchErr(newError(err), nil, rawSetter, contexts...) } func MapTo[T, U any](r Result[T], fn func(T) U) Result[U] { if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - return Fail[U](err) + return Fail[U](errors.WrapCaller(r.getErr(), 1)) } return OK(fn(r.getValue())) @@ -129,9 +134,32 @@ func MapTo[T, U any](r Result[T], fn func(T) U) Result[U] { func FlatMapTo[T, U any](r Result[T], fn func(T) Result[U]) Result[U] { if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - return Fail[U](err) + return Fail[U](errors.WrapCaller(r.getErr(), 1)) } return fn(r.getValue()) } + +func LogErr(err error, events ...func(e *zerolog.Event)) { + logErr(nil, 0, err, events...) +} + +func LogErrCtx(ctx context.Context, err error, events ...func(e *zerolog.Event)) { + logErr(ctx, 0, err, events...) +} + +func Must(err error, events ...func(e *zerolog.Event)) { + if err == nil { + return + } + + errNilOrPanic(errors.WrapCaller(err, 1), events...) +} + +func Must1[T any](ret T, err error) T { + if err != nil { + errNilOrPanic(errors.WrapCaller(err, 1)) + } + + return ret +} diff --git a/v2/result/error.go b/result/error.go similarity index 74% rename from v2/result/error.go rename to result/error.go index 6e8cf335..b82e59cf 100644 --- a/v2/result/error.go +++ b/result/error.go @@ -6,13 +6,16 @@ import ( "github.com/rs/zerolog" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/errors/errutil" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/errors/errutil" + "github.com/pubgo/funk/v2/log/logfields" ) -var _ Catchable = new(Error) -var _ Checkable = new(Error) -var _ ErrSetter = new(Error) +var ( + _ Catchable = new(Error) + _ Checkable = new(Error) + _ ErrSetter = new(Error) +) func newError(err error) Error { return Error{err: err} @@ -35,12 +38,12 @@ func (e Error) Map(fn func(error) error) Error { } func (e Error) LogCtx(ctx context.Context, events ...func(e *zerolog.Event)) Error { - logErr(ctx, e.err, events...) + logErr(ctx, 0, e.err, events...) return e } func (e Error) Log(events ...func(e *zerolog.Event)) Error { - logErr(nil, e.err, events...) + logErr(nil, 0, e.err, events...) return e } @@ -55,6 +58,7 @@ func (e Error) WithFn(fn func() error) Error { func (e Error) WithErr(err error) Error { return Error{err: errors.WrapCaller(err, 1)} } + func (e Error) WithErrorf(format string, args ...any) Error { return Error{err: errors.WrapCaller(fmt.Errorf(format, args...), 1)} } @@ -70,16 +74,11 @@ func (e Error) Inspect(fn func(error)) Error { func (e Error) InspectErr(fn func(error)) Error { return e.Inspect(fn) } -func (e Error) Unwrap() error { return e.err } -func (e Error) UnwrapErr(setter ErrSetter, contexts ...context.Context) bool { - return catchErr(e, setter, nil, contexts...) -} - -func (e Error) Catch(setter *error, ctx ...context.Context) bool { +func (e Error) CatchErr(setter *error, ctx ...context.Context) bool { return catchErr(e, nil, setter, ctx...) } -func (e Error) CatchErr(setter ErrSetter, ctx ...context.Context) bool { +func (e Error) Catch(setter ErrSetter, ctx ...context.Context) bool { return catchErr(e, setter, nil, ctx...) } @@ -95,12 +94,12 @@ func (e Error) GetErr() error { return e.getErr() } -func (e Error) Must() { +func (e Error) Must(events ...func(e *zerolog.Event)) { if e.IsOK() { return } - errNilOrPanic(errors.WrapCaller(e.getErr(), 1)) + errNilOrPanic(errors.WrapCaller(e.getErr(), 1), events...) } func (e Error) Expect(format string, args ...any) { @@ -109,13 +108,14 @@ func (e Error) Expect(format string, args ...any) { } err := errors.WrapCaller(e.getErr(), 1) - err = errors.Wrapf(err, format, args...) - errNilOrPanic(err) + errNilOrPanic(err, func(e *zerolog.Event) { + e.Str(logfields.Msg, fmt.Sprintf(format, args...)) + }) } func (e Error) String() string { if e.IsOK() { - return "Ok" + return "OK" } return fmt.Sprintf("Error(%v)", e.err) diff --git a/v2/result/error_test.go b/result/error_test.go similarity index 71% rename from v2/result/error_test.go rename to result/error_test.go index ebbc69ff..c7f99c0a 100644 --- a/v2/result/error_test.go +++ b/result/error_test.go @@ -3,9 +3,10 @@ package result import ( "testing" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log/logfields" "github.com/rs/zerolog" + + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log/logfields" ) func TestErrorLog(t *testing.T) { diff --git a/result/future.go b/result/future.go new file mode 100644 index 00000000..71bb2e1c --- /dev/null +++ b/result/future.go @@ -0,0 +1,79 @@ +package result + +import ( + "context" + + "github.com/samber/lo" + + "github.com/pubgo/funk/v2/errors" +) + +func AsyncErr(fn func() Error) *FutureErr { + if fn == nil { + return &FutureErr{e: errors.WrapCaller(errFnIsNil, 1)} + } + + future := newErrFuture() + go func() { + defer future.close() + future.setErr(try(func() error { return fn().getErr() })) + }() + return future +} + +func Async[T any](fn func() Result[T]) *Future[T] { + if fn == nil { + return &Future[T]{v: Fail[T](errors.WrapCaller(errFnIsNil, 1))} + } + + future := newFuture[T]() + go func() { + defer future.close() + future.setVal(tryResult(fn)) + }() + return future +} + +func newFuture[T any]() *Future[T] { + return &Future[T]{done: make(chan struct{})} +} + +type Future[T any] struct { + v Result[T] + done chan struct{} +} + +func (f *Future[T]) close() { close(f.done) } +func (f *Future[T]) setVal(val Result[T]) { f.v = val } + +func (f *Future[T]) Await(ctxL ...context.Context) Result[T] { + ctx := lo.FirstOr(ctxL, context.Background()) + select { + case <-f.done: + return f.v + case <-ctx.Done(): + return f.v.WithErr(ctx.Err()) + } +} + +func newErrFuture() *FutureErr { + return &FutureErr{done: make(chan struct{})} +} + +type FutureErr struct { + e error + done chan struct{} +} + +func (f *FutureErr) close() { close(f.done) } +func (f *FutureErr) setErr(err error) { f.e = err } + +func (f *FutureErr) Await(ctxL ...context.Context) Error { + ctx := lo.FirstOr(ctxL, context.Background()) + select { + case <-f.done: + return ErrOf(f.e) + case <-ctx.Done(): + return ErrOf(ctx.Err()) + } +} diff --git a/result/future_test.go b/result/future_test.go new file mode 100644 index 00000000..3bfd01cd --- /dev/null +++ b/result/future_test.go @@ -0,0 +1,66 @@ +package result_test + +import ( + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/pubgo/funk/v2/result" +) + +func TestFuture_ConcurrentAwait(t *testing.T) { + future := result.Async(func() result.Result[int] { + time.Sleep(10 * time.Millisecond) + return result.OK(42) + }) + + var wg sync.WaitGroup + results := make([]result.Result[int], 10) + + // Start multiple goroutines waiting for the same future + for i := 0; i < 10; i++ { + wg.Add(1) + idx := i + go func() { + defer wg.Done() + results[idx] = future.Await() + }() + } + + wg.Wait() + + // All results should be the same + for _, r := range results { + assert.True(t, r.IsOK()) + assert.Equal(t, 42, r.GetValue()) + } +} + +func TestErrFuture_ConcurrentAwait(t *testing.T) { + future := result.AsyncErr(func() (r result.Error) { + time.Sleep(10 * time.Millisecond) + return r.WithErr(nil) + }) + + var wg sync.WaitGroup + results := make([]result.Error, 10) + + // Start multiple goroutines waiting for the same future + for i := 0; i < 10; i++ { + wg.Add(1) + idx := i + go func() { + defer wg.Done() + results[idx] = future.Await() + }() + } + + wg.Wait() + + // All results should be the same + for _, r := range results { + assert.True(t, r.IsOK()) + } +} diff --git a/result/interface.go b/result/interface.go new file mode 100644 index 00000000..da96e396 --- /dev/null +++ b/result/interface.go @@ -0,0 +1,32 @@ +package result + +import ( + "context" + + "github.com/pubgo/funk/v2" +) + +// Checkable defines types that can be checked for Ok/Error state +type Checkable interface { + IsOK() bool + IsErr() bool + GetErr() error + String() string +} + +type ErrSetter interface { + Checkable + setErrorInner() +} + +type Catchable interface { + CatchErr(err *error, contexts ...context.Context) bool + Catch(err ErrSetter, contexts ...context.Context) bool +} + +type UnWrapper[T any] interface { + UnwrapErr(setter *error, contexts ...context.Context) T + Unwrap(setter ErrSetter, contexts ...context.Context) T +} + +type Void = funk.Void diff --git a/v2/result/proxy.go b/result/proxy.go similarity index 51% rename from v2/result/proxy.go rename to result/proxy.go index 970f6a2e..3c1bb9e6 100644 --- a/v2/result/proxy.go +++ b/result/proxy.go @@ -6,31 +6,31 @@ import ( "github.com/samber/lo" ) -var _ ErrSetter = new(ErrProxy) +var _ ErrSetter = new(ProxyErr) -type ErrProxy struct { +type ProxyErr struct { err *error } -func (e ErrProxy) IsOK() bool { +func (e ProxyErr) IsOK() bool { return lo.FromPtr(e.err) == nil } -func (e ErrProxy) IsErr() bool { +func (e ProxyErr) IsErr() bool { return lo.FromPtr(e.err) != nil } -func (e ErrProxy) GetErr() error { +func (e ProxyErr) GetErr() error { return lo.FromPtr(e.err) } -func (e ErrProxy) String() string { +func (e ProxyErr) String() string { if e.IsOK() { - return "Ok" + return "OK" } return fmt.Sprintf("Error(%v)", lo.FromPtr(e.err)) } -func (e ErrProxy) setErrorInner() { +func (e ProxyErr) setErrorInner() { } diff --git a/v2/result/proxy_test.go b/result/proxy_test.go similarity index 73% rename from v2/result/proxy_test.go rename to result/proxy_test.go index f5da4843..bf1a19e2 100644 --- a/v2/result/proxy_test.go +++ b/result/proxy_test.go @@ -8,8 +8,8 @@ import ( func TestProxy(t *testing.T) { var gErr error - var err = ErrProxyOf(&gErr) - Errorf("test proxy error").Log().CatchErr(&err) + err := ErrProxyOf(&gErr) + Errorf("test proxy error").Log().Catch(&err) assert.NotNil(t, gErr) assert.NotNil(t, err.GetErr()) assert.Equal(t, gErr, err.GetErr()) diff --git a/result/result.go b/result/result.go index ce92083c..c6c52fc7 100644 --- a/result/result.go +++ b/result/result.go @@ -1,315 +1,233 @@ package result import ( + "context" "encoding/json" "fmt" - "runtime/debug" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/stack" - "github.com/rs/zerolog/log" + "github.com/rs/zerolog" "github.com/samber/lo" -) - -var _ error = (*Error)(nil) - -type Error struct { - Msg string - Stack string -} - -func (e Error) String() string { - return fmt.Sprintf("%s:\n%s", e.Msg, e.Stack) -} - -func (e Error) Error() string { - return e.String() -} - -type R[T any] interface { - Unwrap() T - IsErr() bool - Err() error - Expect(format string, args ...any) T -} - -func OK[T any](v T) Result[T] { - return Result[T]{v: &v} -} - -func Err[T any](err error) Result[T] { - return Result[T]{E: errors.WrapCaller(err, 1)} -} -func Wrap[T any](v T, err error) Result[T] { - return Result[T]{v: &v, E: errors.WrapCaller(err, 1)} -} + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log/logfields" +) -func Of[T any](v T, err error) Result[T] { - return Result[T]{v: &v, E: errors.WrapCaller(err, 1)} -} +var ( + _ Catchable = new(Result[any]) + _ Checkable = new(Result[any]) + _ ErrSetter = new(Result[any]) +) type Result[T any] struct { - v *T - E error -} + _ [0]func() // disallow == -func (r Result[T]) WithErrorf(format string, args ...any) Result[T] { - return Result[T]{E: errors.WrapCaller(errors.Errorf(format, args...), 1)} -} - -func (r Result[T]) WithErr(err error) Result[T] { - return Result[T]{E: errors.WrapCaller(err, 1)} -} - -func (r Result[T]) WithVal(v T) Result[T] { - return OK(v) + v *T + err error } -func (r Result[T]) ValueTo(v *T) error { +func (r Result[T]) GetValue() (t T) { if r.IsErr() { - return errors.WrapCaller(r.E, 1) + return t } - *v = generic.FromPtr(r.v) - return nil + return r.getValue() } -func (r Result[T]) OnValue(fn func(t T) error) error { +func (r Result[T]) WithFn(fn func() (T, error)) Result[T] { if r.IsErr() { - return r.E + err := errors.WrapCaller(r.getErr(), 1) + return Result[T]{err: err} } - return errors.WrapCaller(fn(generic.FromPtr(r.v)), 1) + return WrapFn(fn) } -func (r Result[T]) OnErr(check func(err error)) { - if r.IsOK() { - return - } - - check(r.E) -} - -func (r Result[T]) GetErr() error { - if r.IsOK() { - return nil +func (r Result[T]) WithValue(v T) Result[T] { + if r.IsErr() { + err := errors.WrapCaller(r.getErr(), 1) + return Result[T]{err: err} } - return errors.WrapCaller(r.E, 1) + return OK(v) } -func (r Result[T]) Err(check ...func(err error) error) error { - if r.IsOK() { - return nil +func (r Result[T]) ValueTo(v *T) Error { + if r.IsErr() { + return newError(errors.WrapCaller(r.getErr(), 1)) } - if len(check) > 0 && check[0] != nil { - return errors.WrapCaller(check[0](r.E), 1) + if v == nil { + return newError(errors.WrapStack(errors.New("v param is nil"))) } - return errors.WrapCaller(r.E, 1) + *v = r.getValue() + return newError(nil) } -func (r Result[T]) IsErr() bool { return r.E != nil } - -func (r Result[T]) IsOK() bool { return r.E == nil } - func (r Result[T]) OrElse(v T) T { if r.IsErr() { return v } - return generic.FromPtr(r.v) + return lo.FromPtr(r.v) } -func (r Result[T]) UnwrapErr(setter *error) T { - if setter == nil { - debug.PrintStack() - panic("UnwrapErr: setter is nil") - } - +func (r Result[T]) Expect(format string, args ...any) T { if r.IsErr() { - *setter = errors.WrapCaller(r.E, 1) + err := errors.WrapCaller(r.getErr(), 1) + errNilOrPanic(err, func(e *zerolog.Event) { + e.Str(logfields.Msg, fmt.Sprintf(format, args...)) + }) } - return lo.FromPtr(r.v) + return r.getValue() } -func (r Result[T]) Unwrap(check ...func(err error) error) T { - if r.IsOK() { - return generic.FromPtr(r.v) +func (r Result[T]) Must(events ...func(e *zerolog.Event)) T { + if r.IsErr() { + errNilOrPanic(errors.WrapCaller(r.getErr(), 1), events...) } - if len(check) > 0 && check[0] != nil { - panic(check[0](r.E)) - } else { - panic(r.E) - } + return r.getValue() } -func (r Result[T]) GetValue() T { - if r.IsOK() { - return generic.FromPtr(r.v) - } +func (r Result[T]) CatchErr(setter *error, ctx ...context.Context) bool { + return catchErr(newError(r.err), nil, setter, ctx...) +} - panic(errors.WrapStack(r.E)) +func (r Result[T]) Catch(setter ErrSetter, ctx ...context.Context) bool { + return catchErr(newError(r.err), setter, nil, ctx...) } -func (r Result[T]) Expect(format string, args ...any) T { - if r.IsOK() { - return generic.FromPtr(r.v) - } +func (r Result[T]) IsErr() bool { return r.getErr() != nil } - panic(errors.WrapStack(errors.Wrapf(r.E, format, args...))) -} +func (r Result[T]) IsOK() bool { return r.getErr() == nil } -func (r Result[T]) String() string { - if r.IsOK() { - return fmt.Sprintf("%v", generic.FromPtr(r.v)) +func (r Result[T]) InspectErr(fn func(err error)) Result[T] { + if r.IsErr() { + fn(r.getErr()) } - - return fmt.Sprint(errors.WrapCaller(r.E, 1)) + return r } -func (r Result[T]) MarshalJSON() ([]byte, error) { - if r.IsErr() { - return nil, errors.WrapCaller(r.E, 1) +func (r Result[T]) Inspect(fn func(val T)) Result[T] { + if r.IsOK() { + fn(r.getValue()) } + return r +} - return json.Marshal(generic.FromPtr(r.v)) +func (r Result[T]) LogCtx(ctx context.Context, events ...func(e *zerolog.Event)) Result[T] { + logErr(ctx, 0, r.err, events...) + return r } -func (r Result[T]) UnmarshalJSON([]byte) error { - panic("unimplemented") +func (r Result[T]) Log(events ...func(e *zerolog.Event)) Result[T] { + logErr(nil, 0, r.err, events...) + return r } -func (r Result[T]) Do(fn func(v T)) { +func (r Result[T]) Map(fn func(val T) T) Result[T] { if r.IsErr() { - return + return r } - - fn(generic.FromPtr(r.v)) + return OK(fn(r.getValue())) } -func (r Result[T]) CatchTo(setter *error, callbacks ...func(err error) error) bool { - if setter == nil { - debug.PrintStack() - panic("CatchTo: setter is nil") - } - - if r.IsOK() { - return false - } - - // setter err is not nil - if *setter != nil { - log.Err(*setter).Msgf("CatchTo: setter error is not nil") - return true - } - - var err = r.E - for _, fn := range callbacks { - err = fn(err) - if err == nil { - return false - } +func (r Result[T]) FlatMap(fn func(val T) Result[T]) Result[T] { + if r.IsErr() { + return r } - - *setter = errors.WrapCaller(err, 1) - return true + return fn(r.getValue()) } -func (r Result[T]) InspectErr(fn func(error)) Result[T] { +func (r Result[T]) Validate(fn func(val T) error) Result[T] { if r.IsErr() { - fn(r.E) + return r } - return r -} -func (r Result[T]) Inspect(fn func(T)) Result[T] { - if r.IsOK() { - fn(generic.FromPtr(r.v)) + err := fn(r.getValue()) + if err != nil { + return Fail[T](errors.WrapCaller(err, 1)) } - return r + return OK(r.getValue()) } -func (r Result[T]) FlatMap(fn func(T) Result[T]) Result[T] { +func (r Result[T]) MapErr(fn func(err error) error) Result[T] { if r.IsOK() { return r } - return fn(generic.FromPtr(r.v)) + return Fail[T](fn(r.getErr())) } -func (r Result[T]) Map(fn func(T) T) Result[T] { +func (r Result[T]) MapErrOr(fn func(err error) Result[T]) Result[T] { if r.IsOK() { return r } - return OK(fn(generic.FromPtr(r.v))) + return fn(r.getErr()) } -func (r Result[T]) MapErr(fn func(error) error) Result[T] { +func (r Result[T]) GetErr() error { if r.IsOK() { - return r + return nil } - return Err[T](fn(r.E)) + + return r.getErr() } -func MapTo[Src any, To any](s Result[Src], do func(s Src) To) Result[To] { - if s.IsErr() { - return Err[To](errors.WrapCaller(s.Err(), 1)) +func (r Result[T]) String() string { + if r.IsOK() { + return fmt.Sprintf("OK(%v)", r.getValue()) } + return fmt.Sprintf("Error(%v)", r.getErr()) +} - return OK(do(s.Unwrap())) +func (r Result[T]) WithErrorf(format string, args ...any) Result[T] { + err := fmt.Errorf(format, args...) + err = errors.WrapCaller(err, 1) + return Result[T]{err: err} } -func FlatMap[Src any, To any](s Result[Src], do func(s Src) (r Result[To])) Result[To] { - if s.IsErr() { - return Err[To](errors.WrapCaller(s.Err(), 1)) +func (r Result[T]) WithErr(err error) Result[T] { + if err == nil { + return r } - return do(s.Unwrap()) + err = errors.WrapCaller(err, 1) + return Result[T]{err: err} } -func Unwrap[T any](ret Result[T], gErr *error, callback ...func(err error) error) T { - if gErr == nil { - debug.PrintStack() - panic("Unwrap: gErr is nil") - } +func (r Result[T]) WrapErr(err *errors.Err, tags ...errors.Tag) Result[T] { + return Result[T]{err: errors.WrapTag(errors.WrapCaller(err, 1), tags...)} +} - if ret.IsOK() { - return ret.GetValue() +func (r Result[T]) UnwrapErr(setter *error, contexts ...context.Context) T { + ret, err := unwrapErr(r, setter, nil, contexts...) + if err != nil { + *setter = errors.WrapCaller(err, 1) } + return ret +} - var t T - err := ret.Err() - for _, fn := range callback { - if err == nil { - return t - } - - err = fn(err) +func (r Result[T]) Unwrap(setter ErrSetter, contexts ...context.Context) T { + ret, err := unwrapErr(r, nil, setter, contexts...) + if err != nil { + setError(setter, errors.WrapCaller(err, 1)) } - - *gErr = errors.WrapCaller(err, 1) - return t + return ret } -func Try[T any](fn func() Result[T]) (g Result[T]) { - if fn == nil { - return g.WithErr(errors.WrapStack(errors.New("[fn] is nil"))) +func (r Result[T]) MarshalJSON() ([]byte, error) { + if r.IsErr() { + return nil, errors.WrapCaller(r.err, 1) } - defer func() { - if err := errors.Parse(recover()); !generic.IsNil(err) { - g = g.WithErr(errors.WrapStack(err)) - } + return json.Marshal(funk.FromPtr(r.v)) +} + +func (r Result[T]) getValue() T { return lo.FromPtr(r.v) } - if g.IsErr() { - g = g.WithErr(errors.WrapKV(g.Err(), "fn_stack", stack.CallerWithFunc(fn))) - } - }() +func (r Result[T]) getErr() error { return r.err } - g = fn() - return +func (r Result[T]) setErrorInner() { } diff --git a/result/result_test.go b/result/result_test.go index 8703c337..23d2316d 100644 --- a/result/result_test.go +++ b/result/result_test.go @@ -1,52 +1,92 @@ package result_test import ( + "context" "encoding/json" "fmt" "testing" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/result" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/recovery" + "github.com/pubgo/funk/v2/result" + "github.com/pubgo/funk/v2/result/resultchecker" ) +func TestMust(t *testing.T) { + defer recovery.Testing(t) + result.Must(fmt.Errorf("test must")) +} + type hello struct { Name string `json:"name"` } func TestName(t *testing.T) { - ok := result.OK(&hello{Name: "abc"}) - okBytes := result.Of(json.Marshal(&ok)) + defer recovery.DebugPrint() + ok := &hello{Name: "abc"} + okBytes := result.Wrap(json.Marshal(&ok)) data := string(okBytes.Expect("failed to encode json data")) t.Log(data) if data != `{"name":"abc"}` { t.Log(data) t.Fatal("not match") } - - var ok1 hello - if err := json.Unmarshal([]byte(data), &ok1); err != nil { - t.Fatal(err) - } - t.Log("ok", ok1.Name) } func TestResultDo(t *testing.T) { ok := result.OK(&hello{Name: "abc"}) - ok.Do(func(v *hello) { + ok.Inspect(func(v *hello) { assert.If(v.Name != "abc", "not match") - }) - ok.Do(func(v *hello) { + }).Inspect(func(v *hello) { assert.If(v.Name != "abc", "not match") }) + ok.InspectErr(func(err error) { + t.Log(err) + }) +} - assert.Assert(err1().Err() == nil, "failed to check CatchTo") - assert.Assert(err1().Err().Error() != "test error", "error not match") +func TestErrOf(t *testing.T) { + ctx := log.UpdateEventCtx(context.Background(), log.Map{"test": "ok"}) + resultchecker.RegisterErrCheck(log.RecordErr()) + + var err result.Error + if fn1().Catch(&err, ctx) { + errors.Debug(err.GetErr()) + } } -func err1() (gErr result.Result[any]) { - ret := result.Err[any](fmt.Errorf("test error")) - if ret.CatchTo(&gErr.E) { - return +func fn1() (r result.Result[string]) { + if fn3().Catch(&r) { + return r } - return + + val := fn2().Unwrap(&r) + if r.IsErr() { + return r + } + + return r.WithValue(val) +} + +func fn2() (r result.Result[string]) { + fn3(). + InspectErr(func(err error) { + log.Err(err).Msg("test error") + }). + Catch(&r) + if r.IsErr() { + return r + } + + return r.WithValue("ok") +} + +func fn3() result.Error { + return result.ErrOf(fmt.Errorf("error test, this is error")). + InspectErr(func(err error) { + log.Err(err).Msg("ddd") + }). + Log() } diff --git a/v2/result/resultchecker/checker.go b/result/resultchecker/checker.go similarity index 69% rename from v2/result/resultchecker/checker.go rename to result/resultchecker/checker.go index cf6aa3a5..3088fab6 100644 --- a/v2/result/resultchecker/checker.go +++ b/result/resultchecker/checker.go @@ -2,17 +2,20 @@ package resultchecker import ( "context" - "reflect" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2/stack" ) var errChecks []ErrChecker func RegisterErrCheck(f ErrChecker) bool { - var checkFrame = stack.CallerWithFunc(f) + if f == nil { + return false + } + + checkFrame := stack.CallerWithFunc(f).String() for _, errFunc := range errChecks { - if reflect.DeepEqual(checkFrame, stack.CallerWithFunc(errFunc)) { + if checkFrame == stack.CallerWithFunc(errFunc).String() { return false } } @@ -32,10 +35,10 @@ func GetErrCheckStacks() []*stack.Frame { } func RemoveErrCheck(f func(context.Context, error) error) { - var checkFrame = stack.CallerWithFunc(f) - var index = -1 + checkFrame := stack.CallerWithFunc(f).String() + index := -1 for idx, errFunc := range errChecks { - if reflect.DeepEqual(checkFrame, stack.CallerWithFunc(errFunc)) { + if checkFrame == stack.CallerWithFunc(errFunc).String() { index = idx break } diff --git a/v2/result/resultchecker/checker_test.go b/result/resultchecker/checker_test.go similarity index 100% rename from v2/result/resultchecker/checker_test.go rename to result/resultchecker/checker_test.go diff --git a/v2/result/resultchecker/context.go b/result/resultchecker/context.go similarity index 100% rename from v2/result/resultchecker/context.go rename to result/resultchecker/context.go diff --git a/v2/result/util.go b/result/util.go similarity index 63% rename from v2/result/util.go rename to result/util.go index d76129bd..25438514 100644 --- a/v2/result/util.go +++ b/result/util.go @@ -3,7 +3,6 @@ package result import ( "context" "fmt" - "log/slog" "reflect" "runtime/debug" @@ -13,11 +12,11 @@ import ( "github.com/samber/lo" "google.golang.org/protobuf/encoding/prototext" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/log/logfields" "github.com/pubgo/funk/v2/result/resultchecker" + "github.com/pubgo/funk/v2/stack" ) var errFnIsNil = errors.New("[fn] is nil") @@ -25,20 +24,42 @@ var errFnIsNil = errors.New("[fn] is nil") func try(fn func() error) (gErr error) { if fn == nil { gErr = errors.WrapStack(errFnIsNil) - return + return gErr } defer func() { - if err := errors.Parse(recover()); !generic.IsNil(err) { + if err := errors.Parse(recover()); err != nil { gErr = errors.WrapStack(err) - errors.Debug(gErr) } - gErr = errors.WrapKV(gErr, "fn_stack", stack.CallerWithFunc(fn).String()) + if gErr != nil { + gErr = errors.WrapKV(gErr, "fn_stack", stack.CallerWithFunc(fn).String()) + } }() gErr = fn() - return + return gErr +} + +func tryResult[T any](fn func() Result[T]) (r Result[T]) { + if fn == nil { + return r.WithErr(errFnIsNil) + } + + defer func() { + var gErr error + if err := errors.Parse(recover()); err != nil { + gErr = errors.WrapStack(err) + } + + if gErr != nil { + gErr = errors.WrapKV(gErr, "fn_stack", stack.CallerWithFunc(fn)) + } + + r = r.WithErr(gErr) + }() + + return fn() } func try1[T any](fn func() (T, error)) (t T, gErr error) { @@ -47,9 +68,8 @@ func try1[T any](fn func() (T, error)) (t T, gErr error) { } defer func() { - if err := errors.Parse(recover()); !generic.IsNil(err) { + if err := errors.Parse(recover()); err != nil { gErr = errors.WrapStack(err) - errors.Debug(gErr) } if gErr != nil { @@ -58,20 +78,15 @@ func try1[T any](fn func() (T, error)) (t T, gErr error) { }() t, gErr = fn() - return + return t, gErr } -func errNilOrPanic(err error, args ...any) { +func errNilOrPanic(err error, events ...func(e *zerolog.Event)) { if err == nil { return } - if len(args) > 0 { - err = errors.Wrap(err, fmt.Sprint(args...)) - } - - err = errors.WrapStack(err) - errors.Debug(err) + logErr(nil, 1, err, events...) panic(err) } @@ -84,7 +99,7 @@ func catchErr(r Error, setter ErrSetter, rawSetter *error, contexts ...context.C return false } - var isErr = func() bool { + isErr := func() bool { if setter != nil { return setter.IsErr() } @@ -96,7 +111,7 @@ func catchErr(r Error, setter ErrSetter, rawSetter *error, contexts ...context.C return false } - var getErr = func() error { + getErr := func() error { if setter != nil { return setter.GetErr() } @@ -108,7 +123,7 @@ func catchErr(r Error, setter ErrSetter, rawSetter *error, contexts ...context.C return nil } - var setErr = func(err error) { + setErr := func(err error) { if setter != nil { setError(setter, err) } @@ -118,7 +133,7 @@ func catchErr(r Error, setter ErrSetter, rawSetter *error, contexts ...context.C } } - var ctx = context.Background() + ctx := context.Background() for i := range contexts { if contexts[i] == nil { continue @@ -133,8 +148,8 @@ func catchErr(r Error, setter ErrSetter, rawSetter *error, contexts ...context.C log.Err(err, ctx).Msgf("error setter has already set the error, err=%s", err.Error()) } - var checkers = append(resultchecker.GetErrChecks(), resultchecker.GetCheckersFromCtx(ctx)...) - var err = r.getErr() + checkers := append(resultchecker.GetErrChecks(), resultchecker.GetCheckersFromCtx(ctx)...) + err := r.getErr() for _, fn := range checkers { err = fn(ctx, err) if err == nil { @@ -164,7 +179,7 @@ func errRecovery(getErr func() error, callbacks ...func(err error) error) error } } - debug.PrintStack() + stack.PrintStack() return err } @@ -173,12 +188,12 @@ func unwrapErr[T any](r Result[T], setter1 *error, setter2 ErrSetter, contexts . errNilOrPanic(fmt.Errorf("error setter is nil")) } - var ret = r.getValue() + ret := r.getValue() if r.IsOK() { return ret, nil } - var ctx = context.Background() + ctx := context.Background() if len(contexts) > 0 { ctx = contexts[0] } @@ -194,8 +209,8 @@ func unwrapErr[T any](r Result[T], setter1 *error, setter2 ErrSetter, contexts . log.Err(preErr, ctx).Msgf("error setter has already set the error, err=%v", preErr) } - var err = r.getErr() - var checkers = append(resultchecker.GetErrChecks(), resultchecker.GetCheckersFromCtx(ctx)...) + err := r.getErr() + checkers := append(resultchecker.GetErrChecks(), resultchecker.GetCheckersFromCtx(ctx)...) for _, fn := range checkers { err = fn(ctx, err) if err == nil { @@ -219,15 +234,18 @@ func setError(setter ErrSetter, err error) { switch errSet := setter.(type) { case *Error: errSet.err = err - case *ErrProxy: + case *ProxyErr: + *errSet.err = err + case ProxyErr: *errSet.err = err default: rv := reflect.ValueOf(setter) t := rv.Type() if !strings.Contains(t.String(), "Result[") { - slog.Error("error setter type error", + slog.Error("error setter type error, type is not Result", slog.String("type", fmt.Sprintf("%T", setter)), + slog.String("type-string", t.String()), slog.String("stack", string(debug.Stack())), ) return @@ -238,22 +256,30 @@ func setError(setter ErrSetter, err error) { } } -func logErr(ctx context.Context, err error, events ...func(e *zerolog.Event)) { +var resultFile = stack.Caller(0) + +func logErr(ctx context.Context, skip int, err error, events ...func(e *zerolog.Event)) { if err == nil { return } + traces := lo.Filter(stack.Trace(), func(item *stack.Frame, index int) bool { + return !item.IsRuntime() && item.Pkg != resultFile.Pkg + }) + log.Error(ctx). + Func(func(e *zerolog.Event) { + e.Str(logfields.Module, "result") + e.Strs(logfields.ErrorStack, lo.Map(traces, func(item *stack.Frame, index int) string { return item.String() })) + e.Str(logfields.ErrorID, errors.GetErrorId(err)) + e.Str(logfields.ErrorDetail, fmt.Sprintf("%v", err)) + e.Str(zerolog.ErrorFieldName, err.Error()) + e.CallerSkipFrame(2 + skip) + }). Func(func(e *zerolog.Event) { for _, fn := range events { fn(e) } - - if id := errors.GetErrorId(err); id != "" { - e.Str("error_id", id) - } }). - Str(zerolog.ErrorFieldName, err.Error()). - CallerSkipFrame(2). Msgf("%s\n%s", err.Error(), prototext.Format(errors.ParseErrToPb(err))) } diff --git a/retry/backoff_constant.go b/retry/backoff_constant.go index bc84da7a..c8abb557 100644 --- a/retry/backoff_constant.go +++ b/retry/backoff_constant.go @@ -3,7 +3,7 @@ package retry import ( "time" - "github.com/pubgo/funk/assert" + "github.com/pubgo/funk/v2/assert" ) const DefaultConstant = time.Second diff --git a/retry/backoff_exponential.go b/retry/backoff_exponential.go index 57a4c90c..c439b78c 100644 --- a/retry/backoff_exponential.go +++ b/retry/backoff_exponential.go @@ -4,7 +4,7 @@ import ( "sync/atomic" "time" - "github.com/pubgo/funk/assert" + "github.com/pubgo/funk/v2/assert" ) // NewExponential creates a new exponential backoff using the starting value of diff --git a/retry/backoff_fibonacci.go b/retry/backoff_fibonacci.go index 94f3b489..2a60604b 100644 --- a/retry/backoff_fibonacci.go +++ b/retry/backoff_fibonacci.go @@ -5,7 +5,7 @@ import ( "time" "unsafe" - "github.com/pubgo/funk/assert" + "github.com/pubgo/funk/v2/assert" ) // NewFibonacci creates a new Fibonacci backoff using the starting value of diff --git a/retry/retry.go b/retry/retry.go index 9732ce55..5578ca71 100644 --- a/retry/retry.go +++ b/retry/retry.go @@ -3,7 +3,7 @@ package retry import ( "time" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2/recovery" ) type Retry func() Backoff @@ -22,15 +22,15 @@ func (d Retry) Do(f func(i int) error) (err error) { dur, stop := b.Next() if stop { - return + return err } time.Sleep(dur) } } -func (d Retry) DoVal(f func(i int) (interface{}, error)) (val interface{}, err error) { - wrap := func(i int) (val interface{}, err error) { +func (d Retry) DoVal(f func(i int) (any, error)) (val any, err error) { + wrap := func(i int) (val any, err error) { defer recovery.Err(&err) return f(i) } @@ -43,7 +43,7 @@ func (d Retry) DoVal(f func(i int) (interface{}, error)) (val interface{}, err e dur, stop := b.Next() if stop { - return + return val, err } time.Sleep(dur) diff --git a/running/runtime.go b/running/runtime.go index dbf3952a..57376e97 100644 --- a/running/runtime.go +++ b/running/runtime.go @@ -1,37 +1,41 @@ package running import ( + "context" "os" + "strconv" "strings" + "sync" "github.com/projectdiscovery/machineid" "github.com/rs/xid" - - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/env" - "github.com/pubgo/funk/netutil" - "github.com/pubgo/funk/pathutil" - "github.com/pubgo/funk/strutil" - "github.com/pubgo/funk/version" + "github.com/urfave/cli/v3" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/buildinfo/version" + "github.com/pubgo/funk/v2/config" + "github.com/pubgo/funk/v2/env" + "github.com/pubgo/funk/v2/netutil" + "github.com/pubgo/funk/v2/pathutil" + "github.com/pubgo/funk/v2/strutil" ) // default global variables var ( - HttpPort = 8080 - GrpcPort = 50051 - Project = version.Project() - - Env = "debug" - IsDebug = true + Env = sync.OnceValue(func() string { return EnvFlag.Get().(string) }) + Debug = sync.OnceValue(func() bool { return DebugFlag.Get().(bool) }) + HttpPort = sync.OnceValue(func() int { return HttpPortFlag.Get().(int) }) + GrpcPort = sync.OnceValue(func() int { return GrpcPortFlag.Get().(int) }) + Project = version.Project // InstanceID service id InstanceID = xid.New().String() DeviceID = InstanceID - Version = version.Version() + Version = version.Version - CommitID = version.CommitID() + CommitID = version.CommitID Pwd = assert.Exit1(os.Getwd()) @@ -39,14 +43,14 @@ var ( LocalIP = netutil.GetLocalIP() Hostname = strutil.FirstFnNotEmpty( - func() string { return os.Getenv("HOSTNAME") }, + func() string { return env.Get("HOSTNAME") }, func() string { return assert.Exit1(os.Hostname()) }, ) // Namespace K8s namespace Namespace = strutil.FirstFnNotEmpty( - func() string { return os.Getenv("NAMESPACE") }, - func() string { return os.Getenv("POD_NAMESPACE") }, + func() string { return env.Get("NAMESPACE") }, + func() string { return env.Get("POD_NAMESPACE") }, func() string { file := "/var/run/secrets/kubernetes.io/serviceaccount/namespace" if pathutil.IsNotExist(file) { @@ -57,13 +61,79 @@ var ( }, ) - Domain string + Domain = version.Domain + + DebugFlag = cli.BoolFlag{ + Name: "debug", + Usage: "enable debug mode", + Value: false, + Local: true, + Category: "system", + Sources: cli.EnvVars(env.Key("enable_debug"), env.Key("debug")), + Action: func(ctx context.Context, command *cli.Command, b bool) error { + env.Set("enable_debug", strconv.FormatBool(b)) + env.Set("debug", strconv.FormatBool(b)) + return nil + }, + } + + EnvFlag = cli.StringFlag{ + Name: "env", + Usage: "running env, dev,test,stage,prod", + Value: "dev", + Local: true, + Category: "system", + Sources: cli.NewValueSourceChain(cli.EnvVar(env.Key("env")), cli.EnvVar(env.Key("run_env"))), + Action: func(ctx context.Context, command *cli.Command, s string) error { + env.Set("env", s) + env.Set("run_env", s) + return nil + }, + } + + GrpcPortFlag = cli.IntFlag{ + Name: "grpc-port", + Usage: "service grpc port", + Local: true, + Value: 50051, + Category: "system", + Sources: cli.EnvVars(env.Key("server_grpc_port")), + Action: func(ctx context.Context, command *cli.Command, i int) error { + env.Set("server_grpc_port", strconv.Itoa(i)) + return nil + }, + } + + HttpPortFlag = cli.IntFlag{ + Name: "http-port", + Usage: "service http port", + Local: true, + Value: 8080, + Category: "system", + Sources: cli.EnvVars(env.Key("server_http_port")), + Action: func(ctx context.Context, command *cli.Command, i int) error { + env.Set("server_http_port", strconv.Itoa(i)) + return nil + }, + } + + ConfFlag = cli.StringFlag{ + Name: "config", + Aliases: []string{"c"}, + Usage: "config path", + Value: config.GetConfigPath(), + Local: true, + Category: "system", + Sources: cli.EnvVars(env.Key("config_path")), + Action: func(ctx context.Context, command *cli.Command, s string) error { + config.SetConfigPath(s) + env.Set("config_path", s) + return nil + }, + } ) func init() { - env.GetBoolVal(&IsDebug, "enable_debug", "debug", "dev_mode") - env.GetVal(&Env, "env", "run_mode", "run_env") - id, err := machineid.ID() if err == nil { DeviceID = id diff --git a/running/util.go b/running/util.go index f7aaf443..023e1747 100644 --- a/running/util.go +++ b/running/util.go @@ -6,32 +6,28 @@ import ( semver "github.com/hashicorp/go-version" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/recovery" - "github.com/pubgo/funk/version" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/buildinfo/version" + "github.com/pubgo/funk/v2/recovery" ) -func SetVersion(v string) { Version = v } -func SetProject(p string) { Project = p } -func SetDomain(d string) { Domain = d } - func GetSysInfo() map[string]string { return map[string]string{ "main_path": version.MainPath(), - "grpc_port": fmt.Sprintf("%v", GrpcPort), - "http_post": fmt.Sprintf("%v", HttpPort), - "debug": fmt.Sprintf("%v", IsDebug), + "grpc_port": fmt.Sprintf("%v", GrpcPort()), + "http_post": fmt.Sprintf("%v", HttpPort()), + "debug": fmt.Sprintf("%v", Debug()), "cur_dir": Pwd, "local_ip": LocalIP, "namespace": Namespace, "instance_id": InstanceID, "device_id": DeviceID, - "project": Project, + "project": Project(), "hostname": Hostname, "build_time": version.BuildTime(), - "version": Version, - "domain": Domain, - "commit_id": CommitID, + "version": Version(), + "domain": Domain(), + "commit_id": CommitID(), "go_root": rt.GOROOT(), "go_arch": rt.GOARCH, "go_os": rt.GOOS, @@ -43,6 +39,10 @@ func GetSysInfo() map[string]string { func CheckVersion() { defer recovery.Exit() + assert.If(version.Project() == "", "project is null") + assert.If(version.Version() == "", "version is null") + assert.If(version.CommitID() == "", "commitID is null") + assert.If(version.BuildTime() == "", "buildTime is null") assert.MustFn(func() error { _, err := semver.NewVersion(version.Version()) if err != nil { @@ -50,8 +50,4 @@ func CheckVersion() { } return nil }) - assert.If(version.Project() == "", "project is null") - assert.If(version.Version() == "", "version is null") - assert.If(version.CommitID() == "", "commitID is null") - assert.If(version.BuildTime() == "", "buildTime is null") } diff --git a/shutil/shell.go b/shutil/shell.go index 03cd3c06..5fd76324 100644 --- a/shutil/shell.go +++ b/shutil/shell.go @@ -2,30 +2,28 @@ package shutil import ( "bytes" + "fmt" "os" "os/exec" "strings" - "github.com/pubgo/funk/log" + "github.com/rs/zerolog" + + "github.com/pubgo/funk/v2/log/logfields" "github.com/pubgo/funk/v2/result" ) func Run(args ...string) (r result.Result[string]) { - defer result.RecoveryErr(&r) + defer result.Recovery(&r) b := bytes.NewBufferString("") cmd := Shell(args...) cmd.Stdout = b - result.ErrOf(cmd.Run()). - Inspect(func(err error) { - log.Err(err).Msg("failed to execute: " + strings.Join(args, " ")) - }). - CatchErr(&r) - if r.IsErr() { - return - } + result.ErrOf(cmd.Run()).Must(func(e *zerolog.Event) { + e.Str(logfields.Msg, fmt.Sprintf("failed to execute: %q", args)) + }) return r.WithValue(strings.TrimSpace(b.String())) } diff --git a/stack/stack.go b/stack/stack.go index 09586962..682ccd67 100644 --- a/stack/stack.go +++ b/stack/stack.go @@ -43,6 +43,8 @@ func (f *Frame) IsRuntime() bool { func GetGORoot() string { return goRoot } +// Caller returns the Frame of the caller. +// skip: skip frames, 0 means the current call, 1 means the parent call func Caller(skip int) *Frame { var pcs [1]uintptr n := runtime.Callers(skip+2, pcs[:]) @@ -53,6 +55,7 @@ func Caller(skip int) *Frame { return stack(pcs[0] - 1) } +// Callers returns the Frame of the callers. func Callers(depth int, skips ...int) []*Frame { skip := 0 if len(skips) > 0 { @@ -80,7 +83,9 @@ func CallerWithType(typ reflect.Type) *Frame { return &Frame{Pkg: typ.PkgPath(), Name: typ.Name(), File: typ.PkgPath()} } -func CallerWithFunc(fn interface{}) *Frame { +// CallerWithFunc returns the Frame of the caller. +// fn: function +func CallerWithFunc(fn any) *Frame { if fn == nil { panic("[fn] param is nil") } diff --git a/stack/stack_test.go b/stack/stack_test.go index 3e1647f4..5a9be0d1 100644 --- a/stack/stack_test.go +++ b/stack/stack_test.go @@ -5,10 +5,11 @@ import ( "reflect" "testing" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/stack" "github.com/stretchr/testify/assert" + + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/pretty" + "github.com/pubgo/funk/v2/stack" ) func init1() { @@ -40,7 +41,7 @@ func TestCallerWithDepth(t *testing.T) { func TestCallType(t *testing.T) { assert.Equal(t, - "github.com/pubgo/funk/errors", + "github.com/pubgo/funk/v2/errors", stack.CallerWithType(reflect.TypeOf(errors.ErrMsg{})).Pkg, ) } diff --git a/stack/trace_test.go b/stack/trace_test.go index b0448295..e2c11bb5 100644 --- a/stack/trace_test.go +++ b/stack/trace_test.go @@ -3,11 +3,16 @@ package stack_test import ( "testing" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/stack" + "github.com/samber/lo" + + "github.com/pubgo/funk/v2/pretty" + "github.com/pubgo/funk/v2/stack" ) func TestTrace(t *testing.T) { traces := stack.Trace() t.Log(pretty.Sprint(traces)) + + traces = lo.Filter(traces, func(item *stack.Frame, index int) bool { return !item.IsRuntime() }) + t.Log(pretty.Sprint(lo.Map(traces, func(item *stack.Frame, index int) string { return item.String() }))) } diff --git a/stack/util.go b/stack/util.go new file mode 100644 index 00000000..62618d09 --- /dev/null +++ b/stack/util.go @@ -0,0 +1,17 @@ +package stack + +import ( + "runtime/debug" + + "github.com/pubgo/funk/v2/features" +) + +var EnablePrintStack = features.Bool("stack.enable_print_stack", false, "stack enable print stack data") + +func PrintStack() { + if !EnablePrintStack.GetValue() { + return + } + + debug.PrintStack() +} diff --git a/strutil/template.go b/strutil/template.go index 2c2c376e..adafeb84 100644 --- a/strutil/template.go +++ b/strutil/template.go @@ -3,8 +3,9 @@ package strutil import ( "io" - "github.com/pubgo/funk/convert" "github.com/valyala/fasttemplate" + + "github.com/pubgo/funk/v2/convert" ) func Format(template string, data map[string]string) string { diff --git a/syncutil/base.go b/syncutil/base.go index 14574867..35e11c1a 100644 --- a/syncutil/base.go +++ b/syncutil/base.go @@ -1,6 +1,6 @@ package syncutil -import "github.com/pubgo/funk/log" +import "github.com/pubgo/funk/v2/log" const Name = "sync-util" diff --git a/syncutil/pool_test.go b/syncutil/pool_test.go index 138f48d1..64b52969 100644 --- a/syncutil/pool_test.go +++ b/syncutil/pool_test.go @@ -10,11 +10,11 @@ import ( func TestPool(t *testing.T) { now := time.Now() defer func() { - var cost = time.Since(now) + cost := time.Since(now) assert.True(t, cost > time.Millisecond*10*2 && cost < time.Millisecond*10*3) }() - var p = NewPool().WithMaxGoroutines(5) + p := NewPool().WithMaxGoroutines(5) assert.Equal(t, p.MaxGoroutines(), 5) for i := 0; i < 10; i++ { p.Go(func() { diff --git a/syncutil/unbounded.go b/syncutil/unbounded.go index 4c3339be..8bcbfaf9 100644 --- a/syncutil/unbounded.go +++ b/syncutil/unbounded.go @@ -34,18 +34,18 @@ import "sync" // defining a new type specific implementation of this buffer is preferred. See // internal/transport/transport.go for an example of this. type Unbounded struct { - c chan interface{} + c chan any mu sync.Mutex - backlog []interface{} + backlog []any } // NewUnbounded returns a new instance of Unbounded. func NewUnbounded() *Unbounded { - return &Unbounded{c: make(chan interface{}, 1)} + return &Unbounded{c: make(chan any, 1)} } // Put adds t to the unbounded buffer. -func (b *Unbounded) Put(t interface{}) { +func (b *Unbounded) Put(t any) { b.mu.Lock() if len(b.backlog) == 0 { select { @@ -80,6 +80,6 @@ func (b *Unbounded) Load() { // // Upon reading a value from this channel, users are expected to call Load() to // send the next buffered value onto the channel if there is any. -func (b *Unbounded) Get() <-chan interface{} { +func (b *Unbounded) Get() <-chan any { return b.c } diff --git a/syncutil/waitgroup.go b/syncutil/waitgroup.go index 2a09a43a..ef768359 100644 --- a/syncutil/waitgroup.go +++ b/syncutil/waitgroup.go @@ -3,10 +3,11 @@ package syncutil import ( "sync" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/stack" - "github.com/pubgo/funk/try" "github.com/rs/zerolog" + + "github.com/pubgo/funk/v2/log" + "github.com/pubgo/funk/v2/stack" + "github.com/pubgo/funk/v2/try" ) type WaitGroup struct { diff --git a/template/template.go b/template/template.go index 18f7abaa..d5a6b6d7 100644 --- a/template/template.go +++ b/template/template.go @@ -8,8 +8,8 @@ import ( "github.com/open2b/scriggo" "github.com/open2b/scriggo/native" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/log" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/log" ) type Template struct { @@ -37,7 +37,7 @@ func Build[Data any](t *Template, name string, data *Data) (string, error) { tt, _ := t.templates.Load(name) var buf bytes.Buffer - err := tt.(*scriggo.Template).Run(&buf, map[string]interface{}{"data": data}, nil) + err := tt.(*scriggo.Template).Run(&buf, map[string]any{"data": data}, nil) if err != nil { return "", err } diff --git a/testing/aaa.go b/testing/aaa.go index e9496822..6a601259 100644 --- a/testing/aaa.go +++ b/testing/aaa.go @@ -2,13 +2,15 @@ package testing import "testing" -var _ Interface = (*testing.T)(nil) -var _ Interface = (*testing.B)(nil) +var ( + _ Interface = (*testing.T)(nil) + _ Interface = (*testing.B)(nil) +) type Interface interface { Name() string Cleanup(f func()) - Logf(fmt string, args ...interface{}) - Fatalf(format string, args ...interface{}) - Errorf(message string, args ...interface{}) + Logf(fmt string, args ...any) + Fatalf(format string, args ...any) + Errorf(message string, args ...any) } diff --git a/try/try.go b/try/try.go index 706e1f19..5aed0e0d 100644 --- a/try/try.go +++ b/try/try.go @@ -1,35 +1,11 @@ package try import ( - "github.com/pubgo/funk" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/result" - "github.com/pubgo/funk/stack" + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/errors" + "github.com/pubgo/funk/v2/stack" ) -// Result -// Deprecated: use result.Try instead -func Result[T any](fn func() result.Result[T]) (g result.Result[T]) { - if fn == nil { - g = g.WithErr(errors.WrapStack(errors.New("[fn] is nil"))) - return - } - - defer func() { - if err := errors.Parse(recover()); !generic.IsNil(err) { - g = g.WithErr(errors.WrapStack(err)) - } - - if g.IsErr() { - g = g.WithErr(errors.WrapKV(g.Err(), "fn_stack", stack.CallerWithFunc(fn))) - } - }() - - g = fn() - return -} - func WithErr(gErr *error, fn func() error) { if fn == nil { *gErr = errors.WrapStack(errors.New("[fn] is nil")) @@ -50,7 +26,7 @@ func WithErr(gErr *error, fn func() error) { func Try(fn func() error) (gErr error) { if fn == nil { gErr = errors.WrapStack(errors.New("[fn] is nil")) - return + return gErr } defer func() { @@ -62,5 +38,5 @@ func Try(fn func() error) (gErr error) { }() gErr = fn() - return + return gErr } diff --git a/try/try_test.go b/try/try_test.go index 9bd1f245..3b6e71bc 100644 --- a/try/try_test.go +++ b/try/try_test.go @@ -3,7 +3,7 @@ package try import ( "testing" - "github.com/pubgo/funk/errors" + "github.com/pubgo/funk/v2/errors" ) func TestTry(t *testing.T) { diff --git a/typex/lock_map.go b/typex/lock_map.go index 0407b09d..c0c28886 100644 --- a/typex/lock_map.go +++ b/typex/lock_map.go @@ -3,7 +3,7 @@ package typex import ( "sync" - "github.com/pubgo/funk/generic" + "github.com/pubgo/funk/v2" ) var globalMutex sync.Mutex @@ -54,7 +54,7 @@ func (t *Map[T]) Get(key string) T { return val } - return generic.Zero[T]() + return funk.Zero[T]() } func (t *Map[T]) Load(key string) (T, bool) { diff --git a/typex/priority_queue.go b/typex/priority_queue.go index c498dea5..70c8a509 100644 --- a/typex/priority_queue.go +++ b/typex/priority_queue.go @@ -3,7 +3,7 @@ package typex import "container/heap" type PriorityQueueItem struct { - Value interface{} + Value any Priority int64 Index int } @@ -28,7 +28,7 @@ func (pq *PriorityQueue) PushItem(x *PriorityQueueItem) { pq.Push(x) } // Push implements the heap.Interface.Push. // Adds x as element Len(). -func (pq *PriorityQueue) Push(x interface{}) { +func (pq *PriorityQueue) Push(x any) { n := len(*pq) item := x.(*PriorityQueueItem) item.Index = n @@ -46,7 +46,7 @@ func (pq *PriorityQueue) PopItem() *PriorityQueueItem { // Pop implements the heap.Interface.Pop. // Removes and returns element Len() - 1. -func (pq *PriorityQueue) Pop() interface{} { +func (pq *PriorityQueue) Pop() any { old := *pq n := len(old) if n == 0 { @@ -63,4 +63,4 @@ func (pq *PriorityQueue) Pop() interface{} { func (pq *PriorityQueue) Head() *PriorityQueueItem { return (*pq)[0] } // Remove removes and returns the element at Index i from the PriorityQueue. -func (pq *PriorityQueue) Remove(i int) interface{} { return heap.Remove(pq, i) } +func (pq *PriorityQueue) Remove(i int) any { return heap.Remove(pq, i) } diff --git a/typex/rw_map.go b/typex/rw_map.go index 9ffa347a..f8149653 100644 --- a/typex/rw_map.go +++ b/typex/rw_map.go @@ -4,7 +4,7 @@ import "sync" type RwMap struct { rw sync.RWMutex - data map[string]interface{} + data map[string]any } func (t *RwMap) Has(key string) bool { @@ -15,11 +15,11 @@ func (t *RwMap) Has(key string) bool { return ok } -func (t *RwMap) Map() map[string]interface{} { +func (t *RwMap) Map() map[string]any { t.rw.RLock() defer t.rw.RUnlock() - dt := make(map[string]interface{}, len(t.data)) + dt := make(map[string]any, len(t.data)) for k, v := range t.data { dt[k] = v } @@ -27,7 +27,7 @@ func (t *RwMap) Map() map[string]interface{} { return dt } -func (t *RwMap) Get(key string) interface{} { +func (t *RwMap) Get(key string) any { t.rw.RLock() val, ok := t.data[key] defer t.rw.RUnlock() @@ -39,7 +39,7 @@ func (t *RwMap) Get(key string) interface{} { return NotFound } -func (t *RwMap) Load(key string) (interface{}, bool) { +func (t *RwMap) Load(key string) (any, bool) { t.rw.RLock() val, ok := t.data[key] t.rw.RUnlock() @@ -58,7 +58,7 @@ func (t *RwMap) Keys() []string { return keys } -func (t *RwMap) Each(fn func(name string, val interface{})) { +func (t *RwMap) Each(fn func(name string, val any)) { t.rw.RLock() defer t.rw.RUnlock() @@ -67,7 +67,7 @@ func (t *RwMap) Each(fn func(name string, val interface{})) { } } -func (t *RwMap) Range(fn func(name string, val interface{}) bool) { +func (t *RwMap) Range(fn func(name string, val any) bool) { t.rw.RLock() defer t.rw.RUnlock() @@ -78,12 +78,12 @@ func (t *RwMap) Range(fn func(name string, val interface{}) bool) { } } -func (t *RwMap) Set(key string, val interface{}) { +func (t *RwMap) Set(key string, val any) { t.rw.Lock() defer t.rw.Unlock() if t.data == nil { - t.data = make(map[string]interface{}, 8) + t.data = make(map[string]any, 8) } t.data[key] = val diff --git a/typex/rw_queue.go b/typex/rw_queue.go index 791cfac0..703da488 100644 --- a/typex/rw_queue.go +++ b/typex/rw_queue.go @@ -4,7 +4,7 @@ import ( "sync" ) -func QueueOf(val ...interface{}) *Queue { +func QueueOf(val ...any) *Queue { q := &Queue{} for i := range val { q.Push(val[i]) @@ -14,27 +14,27 @@ func QueueOf(val ...interface{}) *Queue { type Queue struct { mu sync.RWMutex - data []interface{} + data []any } -func (t *Queue) Push(val interface{}) { +func (t *Queue) Push(val any) { t.mu.Lock() defer t.mu.Unlock() t.data = append(t.data, val) } -func (t *Queue) Pop() interface{} { +func (t *Queue) Pop() any { t.mu.Lock() defer t.mu.Unlock() - data := make([]interface{}, len(t.data)-1) + data := make([]any, len(t.data)-1) copy(data, t.data[:len(t.data)-2]) t.data = data return t.data[len(t.data)-1] } -func (t *Queue) PopFirst() interface{} { +func (t *Queue) PopFirst() any { t.mu.Lock() defer t.mu.Unlock() @@ -42,7 +42,7 @@ func (t *Queue) PopFirst() interface{} { return nil } - data := make([]interface{}, len(t.data)-1) + data := make([]any, len(t.data)-1) copy(data, t.data[1:]) t.data = data return t.data[0] @@ -59,7 +59,7 @@ func (t *Queue) Del(index uint32) { copy(t.data[:index], t.data[index+1:]) } -func (t *Queue) Get(index uint32) interface{} { +func (t *Queue) Get(index uint32) any { t.mu.RLock() defer t.mu.RUnlock() @@ -70,20 +70,20 @@ func (t *Queue) Get(index uint32) interface{} { return t.data[index] } -func (t *Queue) List() []interface{} { - data := make([]interface{}, len(t.data)) +func (t *Queue) List() []any { + data := make([]any, len(t.data)) copy(data, t.data) return data } -func (t *Queue) First() interface{} { +func (t *Queue) First() any { t.mu.RLock() defer t.mu.RUnlock() return t.data[0] } -func (t *Queue) Last() interface{} { +func (t *Queue) Last() any { t.mu.RLock() defer t.mu.RUnlock() diff --git a/typex/set.go b/typex/set.go index becbefc6..2f21949c 100644 --- a/typex/set.go +++ b/typex/set.go @@ -4,13 +4,14 @@ import ( "reflect" "sync" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/recovery" "go.uber.org/atomic" + + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/recovery" ) -func SetOf(val ...interface{}) *Set { +func SetOf(val ...any) *Set { s := &Set{} for i := range val { s.Add(val[i]) @@ -23,10 +24,10 @@ type Set struct { count atomic.Uint32 } -func (t *Set) Has(v interface{}) bool { _, ok := t.m.Load(v); return ok } -func (t *Set) Len() uint32 { return t.count.Load() } +func (t *Set) Has(v any) bool { _, ok := t.m.Load(v); return ok } +func (t *Set) Len() uint32 { return t.count.Load() } -func (t *Set) Map(data interface{}) (err error) { +func (t *Set) Map(data any) (err error) { defer recovery.Err(&err) vd := reflect.ValueOf(data) @@ -34,7 +35,7 @@ func (t *Set) Map(data interface{}) (err error) { vd = vd.Elem() dt := reflect.MakeSlice(vd.Type(), 0, int(t.count.Load())) - t.m.Range(func(key, _ interface{}) bool { + t.m.Range(func(key, _ any) bool { dt = reflect.AppendSlice(dt, reflect.ValueOf(key)) return true }) @@ -43,21 +44,21 @@ func (t *Set) Map(data interface{}) (err error) { return nil } -func (t *Set) Add(v interface{}) { +func (t *Set) Add(v any) { _, ok := t.m.LoadOrStore(v, struct{}{}) if !ok { t.count.Inc() } } -func (t *Set) List() (val []interface{}) { - t.m.Range(func(key, _ interface{}) bool { val = append(val, key); return true }) - return +func (t *Set) List() (val []any) { + t.m.Range(func(key, _ any) bool { val = append(val, key); return true }) + return val } -func (t *Set) Each(fn interface{}) { +func (t *Set) Each(fn any) { assert.If(fn == nil, "[fn] should not be nil") vfn := reflect.ValueOf(fn) - t.m.Range(func(key, value interface{}) bool { _ = vfn.Call(generic.ListOf(reflect.ValueOf(key))); return true }) + t.m.Range(func(key, value any) bool { _ = vfn.Call(funk.ListOf(reflect.ValueOf(key))); return true }) } diff --git a/typex/sync_map.go b/typex/sync_map.go index c05196c4..f6b67d6b 100644 --- a/typex/sync_map.go +++ b/typex/sync_map.go @@ -4,9 +4,9 @@ import ( "reflect" "sync" - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/generic" - "github.com/pubgo/funk/recovery" + "github.com/pubgo/funk/v2" + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/recovery" ) var NotFound = new(struct{}) @@ -15,34 +15,34 @@ type SyncMap struct { data sync.Map } -func (t *SyncMap) Each(fn interface{}) (err error) { +func (t *SyncMap) Each(fn any) (err error) { defer recovery.Err(&err) assert.If(fn == nil, "[fn] should not be nil") vfn := reflect.ValueOf(fn) onlyKey := reflect.TypeOf(fn).NumIn() == 1 - t.data.Range(func(key, value interface{}) bool { + t.data.Range(func(key, value any) bool { if onlyKey { - _ = vfn.Call(generic.ListOf(reflect.ValueOf(key))) + _ = vfn.Call(funk.ListOf(reflect.ValueOf(key))) return true } - _ = vfn.Call(generic.ListOf(reflect.ValueOf(key), reflect.ValueOf(value))) + _ = vfn.Call(funk.ListOf(reflect.ValueOf(key), reflect.ValueOf(value))) return true }) return nil } -func (t *SyncMap) Map(fn func(val interface{}) interface{}) { - t.data.Range(func(key, value interface{}) bool { +func (t *SyncMap) Map(fn func(val any) any) { + t.data.Range(func(key, value any) bool { t.data.Store(key, fn(value)) return true }) } -func (t *SyncMap) MapTo(data interface{}) (err error) { +func (t *SyncMap) MapTo(data any) (err error) { defer recovery.Err(&err) vd := reflect.ValueOf(data) @@ -55,7 +55,7 @@ func (t *SyncMap) MapTo(data interface{}) (err error) { // var data map[string]int; MapTo(&data) assert.If(!vd.IsValid() || vd.IsNil(), "[data] type error") - t.data.Range(func(key, value interface{}) bool { + t.data.Range(func(key, value any) bool { vd.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(value)) return true }) @@ -63,11 +63,11 @@ func (t *SyncMap) MapTo(data interface{}) (err error) { return nil } -func (t *SyncMap) Set(key, value interface{}) { +func (t *SyncMap) Set(key, value any) { t.data.Store(key, value) } -func (t *SyncMap) Get(key interface{}) interface{} { +func (t *SyncMap) Get(key any) any { value, ok := t.data.Load(key) if ok { return value @@ -76,10 +76,10 @@ func (t *SyncMap) Get(key interface{}) interface{} { return NotFound } -func (t *SyncMap) LoadAndDelete(key interface{}) (value interface{}, ok bool) { +func (t *SyncMap) LoadAndDelete(key any) (value any, ok bool) { return t.data.LoadAndDelete(key) } -func (t *SyncMap) Load(key interface{}) (value interface{}, ok bool) { return t.data.Load(key) } -func (t *SyncMap) Range(f func(key, value interface{}) bool) { t.data.Range(f) } -func (t *SyncMap) Delete(key interface{}) { t.data.Delete(key) } -func (t *SyncMap) Has(key interface{}) (ok bool) { _, ok = t.data.Load(key); return } +func (t *SyncMap) Load(key any) (value any, ok bool) { return t.data.Load(key) } +func (t *SyncMap) Range(f func(key, value any) bool) { t.data.Range(f) } +func (t *SyncMap) Delete(key any) { t.data.Delete(key) } +func (t *SyncMap) Has(key any) (ok bool) { _, ok = t.data.Load(key); return ok } diff --git a/typex/yaml.go b/typex/yaml.go index 0ca917be..889a0412 100644 --- a/typex/yaml.go +++ b/typex/yaml.go @@ -1,9 +1,10 @@ package typex import ( - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" yaml "gopkg.in/yaml.v3" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/errors" ) type YamlListType[T any] []T @@ -31,6 +32,6 @@ func (p *YamlListType[T]) UnmarshalYAML(value *yaml.Node) error { default: var val any assert.Exit(value.Decode(&val)) - return errors.Format("yaml kind type error, kind=%v data=%v", value.Kind, val) + return errors.Errorf("yaml kind type error, kind=%v data=%v", value.Kind, val) } } diff --git a/utils/utils.go b/utils/utils.go index 721ac433..12830227 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -3,7 +3,7 @@ package utils import ( "io" - "github.com/pubgo/funk/log" + "github.com/pubgo/funk/v2/log" ) func SafeClose(closer io.Closer) { diff --git a/utils/vizutil/viz.go b/utils/vizutil/viz.go index 2b9da06c..da14adb8 100644 --- a/utils/vizutil/viz.go +++ b/utils/vizutil/viz.go @@ -7,7 +7,7 @@ import ( ) // Memviz 对象内存转化为graphviz -func Memviz(is ...interface{}) []byte { +func Memviz(is ...any) []byte { data := bytes.NewBuffer(nil) memviz.Map(data, is...) return data.Bytes() diff --git a/v2/result/interface.go b/v2/result/interface.go deleted file mode 100644 index 45873291..00000000 --- a/v2/result/interface.go +++ /dev/null @@ -1,26 +0,0 @@ -package result - -import "context" - -type Catchable interface { - Catch(err *error, contexts ...context.Context) bool - CatchErr(err ErrSetter, contexts ...context.Context) bool -} - -// Checkable defines types that can be checked for Ok/Error state -type Checkable interface { - IsOK() bool - IsErr() bool - GetErr() error - String() string -} - -type ErrSetter interface { - Checkable - setErrorInner() -} - -type UnWrapper[T any] interface { - Unwrap(setter *error, contexts ...context.Context) T - UnwrapErr(setter ErrSetter, contexts ...context.Context) T -} diff --git a/v2/result/result.go b/v2/result/result.go deleted file mode 100644 index 35f4766b..00000000 --- a/v2/result/result.go +++ /dev/null @@ -1,221 +0,0 @@ -package result - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/rs/zerolog" - "github.com/samber/lo" - - "github.com/pubgo/funk" - "github.com/pubgo/funk/errors" -) - -var _ Catchable = new(Result[any]) -var _ Checkable = new(Result[any]) -var _ ErrSetter = new(Result[any]) - -type Result[T any] struct { - _ [0]func() // disallow == - - v *T - err error -} - -func (r Result[T]) GetValue() (t T) { - if r.IsErr() { - return - } - - return r.getValue() -} - -func (r Result[T]) WithFn(fn func() (T, error)) Result[T] { - if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - return Result[T]{err: err} - } - - return WrapFn(fn) -} - -func (r Result[T]) WithValue(v T) Result[T] { - if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - return Result[T]{err: err} - } - - return OK(v) -} - -func (r Result[T]) ValueTo(v *T) Error { - if r.IsErr() { - return newError(errors.WrapCaller(r.getErr(), 1)) - } - - if v == nil { - return newError(errors.WrapStack(errors.New("v param is nil"))) - } - - *v = r.getValue() - return newError(nil) -} - -func (r Result[T]) Expect(format string, args ...any) T { - if r.IsErr() { - err := errors.WrapCaller(r.getErr(), 1) - errNilOrPanic(errors.Wrapf(err, format, args...)) - } - - return r.getValue() -} - -func (r Result[T]) Must() T { - if r.IsErr() { - errNilOrPanic(errors.WrapCaller(r.getErr(), 1)) - } - - return r.getValue() -} - -func (r Result[T]) Catch(setter *error, ctx ...context.Context) bool { - return catchErr(newError(r.err), nil, setter, ctx...) -} - -func (r Result[T]) CatchErr(setter ErrSetter, ctx ...context.Context) bool { - return catchErr(newError(r.err), setter, nil, ctx...) -} - -func (r Result[T]) IsErr() bool { return r.getErr() != nil } - -func (r Result[T]) IsOK() bool { return r.getErr() == nil } - -func (r Result[T]) InspectErr(fn func(error)) Result[T] { - if r.IsErr() { - fn(r.getErr()) - } - return r -} - -func (r Result[T]) Inspect(fn func(T)) Result[T] { - if r.IsOK() { - fn(r.getValue()) - } - return r -} - -func (r Result[T]) LogCtx(ctx context.Context, events ...func(e *zerolog.Event)) Result[T] { - logErr(ctx, r.err, events...) - return r -} - -func (r Result[T]) Log(events ...func(e *zerolog.Event)) Result[T] { - logErr(nil, r.err, events...) - return r -} - -func (r Result[T]) Map(fn func(T) T) Result[T] { - if r.IsOK() { - return r - } - return OK(fn(r.getValue())) -} - -func (r Result[T]) FlatMap(fn func(T) Result[T]) Result[T] { - if r.IsOK() { - return r - } - return fn(r.getValue()) -} - -func (r Result[T]) Validate(fn func(T) error) Result[T] { - if r.IsErr() { - return r - } - - err := fn(r.getValue()) - if err != nil { - return Fail[T](errors.WrapCaller(err, 1)) - } - return OK(r.getValue()) -} - -func (r Result[T]) MapErr(fn func(error) error) Result[T] { - if r.IsOK() { - return r - } - return Fail[T](fn(r.getErr())) -} - -func (r Result[T]) MapErrOr(fn func(error) Result[T]) Result[T] { - if r.IsOK() { - return r - } - return fn(r.getErr()) -} - -func (r Result[T]) GetErr() error { - if r.IsOK() { - return nil - } - - return r.getErr() -} - -func (r Result[T]) String() string { - if r.IsOK() { - return fmt.Sprintf("Ok(%v)", r.getValue()) - } - return fmt.Sprintf("Error(%v)", r.getErr()) -} - -func (r Result[T]) WithErrorf(format string, args ...any) Result[T] { - err := fmt.Errorf(format, args...) - err = errors.WrapCaller(err, 1) - return Result[T]{err: err} -} - -func (r Result[T]) WithErr(err error) Result[T] { - if err == nil { - return r - } - - err = errors.WrapCaller(err, 1) - return Result[T]{err: err} -} - -func (r Result[T]) WrapErr(err *errors.Err, tags ...errors.Tag) Result[T] { - return Result[T]{err: errors.WrapTag(errors.WrapCaller(err, 1), tags...)} -} - -func (r Result[T]) Unwrap(setter *error, contexts ...context.Context) T { - ret, err := unwrapErr(r, setter, nil, contexts...) - if err != nil { - *setter = errors.WrapCaller(err, 1) - } - return ret -} - -func (r Result[T]) UnwrapErr(setter ErrSetter, contexts ...context.Context) T { - ret, err := unwrapErr(r, nil, setter, contexts...) - if err != nil { - setError(setter, errors.WrapCaller(err, 1)) - } - return ret -} - -func (r Result[T]) MarshalJSON() ([]byte, error) { - if r.IsErr() { - return nil, errors.WrapCaller(r.err, 1) - } - - return json.Marshal(funk.FromPtr(r.v)) -} - -func (r Result[T]) getValue() T { return lo.FromPtr(r.v) } - -func (r Result[T]) getErr() error { return r.err } - -func (r Result[T]) setErrorInner() { -} diff --git a/v2/result/result_test.go b/v2/result/result_test.go deleted file mode 100644 index 0f74552c..00000000 --- a/v2/result/result_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package result_test - -import ( - "context" - "encoding/json" - "fmt" - "testing" - - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/errors" - "github.com/pubgo/funk/log" - "github.com/pubgo/funk/recovery" - "github.com/pubgo/funk/v2/result" - "github.com/pubgo/funk/v2/result/resultchecker" -) - -type hello struct { - Name string `json:"name"` -} - -func TestName(t *testing.T) { - defer recovery.DebugPrint() - ok := &hello{Name: "abc"} - okBytes := result.Wrap(json.Marshal(&ok)) - data := string(okBytes.Expect("failed to encode json data")) - t.Log(data) - if data != `{"name":"abc"}` { - t.Log(data) - t.Fatal("not match") - } -} - -func TestResultDo(t *testing.T) { - ok := result.OK(&hello{Name: "abc"}) - ok.Inspect(func(v *hello) { - assert.If(v.Name != "abc", "not match") - }).Inspect(func(v *hello) { - assert.If(v.Name != "abc", "not match") - }) - ok.InspectErr(func(err error) { - t.Log(err) - }) -} - -func TestErrOf(t *testing.T) { - var ctx = log.UpdateEventCtx(context.Background(), log.Map{"test": "ok"}) - resultchecker.RegisterErrCheck(log.RecordErr()) - - var err result.Error - if fn1().CatchErr(&err, ctx) { - errors.Debug(err.GetErr()) - } -} - -func fn1() (r result.Result[string]) { - if fn3().CatchErr(&r) { - return - } - - val := fn2().UnwrapErr(&r) - if r.IsErr() { - return - } - - return r.WithValue(val) -} - -func fn2() (r result.Result[string]) { - fn3(). - InspectErr(func(err error) { - log.Err(err).Msg("test error") - }). - CatchErr(&r) - if r.IsErr() { - return - } - - return r.WithValue("ok") -} - -func fn3() result.Error { - return result. - ErrOf(fmt.Errorf("error test, this is error")). - InspectErr(func(err error) { - log.Err(err).Msg("ddd") - }). - Log() -} diff --git a/vars/vars.go b/vars/vars.go index 123b9a13..092422f7 100644 --- a/vars/vars.go +++ b/vars/vars.go @@ -4,74 +4,82 @@ import ( "encoding/json" "expvar" "fmt" + "log/slog" "strconv" "strings" + "sync" + "time" "github.com/rs/xid" - - "github.com/pubgo/funk/assert" - "github.com/pubgo/funk/convert" - "github.com/pubgo/funk/pretty" - "github.com/pubgo/funk/recovery" + "go.uber.org/atomic" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/recovery" ) -func Float(name string) *expvar.Float { - v := expvar.Get(name) - if v == nil { - return expvar.NewFloat(name) - } - return v.(*expvar.Float) +var mux sync.Mutex + +func Bool(name string) *atomic.Bool { + return Any(name, atomic.NewBool(false)) } -func Int(name string) *expvar.Int { - v := expvar.Get(name) - if v == nil { - return expvar.NewInt(name) - } - return v.(*expvar.Int) +func Float(name string) *atomic.Float64 { + return Any(name, atomic.NewFloat64(0)) } -func String(name string) *expvar.String { - v := expvar.Get(name) - if v == nil { - return expvar.NewString(name) - } - return v.(*expvar.String) +func Int(name string) *atomic.Int64 { + return Any(name, atomic.NewInt64(0)) } -func Map(name string) *expvar.Map { - v := expvar.Get(name) - if v == nil { - return expvar.NewMap(name) - } - return v.(*expvar.Map) +func String(name string) *atomic.String { + return Any(name, atomic.NewString("")) +} + +func Duration(name string) *atomic.Duration { + return Any(name, atomic.NewDuration(0)) +} + +func Time(name string) *atomic.Time { + return Any(name, atomic.NewTime(time.Now())) +} + +func Error(name string) *atomic.Error { + return Any(name, atomic.NewError(nil)) } -var _ json.Marshaler = (*Value)(nil) +var _ json.Marshaler = (*Func)(nil) -type Value func() interface{} +type Func func() any -func (f Value) MarshalJSON() ([]byte, error) { +func (f Func) MarshalJSON() ([]byte, error) { return json.Marshal(f()) } -func (f Value) Value() interface{} { return f() } +func (f Func) Value() any { return f() } -func (f Value) String() (r string) { +func (f Func) String() (r string) { return toString(f()) } +func errToString(err error) string { + if err == nil { + return "null" + } + + return strconv.Quote(fmt.Sprintf("err:%s detail:%#v", err.Error(), err)) +} + func toString(dt any) (r string) { - var errStr = func(err any) string { - ret, err := json.Marshal(err) + jsonStr := func(data any) string { + ret, err := json.Marshal(data) if err != nil { - return strconv.Quote(pretty.SimplePrint(err)) + return errToString(err) } else { - return convert.B2S(ret) + return string(ret) } } - defer recovery.Recovery(func(err error) { r = errStr(err) }) + defer recovery.Recovery(func(err error) { r = jsonStr(err) }) switch dt := dt.(type) { case nil: @@ -80,24 +88,28 @@ func toString(dt any) (r string) { return strconv.Quote(dt) case []byte: return strconv.Quote(string(dt)) + case json.Marshaler: + return jsonStr(dt) case fmt.Stringer: return strconv.Quote(dt.String()) case error: - return strconv.Quote(fmt.Sprintf("err:%s detail:%#v", dt, dt)) + return errToString(dt) default: - return errStr(dt) + return slog.AnyValue(dt).String() } } -func Any(v any) expvar.Var { - switch v.(type) { - case nil: - return anyValue{v: nil} - case Value: - return v.(Value) - default: - return anyValue{v: v} +func Any[T any](name string, v T) T { + mux.Lock() + defer mux.Unlock() + + vv := expvar.Get(name) + if vv != nil { + return vv.(*anyValue).v.(T) } + + expvar.Publish(name, &anyValue{v: v}) + return v } var _ expvar.Var = (*anyValue)(nil) @@ -110,16 +122,13 @@ func (a anyValue) String() string { return toString(a.v) } -func Register(name string, value Value) { - defer recovery.Exit() - assert.If(Has(name), "name:%s already exists", name) - expvar.Publish(name, value) +func (a anyValue) MarshalJSON() ([]byte, error) { + return json.Marshal(a.v) } -func RegisterValue(name string, data any) { - defer recovery.Exit() +func Register(name string, value Func) { assert.If(Has(name), "name:%s already exists", name) - expvar.Publish(name, Value(func() interface{} { return data })) + expvar.Publish(name, value) } func Has(name string) bool { diff --git a/vars/z_test.go b/vars/z_test.go new file mode 100644 index 00000000..5e00a6fe --- /dev/null +++ b/vars/z_test.go @@ -0,0 +1,20 @@ +package vars_test + +import ( + "expvar" + "testing" + + "github.com/pubgo/funk/v2/assert" + "github.com/pubgo/funk/v2/recovery" + "github.com/pubgo/funk/v2/vars" +) + +func TestAny(t *testing.T) { + defer recovery.Testing(t) + name := "test-bool-var" + bb := vars.Bool(name) + assert.If(bb.Load() != false, "not match") + assert.If(vars.Bool(name).String() != "false", "not match") + vars.Bool(name).Store(true) + assert.MustEqual(expvar.Get(name).String(), "true") +} diff --git a/version/export.go b/version/export.go deleted file mode 100644 index ec2aef47..00000000 --- a/version/export.go +++ /dev/null @@ -1,21 +0,0 @@ -package version - -func CommitID() string { - return commitID -} - -func MainPath() string { - return mainPath -} - -func Version() string { - return version -} - -func BuildTime() string { - return buildTime -} - -func Project() string { - return project -} diff --git a/version/version.go b/version/version.go deleted file mode 100644 index 858709f2..00000000 --- a/version/version.go +++ /dev/null @@ -1,58 +0,0 @@ -package version - -import ( - "runtime/debug" - "strings" -) - -var mainPath string - -// git rev-parse HEAD -// git describe --always --abbrev=7 --dirty -var ( - commitID string - buildTime string -) - -// git describe --tags --abbrev=0 -// git tag --sort=committerdate | tail -n 1 -var ( - version = "v0.0.1-dev-99" - project = "project" -) - -var ( - modified bool - os string - arch string - buildTags []string -) - -func init() { - bi, ok := debug.ReadBuildInfo() - if !ok { - return - } - - mainPath = bi.Main.Path - - for i := range bi.Settings { - setting := bi.Settings[i] - switch setting.Key { - case "vcs.revision": - commitID = setting.Value - case "vcs.time": - buildTime = setting.Value - case "vcs.modified": - modified = setting.Value == "true" - case "GOOS": - os = setting.Value - case "GOARCH": - arch = setting.Value - case "-tags": - if setting.Value != "" { - buildTags = strings.Split(setting.Value, ",") - } - } - } -}