diff --git a/dao/file_dao.go b/dao/file_dao.go index fa40c35..2182ca6 100644 --- a/dao/file_dao.go +++ b/dao/file_dao.go @@ -7,9 +7,17 @@ import ( "oss/model/entity" ) -var File = &file{} +var File = &file{ + NoCache: false, +} -type file struct{} +type file struct { + NoCache bool +} + +func (d *file) SetNoCache() { + File.NoCache = true +} // Insert 插入 func (d *file) Insert(ctx context.Context, entity *entity.File) (err error) { diff --git a/dao/tenant_oss_total.go b/dao/tenant_oss_total.go index 1d04c0d..388f9ff 100644 --- a/dao/tenant_oss_total.go +++ b/dao/tenant_oss_total.go @@ -9,9 +9,17 @@ import ( "oss/model/entity" ) -var TenantOssTotal = &tenantOssTotal{} +var TenantOssTotal = &tenantOssTotal{ + NoCache: false, +} -type tenantOssTotal struct{} +type tenantOssTotal struct { + NoCache bool +} + +func (d *tenantOssTotal) SetNoCache() { + TenantOssTotal.NoCache = true +} // Insert 插入 func (d *tenantOssTotal) Insert(ctx context.Context, entity []interface{}) (err error) { @@ -20,12 +28,12 @@ func (d *tenantOssTotal) Insert(ctx context.Context, entity []interface{}) (err } // SaveOrUpdate 增加或更新 -func (d *tenantOssTotal) SaveOrUpdate(ctx context.Context, filterData []*entity.TenantOssTotal, updateData []*entity.TenantOssTotal) (err error) { +func (d *tenantOssTotal) SaveOrUpdate(ctx context.Context, updateData []*entity.TenantOssTotal) (err error) { if !g.IsEmpty(updateData) { var filter, update []bson.M - for i, v := range filterData { + for _, v := range updateData { filter = append(filter, bson.M{"tenantId": v.TenantId}) - update = append(update, bson.M{"$set": bson.M{"usedOssSize": updateData[i].UsedOssSize, "totalOssSize": updateData[i].TotalOssSize}}) + update = append(update, bson.M{"$set": bson.M{"usedOssSize": v.UsedOssSize, "totalOssSize": v.TotalOssSize}}) } _, err = mongo.SaveOrUpdate(ctx, filter, update, consts.TenantOssTotalCollection) } @@ -35,6 +43,6 @@ func (d *tenantOssTotal) SaveOrUpdate(ctx context.Context, filterData []*entity. func (d *tenantOssTotal) GetOneByTenantId(ctx context.Context, tenantId string) (e *entity.TenantOssTotal, err error) { filter := bson.M{"tenantId": tenantId} e = &entity.TenantOssTotal{} - err = mongo.FindOne(ctx, filter, e, consts.TenantOssTotalCollection) + err = mongo.FindOne(ctx, d.NoCache, filter, e, consts.TenantOssTotalCollection) return } diff --git a/model/entity/file.go b/model/entity/file.go index df6c9cc..d9f8bf0 100644 --- a/model/entity/file.go +++ b/model/entity/file.go @@ -10,7 +10,7 @@ type File struct { do.MongoBaseDO `bson:",inline"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted // 基础信息 FileURL string `bson:"fileURL" json:"fileURL"` // 图URL - FileSize int64 `bson:"fileSize" json:"fileSize"` + FileSize byte `bson:"fileSize" json:"fileSize"` } // CollectionName 存储集合名称 diff --git a/service/file_service.go b/service/file_service.go index eb94f5b..dde2055 100644 --- a/service/file_service.go +++ b/service/file_service.go @@ -22,79 +22,68 @@ type file struct{} var File = new(file) func (f *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto.UploadFileRes, err error) { - tenantId := "" - fileSize := req.File.Size + fileSize := gconv.Byte(req.File.Size) totalFileSize := int64(0) // 获取租户id user, err := mongo.GetTenantInfo(ctx) if err != nil { return } + tenantId := gconv.String(user.TenantId) // 获取redis-租户存储容量总数key tenantOssTotalKey := fmt.Sprintf(consts.TenantOssTotalKey, gconv.String(user.TenantId)) // 获取redis-租户存储-锁key fileLockKey := fmt.Sprintf(consts.FileLockKey, gconv.String(user.TenantId)) - i := 0 -LOCK: - if ok, err := redis.RedisClient.SetNX(ctx, fileLockKey, fileSize); !ok || err != nil { - // 获取锁失败,需要重试 - if i < 5 { - i++ - time.Sleep(5 * time.Millisecond) - goto LOCK - } - } - // 设置redis-租户存储-锁key超时时间1分钟 - err = redis.RedisClient.SetEX(ctx, fileLockKey, fileSize, gconv.Int64(time.Minute*1)) - if err != nil { - return nil, err - } - // 获取redis-租户存储容量总数 - get, err := redis.RedisClient.Get(ctx, tenantOssTotalKey) - if err != nil { - return nil, err - } - tenantOssTotalEntity := &entity.TenantOssTotal{} - if g.IsEmpty(get) { - //查询数据库-获取租户存储容量总数 - getByTenantIdReq := &dto.GetByTenantIdReq{ - TenantId: gconv.String(user.TenantId), - } - tenantOssTotal, err := TenantOssTotal.GetOneByTenantId(ctx, getByTenantIdReq) + + success, err := redis.Lock(ctx, fileLockKey, gconv.Int64(time.Minute*1), func(ctx context.Context) error { + // 获取redis-租户存储容量总数 + get, err := redis.RedisClient.Get(ctx, tenantOssTotalKey) if err != nil { - return nil, err + return err } - if g.IsEmpty(tenantOssTotal) { - tenantOssTotalEntity.TenantId = user.TenantId - tenantOssTotalEntity.UsedOssSize = int64(0) - tenantOssTotalEntity.TotalOssSize = g.Cfg().MustGet(ctx, "oss.capacitySize").Int64() + tenantOssTotalEntity := &entity.TenantOssTotal{} + if g.IsEmpty(get) { + //查询数据库-获取租户存储容量总数 + getByTenantIdReq := &dto.GetByTenantIdReq{ + TenantId: gconv.String(user.TenantId), + } + tenantOssTotal, err := TenantOssTotal.GetOneByTenantId(ctx, getByTenantIdReq) + if err != nil { + return err + } + if tenantOssTotal.Id.IsZero() { + tenantOssTotalEntity.TenantId = user.TenantId + tenantOssTotalEntity.UsedOssSize = int64(0) + tenantOssTotalEntity.TotalOssSize = g.Cfg().MustGet(ctx, "oss.capacitySize").Int64() + } else { + tenantOssTotalEntity = tenantOssTotal.TenantOssTotal + } } else { - tenantOssTotalEntity = tenantOssTotal.TenantOssTotal + // 反序列化-redis获取租户存储容量总数 + err = gconv.Struct(get, tenantOssTotalEntity) + if err != nil { + return err + } } - } else { - // 反序列化-redis获取租户存储容量总数 - err = gconv.Struct(get, tenantOssTotalEntity) + tenantId = gconv.String(tenantOssTotalEntity.TenantId) + fileSize = gconv.Byte(tenantOssTotalEntity.UsedOssSize) + fileSize + totalFileSize = tenantOssTotalEntity.TotalOssSize + // 设置redis-租户存储容量总数 + tenantOssTotalKeyMap := map[string]interface{}{"tenantId": tenantId, "UsedOssSize": fileSize, "TotalOssSize": totalFileSize} + // 修改redis-租户存储容量总数 超时时间10分钟 + err = redis.RedisClient.SetEX(ctx, tenantOssTotalKey, tenantOssTotalKeyMap, gconv.Int64(time.Minute*10)) if err != nil { - return nil, err + return err } - } - tenantId = gconv.String(tenantOssTotalEntity.TenantId) - fileSize = tenantOssTotalEntity.UsedOssSize + fileSize - totalFileSize = tenantOssTotalEntity.TotalOssSize - // 设置redis-租户存储容量总数 - tenantOssTotalKeyMap := map[string]interface{}{"tenantId": tenantId, "UsedOssSize": fileSize, "TotalOssSize": totalFileSize} - // 修改redis-租户存储容量总数 超时时间10分钟 - err = redis.RedisClient.SetEX(ctx, tenantOssTotalKey, tenantOssTotalKeyMap, gconv.Int64(time.Minute*10)) + if fileSize > gconv.Byte(totalFileSize) { + return gerror.New("存储服务内存不足") + } + return nil + }) if err != nil { return nil, err } - if fileSize < totalFileSize { - // 删除redis-租户存储-锁key - _, err = redis.RedisClient.Del(ctx, fileLockKey) - if err != nil { - return nil, err - } - } else { + if !success { return nil, gerror.New("存储服务内存不足") } // 上传图片 diff --git a/service/tenant_oss_total_service.go b/service/tenant_oss_total_service.go index 7bd7fec..00e0686 100644 --- a/service/tenant_oss_total_service.go +++ b/service/tenant_oss_total_service.go @@ -2,6 +2,7 @@ package service import ( "context" + "gitee.com/red-future---jilin-g/common/redis" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" "oss/consts" @@ -27,12 +28,11 @@ func (s *tenantOssTotal) GetOneByTenantId(ctx context.Context, req *dto.GetByTen func (s *tenantOssTotal) UpdateUsedOssSize(ctx context.Context) (err error) { // 使用 Keys 取出所有key - keys, err := g.Redis().Keys(ctx, consts.OssTotalKey) + keys, err := redis.RedisClient.Keys(ctx, consts.OssTotalKey) if err != nil { return } updateData := make([]*entity.TenantOssTotal, 0) - filterData := make([]*entity.TenantOssTotal, 0) for _, key := range keys { get, err := g.Redis().Get(ctx, key) if err != nil { @@ -44,13 +44,10 @@ func (s *tenantOssTotal) UpdateUsedOssSize(ctx context.Context) (err error) { return err } updateData = append(updateData, e) - totalOssSize := &entity.TenantOssTotal{} - totalOssSize.TenantId = e.TenantId - filterData = append(filterData, totalOssSize) } // 更新数据库 - err = dao.TenantOssTotal.SaveOrUpdate(ctx, filterData, updateData) + err = dao.TenantOssTotal.SaveOrUpdate(ctx, updateData) if err != nil { return err }