diff --git a/go.mod b/go.mod index d9f86b3..187529a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.0 require ( github.com/apolloconfig/agollo/v4 v4.4.0 - github.com/ayflying/excel2json v1.1.7 + github.com/ayflying/excel2json v1.1.8 github.com/elastic/go-elasticsearch/v8 v8.18.0 github.com/go-pay/crypto v0.0.1 github.com/go-pay/gopay v1.5.109 @@ -12,7 +12,6 @@ require ( github.com/goccy/go-json v0.10.5 github.com/gogf/gf/contrib/config/apollo/v2 v2.9.0 github.com/gogf/gf/v2 v2.9.0 - github.com/gorilla/websocket v1.5.3 github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230 github.com/minio/minio-go/v7 v7.0.91 github.com/prometheus/client_golang v1.22.0 @@ -45,6 +44,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/klauspost/compress v1.18.0 // indirect diff --git a/go.sum b/go.sum index 080b31d..12f0fb7 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,7 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/ayflying/excel2json v1.1.7 h1:gp4Ls6hNXd1EuT2MEiDQ6yPLaSKIFWkGyaNajMTc59c= github.com/ayflying/excel2json v1.1.7/go.mod h1:GjXYP2cDzeTgQxssQ3ba8QRa9JsScAeJMwCrZ7QTlQo= +github.com/ayflying/excel2json v1.1.8/go.mod h1:GjXYP2cDzeTgQxssQ3ba8QRa9JsScAeJMwCrZ7QTlQo= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= diff --git a/pkg/aycache/drive/file.go b/pkg/aycache/drive/file.go index 0ee115a..874c456 100644 --- a/pkg/aycache/drive/file.go +++ b/pkg/aycache/drive/file.go @@ -3,120 +3,251 @@ package drive import ( "context" "github.com/gogf/gf/v2/container/gvar" + "github.com/gogf/gf/v2/crypto/gmd5" + "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" "path" + "strconv" "strings" + "sync" "time" ) +var ( + fileIndex = "index.txt" +) + +type FileIndex struct { + File string `json:"file"` + Duration time.Duration `json:"duration"` +} +type FileData struct { + Data interface{} `json:"data"` + Time int64 `json:"time"` +} + type AdapterFile struct { FilePath string + Lock sync.Mutex } -func (a AdapterFile) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error { - arr := strings.Split(":", gconv.String(key)) - fileName := path.Join(arr...) - return gfile.PutBytes(fileName, gconv.Bytes(value)) +func (a *AdapterFile) Key2Name(key interface{}) string { + md5Str, _ := gmd5.Encrypt(key) + fileName := path.Join(md5Str[0:2], md5Str[2:4], md5Str[4:6], md5Str[16:]) + fileNameAll := path.Join(a.FilePath, fileName) + + return fileNameAll } -func (a AdapterFile) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error { +func (a *AdapterFile) AddIndex(FileName interface{}, duration time.Duration) { + var isEdit bool + + var setTime int64 + if duration == 0 { + setTime = 0 + } else { + setTime = gtime.Now().Add(duration).Unix() + } + saveArr := []string{ + gconv.String(FileName), + strconv.FormatInt(setTime, 10), + } + saveStr := strings.Join(saveArr, "|") + + gfile.ReadLines(fileIndex, func(text string) (err error) { + arr := strings.Split(text, "|") + if arr[0] == FileName { + isEdit = true + gfile.ReplaceFile(text, saveStr, fileIndex) + return + } + return + }) + + if isEdit { + return + } + + gfile.PutContentsAppend(fileIndex, saveStr+"\n") +} + +func (a *AdapterFile) DelIndex(FileName interface{}) { + //var save bool + gfile.ReadLines(fileIndex, func(text string) (err error) { + arr := strings.Split(text, "|") + if arr[0] == FileName { + //save = true + err = gfile.ReplaceFile(text, "", fileIndex) + return + } + + return + }) + +} + +func (a *AdapterFile) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (err error) { + fileNameAll := a.Key2Name(key) + var send = &FileData{ + Data: value, + Time: gtime.Now().Add(duration).Unix(), + } + err = gfile.PutBytes(fileNameAll, gjson.MustEncode(send)) + + if err != nil { + return + } + a.AddIndex(key, duration) + return +} + +func (a *AdapterFile) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) (err error) { + for k, v := range data { + //fileNameAll := a.Key2Name(k) + //var send = &FileData{ + // Data: v, + // Time: gtime.Now().Add(duration).Unix(), + //} + // + //err = gfile.PutBytes(fileNameAll, gconv.Bytes(send)) + a.Set(ctx, k, v, duration) + } + return +} + +func (a *AdapterFile) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) { + err = a.Set(ctx, key, value, duration) + return +} + +func (a *AdapterFile) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) { //TODO implement me panic("implement me") } -func (a AdapterFile) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) { +func (a *AdapterFile) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) { //TODO implement me panic("implement me") } -func (a AdapterFile) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) { +func (a *AdapterFile) Get(ctx context.Context, key interface{}) (res *gvar.Var, err error) { + var data *FileData + name := a.Key2Name(key) + if !gfile.IsFile(name) { + return + } + file := gfile.GetBytes(name) + gjson.DecodeTo(file, &data) + if data.Time < time.Now().Unix() { + a.Remove(ctx, key) + return + } + res = gvar.New(data.Data) + return +} + +func (a *AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) { + a.Set(ctx, key, value, duration) + result, err = a.Get(ctx, key) + return +} + +func (a *AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) { + value := f + a.Set(ctx, key, value, duration) + result, err = a.Get(ctx, key) + return +} + +func (a *AdapterFile) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) { + a.Lock.Lock() + defer a.Lock.Unlock() + result, err = a.GetOrSetFunc(ctx, key, f, duration) + return +} + +func (a *AdapterFile) Contains(ctx context.Context, key interface{}) (bool, error) { + return gfile.IsFile(a.FilePath), nil +} + +func (a *AdapterFile) Size(ctx context.Context) (size int, err error) { + size = int(gfile.Size(a.FilePath)) + return +} + +func (a *AdapterFile) Data(ctx context.Context) (data map[interface{}]interface{}, err error) { //TODO implement me panic("implement me") } -func (a AdapterFile) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) { +func (a *AdapterFile) Keys(ctx context.Context) (keys []interface{}, err error) { + gfile.ReadLines(fileIndex, func(text string) (err error) { + + return + }) + + return +} + +func (a *AdapterFile) Values(ctx context.Context) (values []interface{}, err error) { //TODO implement me panic("implement me") } -func (a AdapterFile) Get(ctx context.Context, key interface{}) (*gvar.Var, error) { +func (a *AdapterFile) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) { + fileNameAll := a.Key2Name(key) + getFile := gfile.GetBytes(fileNameAll) + var data *FileData + gconv.Scan(getFile, &data) + oldValue.Set(data.Data) + + var send = &FileData{ + Data: value, + Time: data.Time, + } + + err = gfile.PutBytes(fileNameAll, gconv.Bytes(send)) + if err != nil { + return + } + a.AddIndex(key, time.Duration(data.Time-gtime.Now().Unix())) + return +} + +func (a *AdapterFile) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) { //TODO implement me panic("implement me") } -func (a AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) { +func (a *AdapterFile) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) { //TODO implement me panic("implement me") } -func (a AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) { - //TODO implement me - panic("implement me") +func (a *AdapterFile) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) { + for _, v := range keys { + fileNameAll := a.Key2Name(v) + lastValue, err = a.Get(ctx, fileNameAll) + err = gfile.RemoveFile(fileNameAll) + //删除索引文件 + a.DelIndex(v) + } + return nil, nil } -func (a AdapterFile) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) { - //TODO implement me - panic("implement me") +func (a *AdapterFile) Clear(ctx context.Context) error { + return gfile.RemoveAll(a.FilePath) } -func (a AdapterFile) Contains(ctx context.Context, key interface{}) (bool, error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Size(ctx context.Context) (size int, err error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Data(ctx context.Context) (data map[interface{}]interface{}, err error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Keys(ctx context.Context) (keys []interface{}, err error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Values(ctx context.Context) (values []interface{}, err error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Clear(ctx context.Context) error { - //TODO implement me - panic("implement me") -} - -func (a AdapterFile) Close(ctx context.Context) error { - //TODO implement me - panic("implement me") +func (a *AdapterFile) Close(ctx context.Context) error { + return nil } func NewAdapterFile(filePath string) gcache.Adapter { + fileIndex = path.Join(filePath, fileIndex) return &AdapterFile{ FilePath: filePath, }