diff --git a/go.mod b/go.mod index 2ae93459..5ba0e9f3 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/google/uuid v1.1.1 github.com/gorilla/websocket v1.4.2 github.com/matchstalk/redisqueue v1.0.3 - github.com/matchstalk/utils v1.0.1 + github.com/matchstalk/go-admin-core v1.0.2 github.com/mojocn/base64Captcha v1.3.1 github.com/mssola/user_agent v0.5.2 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 436692c3..1da1cc03 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bsm/redislock v0.5.0 h1:ODM11/cbuUXQqLgZWK6XQnufaTjsBE2UcwBc2EAFNDA= github.com/bsm/redislock v0.5.0/go.mod h1:qagqKlV+xiLy26iV34Y3zRPxRcJjQYbV7pZfWFeSZ8M= github.com/casbin/casbin/v2 v2.2.2/go.mod h1:XXtYGrs/0zlOsJMeRteEdVi/FsB0ph7KgNfjoCoJUD8= github.com/casbin/casbin/v2 v2.11.2 h1:kdJ3ZMfPtz6uzKwAaW4G4NIld0U2KeHrgFcEhi40evc= @@ -111,8 +112,10 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U= github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -277,9 +280,10 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/matchstalk/go-admin-core v1.0.2 h1:u4znMtpmAn/e+vnaGb5mq1ByTAiodQFGi+0+hkCzxwY= +github.com/matchstalk/go-admin-core v1.0.2/go.mod h1:iCxDnmPHR3+d/5Q+yrdt+QBXhmWhbj7+GeHcUjD9Rn8= +github.com/matchstalk/redisqueue v1.0.3 h1:ZRrEhnvA6/YxLu2EbzdZYeQHQQYT8yZBAi1qv/USEQA= github.com/matchstalk/redisqueue v1.0.3/go.mod h1:5DZ3X4w9t+6Wv9vz9wmUt/i15gsOorGXRnqzGhBP6zI= -github.com/matchstalk/utils v1.0.1 h1:knK5JOl03yii5dAe7uCrQ4j0OClz3TnsyC8GP9IqUSY= -github.com/matchstalk/utils v1.0.1/go.mod h1:U3JISqiqi4iiKlcx+VrpFXCiKh4HRSwE1H39eu4ZYQk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -295,7 +299,6 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/goveralls v0.0.5/go.mod h1:Xg2LHi51faXLyKXwsndxiW6uxEEQT9+3sjGzzwU4xy0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -624,7 +627,6 @@ gorm.io/driver/mysql v0.3.2/go.mod h1:jC/HyPAZJ0xqfGlOqYybd8oNPMtGrkNgvwjWuKDT7f gorm.io/driver/postgres v0.2.6/go.mod h1:AsPyuhKFOplSmQwOPsycVKbe0dRxF8v18KZ7p9i8dIs= gorm.io/driver/postgres v0.2.9 h1:oMY4f4tLEUVg3eapqHFzVEplWKy1Gj1cGBEe9wJ1yWM= gorm.io/driver/postgres v0.2.9/go.mod h1:YATpayFLKALuiVXVRNbDfoEJwECHSMYzl1SmXJ2+CIg= -gorm.io/driver/sqlite v1.0.9 h1:rqOPFRPY3U5fL5AZSDVa9Np+XpkUbxLVmvpG+i1VHjg= gorm.io/driver/sqlite v1.0.9/go.mod h1:xkm8/CEmA3yc4zRd0pdCqm43BjO8Hm6avfTpxWb/7c4= gorm.io/driver/sqlserver v0.2.4 h1:AGofGL/TfzTZotzIHlaLISfxEKJpzj0ATbtXJW+ga1A= gorm.io/driver/sqlserver v0.2.4/go.mod h1:TcPfkdce5b8qlCMgyUeUdm7HQa1ZzWUuxzI+odcueLA= diff --git a/logger/context.go b/logger/context.go new file mode 100644 index 00000000..6940122d --- /dev/null +++ b/logger/context.go @@ -0,0 +1,14 @@ +package logger + +import "context" + +type loggerKey struct{} + +func FromContext(ctx context.Context) (Logger, bool) { + l, ok := ctx.Value(loggerKey{}).(Logger) + return l, ok +} + +func NewContext(ctx context.Context, l Logger) context.Context { + return context.WithValue(ctx, loggerKey{}, l) +} diff --git a/logger/default.go b/logger/default.go new file mode 100644 index 00000000..191e7f71 --- /dev/null +++ b/logger/default.go @@ -0,0 +1,185 @@ +package logger + +import ( + "context" + "fmt" + "os" + "runtime" + "sort" + "strings" + "sync" + "time" + + dlog "go-admin/tools/debug/log" +) + +func init() { + lvl, err := GetLevel(os.Getenv("MICRO_LOG_LEVEL")) + if err != nil { + lvl = InfoLevel + } + + DefaultLogger = NewHelper(NewLogger(WithLevel(lvl))) +} + +type defaultLogger struct { + sync.RWMutex + opts Options +} + +// Init(opts...) should only overwrite provided options +func (l *defaultLogger) Init(opts ...Option) error { + for _, o := range opts { + o(&l.opts) + } + return nil +} + +func (l *defaultLogger) String() string { + return "default" +} + +func (l *defaultLogger) Fields(fields map[string]interface{}) Logger { + l.Lock() + l.opts.Fields = copyFields(fields) + l.Unlock() + return l +} + +func copyFields(src map[string]interface{}) map[string]interface{} { + dst := make(map[string]interface{}, len(src)) + for k, v := range src { + dst[k] = v + } + return dst +} + +// logCallerfilePath returns a package/file:line description of the caller, +// preserving only the leaf directory name and file name. +func logCallerfilePath(loggingFilePath string) string { + // To make sure we trim the path correctly on Windows too, we + // counter-intuitively need to use '/' and *not* os.PathSeparator here, + // because the path given originates from Go stdlib, specifically + // runtime.Caller() which (as of Mar/17) returns forward slashes even on + // Windows. + // + // See https://github.com/golang/go/issues/3335 + // and https://github.com/golang/go/issues/18151 + // + // for discussion on the issue on Go side. + idx := strings.LastIndexByte(loggingFilePath, '/') + if idx == -1 { + return loggingFilePath + } + idx = strings.LastIndexByte(loggingFilePath[:idx], '/') + if idx == -1 { + return loggingFilePath + } + return loggingFilePath[idx+1:] +} + +func (l *defaultLogger) Log(level Level, v ...interface{}) { + // TODO decide does we need to write message if log level not used? + if !l.opts.Level.Enabled(level) { + return + } + + l.RLock() + fields := copyFields(l.opts.Fields) + l.RUnlock() + + fields["level"] = level.String() + + if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok { + fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line) + } + + rec := dlog.Record{ + Timestamp: time.Now(), + Message: fmt.Sprint(v...), + Metadata: make(map[string]string, len(fields)), + } + + keys := make([]string, 0, len(fields)) + for k, v := range fields { + keys = append(keys, k) + rec.Metadata[k] = fmt.Sprintf("%v", v) + } + + sort.Strings(keys) + metadata := "" + + for _, k := range keys { + metadata += fmt.Sprintf(" %s=%v", k, fields[k]) + } + + t := rec.Timestamp.Format("2006-01-02 15:04:05") + fmt.Printf("%s %s %v\n", t, metadata, rec.Message) +} + +func (l *defaultLogger) Logf(level Level, format string, v ...interface{}) { + // TODO decide does we need to write message if log level not used? + if level < l.opts.Level { + return + } + + l.RLock() + fields := copyFields(l.opts.Fields) + l.RUnlock() + + fields["level"] = level.String() + + if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok { + fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line) + } + + rec := dlog.Record{ + Timestamp: time.Now(), + Message: fmt.Sprintf(format, v...), + Metadata: make(map[string]string, len(fields)), + } + + keys := make([]string, 0, len(fields)) + for k, v := range fields { + keys = append(keys, k) + rec.Metadata[k] = fmt.Sprintf("%v", v) + } + + sort.Strings(keys) + metadata := "" + + for _, k := range keys { + metadata += fmt.Sprintf(" %s=%v", k, fields[k]) + } + + t := rec.Timestamp.Format("2006-01-02 15:04:05") + fmt.Printf("%s %s %v\n", t, metadata, rec.Message) +} + +func (l *defaultLogger) Options() Options { + // not guard against options Context values + l.RLock() + opts := l.opts + opts.Fields = copyFields(l.opts.Fields) + l.RUnlock() + return opts +} + +// NewLogger builds a new logger based on options +func NewLogger(opts ...Option) Logger { + // Default options + options := Options{ + Level: InfoLevel, + Fields: make(map[string]interface{}), + Out: os.Stderr, + CallerSkipCount: 2, + Context: context.Background(), + } + + l := &defaultLogger{opts: options} + if err := l.Init(opts...); err != nil { + l.Log(FatalLevel, err) + } + + return l +} diff --git a/logger/helper.go b/logger/helper.go new file mode 100644 index 00000000..94c2f364 --- /dev/null +++ b/logger/helper.go @@ -0,0 +1,114 @@ +package logger + +import ( + "os" +) + +type Helper struct { + Logger + fields map[string]interface{} +} + +func NewHelper(log Logger) *Helper { + return &Helper{Logger: log} +} + +func (h *Helper) Info(args ...interface{}) { + if !h.Logger.Options().Level.Enabled(InfoLevel) { + return + } + h.Logger.Fields(h.fields).Log(InfoLevel, args...) +} + +func (h *Helper) Infof(template string, args ...interface{}) { + if !h.Logger.Options().Level.Enabled(InfoLevel) { + return + } + h.Logger.Fields(h.fields).Logf(InfoLevel, template, args...) +} + +func (h *Helper) Trace(args ...interface{}) { + if !h.Logger.Options().Level.Enabled(TraceLevel) { + return + } + h.Logger.Fields(h.fields).Log(TraceLevel, args...) +} + +func (h *Helper) Tracef(template string, args ...interface{}) { + if !h.Logger.Options().Level.Enabled(TraceLevel) { + return + } + h.Logger.Fields(h.fields).Logf(TraceLevel, template, args...) +} + +func (h *Helper) Debug(args ...interface{}) { + if !h.Logger.Options().Level.Enabled(DebugLevel) { + return + } + h.Logger.Fields(h.fields).Log(DebugLevel, args...) +} + +func (h *Helper) Debugf(template string, args ...interface{}) { + if !h.Logger.Options().Level.Enabled(DebugLevel) { + return + } + h.Logger.Fields(h.fields).Logf(DebugLevel, template, args...) +} + +func (h *Helper) Warn(args ...interface{}) { + if !h.Logger.Options().Level.Enabled(WarnLevel) { + return + } + h.Logger.Fields(h.fields).Log(WarnLevel, args...) +} + +func (h *Helper) Warnf(template string, args ...interface{}) { + if !h.Logger.Options().Level.Enabled(WarnLevel) { + return + } + h.Logger.Fields(h.fields).Logf(WarnLevel, template, args...) +} + +func (h *Helper) Error(args ...interface{}) { + if !h.Logger.Options().Level.Enabled(ErrorLevel) { + return + } + h.Logger.Fields(h.fields).Log(ErrorLevel, args...) +} + +func (h *Helper) Errorf(template string, args ...interface{}) { + if !h.Logger.Options().Level.Enabled(ErrorLevel) { + return + } + h.Logger.Fields(h.fields).Logf(ErrorLevel, template, args...) +} + +func (h *Helper) Fatal(args ...interface{}) { + if !h.Logger.Options().Level.Enabled(FatalLevel) { + return + } + h.Logger.Fields(h.fields).Log(FatalLevel, args...) + os.Exit(1) +} + +func (h *Helper) Fatalf(template string, args ...interface{}) { + if !h.Logger.Options().Level.Enabled(FatalLevel) { + return + } + h.Logger.Fields(h.fields).Logf(FatalLevel, template, args...) + os.Exit(1) +} + +func (h *Helper) WithError(err error) *Helper { + fields := copyFields(h.fields) + fields["error"] = err + return &Helper{Logger: h.Logger, fields: fields} +} + +func (h *Helper) WithFields(fields map[string]interface{}) *Helper { + nfields := copyFields(fields) + for k, v := range h.fields { + nfields[k] = v + } + return &Helper{Logger: h.Logger, fields: nfields} +} diff --git a/logger/level.go b/logger/level.go new file mode 100644 index 00000000..915f0d47 --- /dev/null +++ b/logger/level.go @@ -0,0 +1,126 @@ +package logger + +import ( + "fmt" + "os" +) + +type Level int8 + +const ( + // TraceLevel level. Designates finer-grained informational events than the Debug. + TraceLevel Level = iota - 2 + // DebugLevel level. Usually only enabled when debugging. Very verbose logging. + DebugLevel + // InfoLevel is the default logging priority. + // General operational entries about what's going on inside the application. + InfoLevel + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel + // ErrorLevel level. Logs. Used for errors that should definitely be noted. + ErrorLevel + // FatalLevel level. Logs and then calls `logger.Exit(1)`. highest level of severity. + FatalLevel +) + +func (l Level) String() string { + switch l { + case TraceLevel: + return "trace" + case DebugLevel: + return "debug" + case InfoLevel: + return "info" + case WarnLevel: + return "warn" + case ErrorLevel: + return "error" + case FatalLevel: + return "fatal" + } + return "" +} + +// Enabled returns true if the given level is at or above this level. +func (l Level) Enabled(lvl Level) bool { + return lvl >= l +} + +// GetLevel converts a level string into a logger Level value. +// returns an error if the input string does not match known values. +func GetLevel(levelStr string) (Level, error) { + switch levelStr { + case TraceLevel.String(): + return TraceLevel, nil + case DebugLevel.String(): + return DebugLevel, nil + case InfoLevel.String(): + return InfoLevel, nil + case WarnLevel.String(): + return WarnLevel, nil + case ErrorLevel.String(): + return ErrorLevel, nil + case FatalLevel.String(): + return FatalLevel, nil + } + return InfoLevel, fmt.Errorf("Unknown Level String: '%s', defaulting to InfoLevel", levelStr) +} + +func Info(args ...interface{}) { + DefaultLogger.Log(InfoLevel, args...) +} + +func Infof(template string, args ...interface{}) { + DefaultLogger.Logf(InfoLevel, template, args...) +} + +func Trace(args ...interface{}) { + DefaultLogger.Log(TraceLevel, args...) +} + +func Tracef(template string, args ...interface{}) { + DefaultLogger.Logf(TraceLevel, template, args...) +} + +func Debug(args ...interface{}) { + DefaultLogger.Log(DebugLevel, args...) +} + +func Debugf(template string, args ...interface{}) { + DefaultLogger.Logf(DebugLevel, template, args...) +} + +func Warn(args ...interface{}) { + DefaultLogger.Log(WarnLevel, args...) +} + +func Warnf(template string, args ...interface{}) { + DefaultLogger.Logf(WarnLevel, template, args...) +} + +func Error(args ...interface{}) { + DefaultLogger.Log(ErrorLevel, args...) +} + +func Errorf(template string, args ...interface{}) { + DefaultLogger.Logf(ErrorLevel, template, args...) +} + +func Fatal(args ...interface{}) { + DefaultLogger.Log(FatalLevel, args...) + os.Exit(1) +} + +func Fatalf(template string, args ...interface{}) { + DefaultLogger.Logf(FatalLevel, template, args...) + os.Exit(1) +} + +// Returns true if the given level is at or lower the current logger level +func V(lvl Level, log Logger) bool { + l := DefaultLogger + if log != nil { + l = log + } + return l.Options().Level <= lvl +} diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 00000000..ad3b41a1 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,43 @@ +// Package log provides a log interface +package logger + +var ( + // Default logger + DefaultLogger Logger = NewHelper(NewLogger()) +) + +// Logger is a generic logging interface +type Logger interface { + // Init initialises options + Init(options ...Option) error + // The Logger options + Options() Options + // Fields set fields to always be logged + Fields(fields map[string]interface{}) Logger + // Log writes a log entry + Log(level Level, v ...interface{}) + // Logf writes a formatted log entry + Logf(level Level, format string, v ...interface{}) + // String returns the name of logger + String() string +} + +func Init(opts ...Option) error { + return DefaultLogger.Init(opts...) +} + +func Fields(fields map[string]interface{}) Logger { + return DefaultLogger.Fields(fields) +} + +func Log(level Level, v ...interface{}) { + DefaultLogger.Log(level, v...) +} + +func Logf(level Level, format string, v ...interface{}) { + DefaultLogger.Logf(level, format, v...) +} + +func String() string { + return DefaultLogger.String() +} diff --git a/logger/logger_test.go b/logger/logger_test.go new file mode 100644 index 00000000..f36a3a3b --- /dev/null +++ b/logger/logger_test.go @@ -0,0 +1,18 @@ +package logger + +import ( + "testing" +) + +func TestLogger(t *testing.T) { + l := NewLogger(WithLevel(TraceLevel)) + h1 := NewHelper(l).WithFields(map[string]interface{}{"key1": "val1"}) + h1.Trace("trace_msg1") + h1.Warn("warn_msg1") + + h2 := NewHelper(l).WithFields(map[string]interface{}{"key2": "val2"}) + h2.Trace("trace_msg2") + h2.Warn("warn_msg2") + + l.Fields(map[string]interface{}{"key3": "val4"}).Log(InfoLevel, "test_msg") +} diff --git a/logger/options.go b/logger/options.go new file mode 100644 index 00000000..d0a03302 --- /dev/null +++ b/logger/options.go @@ -0,0 +1,58 @@ +package logger + +import ( + "context" + "io" +) + +type Option func(*Options) + +type Options struct { + // The logging level the logger should log at. default is `InfoLevel` + Level Level + // fields to always be logged + Fields map[string]interface{} + // It's common to set this to a file, or leave it default which is `os.Stderr` + Out io.Writer + // Caller skip frame count for file:line info + CallerSkipCount int + // Alternative options + Context context.Context +} + +// WithFields set default fields for the logger +func WithFields(fields map[string]interface{}) Option { + return func(args *Options) { + args.Fields = fields + } +} + +// WithLevel set default level for the logger +func WithLevel(level Level) Option { + return func(args *Options) { + args.Level = level + } +} + +// WithOutput set default output writer for the logger +func WithOutput(out io.Writer) Option { + return func(args *Options) { + args.Out = out + } +} + +// WithCallerSkipCount set frame count to skip +func WithCallerSkipCount(c int) Option { + return func(args *Options) { + args.CallerSkipCount = c + } +} + +func SetOption(k, v interface{}) Option { + return func(o *Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, k, v) + } +} diff --git a/pkg/cache/memory.go b/pkg/cache/memory.go index ba3b038d..747748b9 100644 --- a/pkg/cache/memory.go +++ b/pkg/cache/memory.go @@ -1,7 +1,7 @@ package cache import ( - "github.com/matchstalk/utils/cache" + "github.com/matchstalk/go-admin-core/cache" ) var MemoryAdapter Adapter diff --git a/pkg/cache/memory_test.go b/pkg/cache/memory_test.go index 367e4b00..6db5bced 100644 --- a/pkg/cache/memory_test.go +++ b/pkg/cache/memory_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/matchstalk/utils/cache" + "github.com/matchstalk/go-admin-core/cache" ) func TestInitMemory(t *testing.T) { diff --git a/pkg/cache/redis.go b/pkg/cache/redis.go index cf48c0e7..232ae275 100644 --- a/pkg/cache/redis.go +++ b/pkg/cache/redis.go @@ -4,8 +4,8 @@ import ( "time" "github.com/go-redis/redis/v7" + "github.com/matchstalk/go-admin-core/cache" "github.com/matchstalk/redisqueue" - "github.com/matchstalk/utils/cache" ) var RedisAdapter Adapter diff --git a/pkg/cache/redis_test.go b/pkg/cache/redis_test.go index 9cc795a3..9459daea 100644 --- a/pkg/cache/redis_test.go +++ b/pkg/cache/redis_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/matchstalk/utils/cache" + "github.com/matchstalk/go-admin-core/cache" ) func TestInitRedis(t *testing.T) { diff --git a/pkg/cache/type.go b/pkg/cache/type.go index ce161775..ffd00204 100644 --- a/pkg/cache/type.go +++ b/pkg/cache/type.go @@ -3,7 +3,7 @@ package cache import ( "time" - "github.com/matchstalk/utils/cache" + "github.com/matchstalk/go-admin-core/cache" ) type Adapter interface { diff --git a/tools/dto.go b/tools/dto.go index cce2a9c2..3f472abf 100644 --- a/tools/dto.go +++ b/tools/dto.go @@ -3,7 +3,7 @@ package tools import ( "go-admin/tools/config" - "github.com/matchstalk/utils/search" + "github.com/matchstalk/go-admin-core/search" "gorm.io/gorm" )