Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5e05089
chore: set version from build info main version
kooksee Sep 7, 2025
3b2b861
feat: add embedded version string and getter
kooksee Sep 7, 2025
e947b5d
refactor(log): improve logger copying and deprecate WithEvent
kooksee Sep 7, 2025
7c0a437
fix: barry quick fix, 2025-09-08 01:09:57
kooksee Sep 7, 2025
54bd373
fix: barry quick fix, 2025-09-12 23:58:36
kooksee Sep 12, 2025
ebc6fb5
refactor(vars): replace expvar with atomic types and fix Result logic
kooksee Sep 13, 2025
a9805a0
fix: barry quick fix, 2025-09-13 09:54:55
kooksee Sep 13, 2025
7726faf
refactor: remove deprecated Result function
kooksee Sep 13, 2025
0a8a1b6
chore: quick update fix/version at 2025-09-15 23:52:18
kooksee Sep 13, 2025
5030e67
chore: quick update fix/version at 2025-09-16 18:31:37
kooksee Sep 13, 2025
b606183
fix: barry quick fix, 2025-09-16 20:42:29
kooksee Sep 16, 2025
82d51f9
fix: barry quick fix, 2025-09-16 20:51:06
kooksee Sep 16, 2025
4aee6c0
chore: quick update fix/version at 2025-09-16 22:00:15
kooksee Sep 16, 2025
5921f06
chore: quick update fix/version at 2025-09-17 17:07:01
kooksee Sep 16, 2025
7c14e8e
Merge branch 'fix/version' of github.com:pubgo/funk into fix/version
kooksee Sep 17, 2025
4781f16
chore: quick update fix/version at 2025-09-17 22:36:02
kooksee Sep 17, 2025
42e184c
chore: quick update fix/version at 2025-09-18 14:28:25
kooksee Sep 17, 2025
bc28ade
Merge branch 'fix/version' of github.com:pubgo/funk into fix/version
kooksee Sep 18, 2025
60706fd
chore: quick update fix/version at 2025-09-19 20:56:03
kooksee Sep 18, 2025
47c1cd2
chore: quick update fix/version at 2025-09-22 11:25:30
kooksee Sep 18, 2025
5f3032e
chore: quick update fix/version at 2025-09-22 11:32:08
kooksee Sep 22, 2025
db141c1
chore: quick update fix/version at 2025-09-23 13:34:47
kooksee Sep 22, 2025
34a5ee7
Merge branch 'fix/version' of github.com:pubgo/funk into fix/version
kooksee Sep 23, 2025
83b32e5
chore: quick update fix/version at 2025-09-23 23:13:48
kooksee Sep 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v0.5.69
13 changes: 11 additions & 2 deletions assert/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@ 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{}) {
if b {
must(fmt.Errorf(format, a...))
}
}

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"))
Comment on lines +18 to +20

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message "a,b not equal" is not very descriptive. When an equality check fails, it's very helpful for debugging to see the difference between the two values. The cmp.Diff function is great for this. Also, the pp.Println calls print to standard output, but their output is not part of the error that gets logged or panicked. Including the diff in the error message would make debugging much easier.

Suggested change
pp.Println("a: ", a)
pp.Println("b: ", b)
must(fmt.Errorf("a,b not equal"))
must(fmt.Errorf("a,b not equal (-a +b):\n%s", cmp.Diff(a, b)))

}
}

func If(b bool, format string, a ...interface{}) {
if b {
must(fmt.Errorf(format, a...))
Expand Down
4 changes: 0 additions & 4 deletions assert/assert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ import (
"github.com/pubgo/funk/recovery"
)

func init() {
assert.EnablePrintStack = true
}

func TestCheckNil(t *testing.T) {
var a *int

Expand Down
12 changes: 6 additions & 6 deletions assert/must.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ 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
Expand All @@ -45,7 +45,7 @@ func Exit(err error, args ...interface{}) {
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)
}
Expand All @@ -56,7 +56,7 @@ func ExitFn(errFn func() error, args ...interface{}) {
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)
}
Expand All @@ -66,14 +66,14 @@ func ExitF(err error, msg string, args ...interface{}) {
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)
}
Expand Down
58 changes: 41 additions & 17 deletions assert/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ package assert
import (
"fmt"
"log/slog"
"reflect"
"runtime/debug"
"sync"

"github.com/pubgo/funk/stack"
"github.com/k0kubun/pp/v3"
"github.com/pubgo/funk/log/logfields"
"github.com/samber/lo"
)

func messageFromMsgAndArgs(msgAndArgs ...any) string {
Expand All @@ -17,10 +21,23 @@ 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...)
}

func logErr(err error, message string, attrs ...slog.Attr) {
if err == nil {
return
}

attrs = append(attrs,
slog.String(logfields.Module, "assert"),
slog.String(logfields.Error, err.Error()),
slog.String(logfields.ErrorStack, string(debug.Stack())),
slog.String(logfields.ErrorDetail, pretty().Sprint(err)),
)
slog.Error(message, lo.ToAnySlice(attrs)...)
}

func must(err error, messageArgs ...any) {
Expand All @@ -32,32 +49,39 @@ func must(err error, messageArgs ...any) {
if message == "" {
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)
debug.PrintStack()
}

panic(message)
logErr(err, message, slog.Bool("panic", true))
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")
gErr = fmt.Errorf("assert: [fn] is nil")
logErr(gErr, gErr.Error())
debug.PrintStack()
return
}

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)
}
}()

Expand Down
2 changes: 1 addition & 1 deletion async/go.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func logErr(fn interface{}, err error) {
return
}

if running.IsDebug {
if running.Debug() {
debug.PrintStack()
errors.Debug(err)
}
Expand Down
2 changes: 0 additions & 2 deletions cmds/protoc-gen-go-cloudevent/internal/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ import (

"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"
)

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
Expand Down
17 changes: 7 additions & 10 deletions component/cloudevent/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import (
"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"
"github.com/pubgo/funk/log/logfields"
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/v2/result"
"github.com/pubgo/funk/version"
"github.com/rs/zerolog"
"github.com/samber/lo"
Expand Down Expand Up @@ -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()
Expand All @@ -98,20 +99,16 @@ func (c *Client) initStream() (r error) {
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
}

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) })...)

Expand Down Expand Up @@ -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)
Expand Down
39 changes: 22 additions & 17 deletions component/cloudevent/publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ package cloudevent

import (
"context"
"fmt"
"time"

"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"
"github.com/pubgo/funk/log/logfields"
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/pubgo/funk/v2/result"
"github.com/rs/xid"
"github.com/rs/zerolog"
"github.com/samber/lo"
Expand Down Expand Up @@ -97,6 +98,7 @@ 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) {
defer result.RecoveryErr(&gErr)
var timeout = ctxutil.GetTimeout(ctx)
var now = time.Now()
var msgId = xid.New().String()
Expand Down Expand Up @@ -127,20 +129,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 := result.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 := result.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
}

Expand All @@ -159,11 +163,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 = result.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
}

Expand Down
2 changes: 1 addition & 1 deletion component/gormclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (c *Client) Ping() error {
return _db.Ping()
}

func (c *Client) Vars() vars.Value {
func (c *Client) Vars() vars.Func {
return func() interface{} {
_db, err := c.DB.DB()
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions config/aaa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
Loading