| @@ -39,14 +39,14 @@ func (s *ObjectService) ListByPath(ctx *gin.Context) { | |||||
| return | return | ||||
| } | } | ||||
| objs, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, req.IsPrefix) | |||||
| coms, objs, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, req.IsPrefix, req.NoRecursive) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warnf("listing objects: %s", err.Error()) | log.Warnf("listing objects: %s", err.Error()) | ||||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, fmt.Sprintf("listing objects: %v", err))) | ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, fmt.Sprintf("listing objects: %v", err))) | ||||
| return | return | ||||
| } | } | ||||
| ctx.JSON(http.StatusOK, OK(cdsapi.ObjectListByPathResp{Objects: objs})) | |||||
| ctx.JSON(http.StatusOK, OK(cdsapi.ObjectListByPathResp{CommonPrefixes: coms, Objects: objs})) | |||||
| } | } | ||||
| func (s *ObjectService) ListByIDs(ctx *gin.Context) { | func (s *ObjectService) ListByIDs(ctx *gin.Context) { | ||||
| @@ -191,7 +191,7 @@ func (s *ObjectService) DownloadByPath(ctx *gin.Context) { | |||||
| return | return | ||||
| } | } | ||||
| obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false) | |||||
| _, obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false, false) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warnf("getting object by path: %s", err.Error()) | log.Warnf("getting object by path: %s", err.Error()) | ||||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | ||||
| @@ -266,7 +266,7 @@ func (s *ObjectService) UpdateInfoByPath(ctx *gin.Context) { | |||||
| return | return | ||||
| } | } | ||||
| obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, true) | |||||
| _, obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, true, false) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warnf("getting object by path: %s", err.Error()) | log.Warnf("getting object by path: %s", err.Error()) | ||||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | ||||
| @@ -343,7 +343,7 @@ func (s *ObjectService) DeleteByPath(ctx *gin.Context) { | |||||
| return | return | ||||
| } | } | ||||
| obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false) | |||||
| _, obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false, false) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warnf("getting object by path: %s", err.Error()) | log.Warnf("getting object by path: %s", err.Error()) | ||||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | ||||
| @@ -22,19 +22,19 @@ func (svc *Service) ObjectSvc() *ObjectService { | |||||
| return &ObjectService{Service: svc} | return &ObjectService{Service: svc} | ||||
| } | } | ||||
| func (svc *ObjectService) GetByPath(userID cdssdk.UserID, pkgID cdssdk.PackageID, path string, isPrefix bool) ([]cdssdk.Object, error) { | |||||
| func (svc *ObjectService) GetByPath(userID cdssdk.UserID, pkgID cdssdk.PackageID, path string, isPrefix bool, noRecursive bool) ([]string, []cdssdk.Object, error) { | |||||
| coorCli, err := stgglb.CoordinatorMQPool.Acquire() | coorCli, err := stgglb.CoordinatorMQPool.Acquire() | ||||
| if err != nil { | if err != nil { | ||||
| return nil, fmt.Errorf("new coordinator client: %w", err) | |||||
| return nil, nil, fmt.Errorf("new coordinator client: %w", err) | |||||
| } | } | ||||
| defer stgglb.CoordinatorMQPool.Release(coorCli) | defer stgglb.CoordinatorMQPool.Release(coorCli) | ||||
| listResp, err := coorCli.GetObjectsByPath(coormq.ReqGetObjectsByPath(userID, pkgID, path, isPrefix)) | |||||
| listResp, err := coorCli.GetObjectsByPath(coormq.ReqGetObjectsByPath(userID, pkgID, path, isPrefix, noRecursive)) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, fmt.Errorf("requsting to coodinator: %w", err) | |||||
| return nil, nil, fmt.Errorf("requsting to coodinator: %w", err) | |||||
| } | } | ||||
| return listResp.Objects, nil | |||||
| return listResp.CommonPrefixes, listResp.Objects, nil | |||||
| } | } | ||||
| func (svc *ObjectService) GetByIDs(userID cdssdk.UserID, objectIDs []cdssdk.ObjectID) ([]*cdssdk.Object, error) { | func (svc *ObjectService) GetByIDs(userID cdssdk.UserID, objectIDs []cdssdk.ObjectID) ([]*cdssdk.Object, error) { | ||||
| @@ -2,6 +2,7 @@ package db2 | |||||
| import ( | import ( | ||||
| "fmt" | "fmt" | ||||
| "strings" | |||||
| "time" | "time" | ||||
| "gorm.io/gorm/clause" | "gorm.io/gorm/clause" | ||||
| @@ -38,6 +39,44 @@ func (db *ObjectDB) GetWithPathPrefix(ctx SQLContext, packageID cdssdk.PackageID | |||||
| return ret, err | return ret, err | ||||
| } | } | ||||
| func (db *ObjectDB) GetCommonPrefixes(ctx SQLContext, packageID cdssdk.PackageID, pathPrefix string) ([]string, error) { | |||||
| var ret []string | |||||
| sepCnt := strings.Count(pathPrefix, cdssdk.ObjectPathSeparator) + 1 | |||||
| prefixStatm := fmt.Sprintf("Substring_Index(Path, '%s', %d)", cdssdk.ObjectPathSeparator, sepCnt) | |||||
| err := ctx.Table("Object").Select(prefixStatm+" as Prefix"). | |||||
| Where("PackageID = ?", packageID). | |||||
| Where("Path like ?", pathPrefix+"%"). | |||||
| Where(prefixStatm + " <> Path"). | |||||
| Group("Prefix").Find(&ret).Error | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| for i := range ret { | |||||
| ret[i] = ret[i] + cdssdk.ObjectPathSeparator | |||||
| } | |||||
| return ret, nil | |||||
| } | |||||
| func (db *ObjectDB) GetDirectChildren(ctx SQLContext, packageID cdssdk.PackageID, pathPrefix string) ([]cdssdk.Object, error) { | |||||
| var ret []cdssdk.Object | |||||
| sepCnt := strings.Count(pathPrefix, cdssdk.ObjectPathSeparator) + 1 | |||||
| prefixStatm := fmt.Sprintf("Substring_Index(Path, '%s', %d)", cdssdk.ObjectPathSeparator, sepCnt) | |||||
| err := ctx.Table("Object"). | |||||
| Where("PackageID = ?", packageID). | |||||
| Where("Path like ?", pathPrefix+"%"). | |||||
| Where(prefixStatm + " = Path"). | |||||
| Find(&ret).Error | |||||
| return ret, err | |||||
| } | |||||
| func (db *ObjectDB) BatchTestObjectID(ctx SQLContext, objectIDs []cdssdk.ObjectID) (map[cdssdk.ObjectID]bool, error) { | func (db *ObjectDB) BatchTestObjectID(ctx SQLContext, objectIDs []cdssdk.ObjectID) (map[cdssdk.ObjectID]bool, error) { | ||||
| if len(objectIDs) == 0 { | if len(objectIDs) == 0 { | ||||
| return make(map[cdssdk.ObjectID]bool), nil | return make(map[cdssdk.ObjectID]bool), nil | ||||
| @@ -67,27 +67,31 @@ var _ = Register(Service.GetObjectsByPath) | |||||
| type GetObjectsByPath struct { | type GetObjectsByPath struct { | ||||
| mq.MessageBodyBase | mq.MessageBodyBase | ||||
| UserID cdssdk.UserID `json:"userID"` | |||||
| PackageID cdssdk.PackageID `json:"packageID"` | |||||
| Path string `json:"path"` | |||||
| IsPrefix bool `json:"isPrefix"` | |||||
| UserID cdssdk.UserID `json:"userID"` | |||||
| PackageID cdssdk.PackageID `json:"packageID"` | |||||
| Path string `json:"path"` | |||||
| IsPrefix bool `json:"isPrefix"` | |||||
| NoRecursive bool `json:"noRecursive"` | |||||
| } | } | ||||
| type GetObjectsByPathResp struct { | type GetObjectsByPathResp struct { | ||||
| mq.MessageBodyBase | mq.MessageBodyBase | ||||
| Objects []model.Object `json:"objects"` | |||||
| CommonPrefixes []string `json:"commonPrefixes"` | |||||
| Objects []model.Object `json:"objects"` | |||||
| } | } | ||||
| func ReqGetObjectsByPath(userID cdssdk.UserID, packageID cdssdk.PackageID, path string, isPrefix bool) *GetObjectsByPath { | |||||
| func ReqGetObjectsByPath(userID cdssdk.UserID, packageID cdssdk.PackageID, path string, isPrefix bool, noRecursive bool) *GetObjectsByPath { | |||||
| return &GetObjectsByPath{ | return &GetObjectsByPath{ | ||||
| UserID: userID, | |||||
| PackageID: packageID, | |||||
| Path: path, | |||||
| IsPrefix: isPrefix, | |||||
| UserID: userID, | |||||
| PackageID: packageID, | |||||
| Path: path, | |||||
| IsPrefix: isPrefix, | |||||
| NoRecursive: noRecursive, | |||||
| } | } | ||||
| } | } | ||||
| func RespGetObjectsByPath(objects []model.Object) *GetObjectsByPathResp { | |||||
| func RespGetObjectsByPath(commonPrefixes []string, objects []model.Object) *GetObjectsByPathResp { | |||||
| return &GetObjectsByPathResp{ | return &GetObjectsByPathResp{ | ||||
| Objects: objects, | |||||
| CommonPrefixes: commonPrefixes, | |||||
| Objects: objects, | |||||
| } | } | ||||
| } | } | ||||
| func (client *Client) GetObjectsByPath(msg *GetObjectsByPath) (*GetObjectsByPathResp, error) { | func (client *Client) GetObjectsByPath(msg *GetObjectsByPath) (*GetObjectsByPathResp, error) { | ||||
| @@ -56,6 +56,7 @@ func (svc *Service) GetObjects(msg *coormq.GetObjects) (*coormq.GetObjectsResp, | |||||
| } | } | ||||
| func (svc *Service) GetObjectsByPath(msg *coormq.GetObjectsByPath) (*coormq.GetObjectsByPathResp, *mq.CodeMessage) { | func (svc *Service) GetObjectsByPath(msg *coormq.GetObjectsByPath) (*coormq.GetObjectsByPathResp, *mq.CodeMessage) { | ||||
| var coms []string | |||||
| var objs []cdssdk.Object | var objs []cdssdk.Object | ||||
| err := svc.db2.DoTx(func(tx db2.SQLContext) error { | err := svc.db2.DoTx(func(tx db2.SQLContext) error { | ||||
| var err error | var err error | ||||
| @@ -65,16 +66,31 @@ func (svc *Service) GetObjectsByPath(msg *coormq.GetObjectsByPath) (*coormq.GetO | |||||
| return fmt.Errorf("getting package by id: %w", err) | return fmt.Errorf("getting package by id: %w", err) | ||||
| } | } | ||||
| if msg.IsPrefix { | |||||
| objs, err = svc.db2.Object().GetWithPathPrefix(tx, msg.PackageID, msg.Path) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting objects with prefix: %w", err) | |||||
| } | |||||
| } else { | |||||
| if !msg.IsPrefix { | |||||
| objs, err = svc.db2.Object().GetByPath(tx, msg.PackageID, msg.Path) | objs, err = svc.db2.Object().GetByPath(tx, msg.PackageID, msg.Path) | ||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("getting object by path: %w", err) | return fmt.Errorf("getting object by path: %w", err) | ||||
| } | } | ||||
| return nil | |||||
| } | |||||
| if !msg.NoRecursive { | |||||
| objs, err = svc.db2.Object().GetWithPathPrefix(tx, msg.PackageID, msg.Path) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting objects with prefix: %w", err) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| coms, err = svc.db2.Object().GetCommonPrefixes(tx, msg.PackageID, msg.Path) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting common prefixes: %w", err) | |||||
| } | |||||
| objs, err = svc.db2.Object().GetDirectChildren(tx, msg.PackageID, msg.Path) | |||||
| if err != nil { | |||||
| return fmt.Errorf("getting direct children: %w", err) | |||||
| } | } | ||||
| return nil | return nil | ||||
| @@ -84,7 +100,7 @@ func (svc *Service) GetObjectsByPath(msg *coormq.GetObjectsByPath) (*coormq.GetO | |||||
| return nil, mq.Failed(errorcode.OperationFailed, "get objects with prefix failed") | return nil, mq.Failed(errorcode.OperationFailed, "get objects with prefix failed") | ||||
| } | } | ||||
| return mq.ReplyOK(coormq.RespGetObjectsByPath(objs)) | |||||
| return mq.ReplyOK(coormq.RespGetObjectsByPath(coms, objs)) | |||||
| } | } | ||||
| func (svc *Service) GetPackageObjects(msg *coormq.GetPackageObjects) (*coormq.GetPackageObjectsResp, *mq.CodeMessage) { | func (svc *Service) GetPackageObjects(msg *coormq.GetPackageObjects) (*coormq.GetPackageObjectsResp, *mq.CodeMessage) { | ||||