diff --git a/server/internal/adapter/publicapi/asset.go b/server/internal/adapter/publicapi/asset.go index 7a4f1ceaac..8813c89f81 100644 --- a/server/internal/adapter/publicapi/asset.go +++ b/server/internal/adapter/publicapi/asset.go @@ -49,7 +49,7 @@ func (c *Controller) GetAssets(ctx context.Context, pKey string, p ListParam) (L return ListResult[Asset]{}, rerror.ErrNotFound } - a, pi, err := c.usecases.Asset.FindByProject(ctx, prj.ID(), interfaces.AssetFilter{ + al, pi, err := c.usecases.Asset.FindByProject(ctx, prj.ID(), interfaces.AssetFilter{ Sort: nil, Keyword: nil, Pagination: p.Pagination, @@ -62,16 +62,12 @@ func (c *Controller) GetAssets(ctx context.Context, pKey string, p ListParam) (L return ListResult[Asset]{}, err } - res, err := util.TryMap(a, func(i *asset.Asset) (Asset, error) { - f, err := c.usecases.Asset.FindFileByID(ctx, i.ID(), nil) - if err != nil { - return Asset{}, err - } - return NewAsset(i, f, c.assetUrlResolver), nil - }) + fileMap, err := c.usecases.Asset.FindFilesByIDs(ctx, util.Map(al, func(a *asset.Asset) id.AssetID { return a.ID() }), nil) if err != nil { return ListResult[Asset]{}, err } - return NewListResult(res, pi, p.Pagination), nil + return NewListResult(util.Map(al, func(a *asset.Asset) Asset { + return NewAsset(a, fileMap[a.ID()], c.assetUrlResolver) + }), pi, p.Pagination), nil } diff --git a/server/internal/infrastructure/memory/asset_file.go b/server/internal/infrastructure/memory/asset_file.go index 28c2967ecf..762b893483 100644 --- a/server/internal/infrastructure/memory/asset_file.go +++ b/server/internal/infrastructure/memory/asset_file.go @@ -41,6 +41,32 @@ func (r *AssetFile) FindByID(ctx context.Context, id id.AssetID) (*asset.File, e return rerror.ErrIfNil(f, rerror.ErrNotFound) } +func (r *AssetFile) FindByIDs(ctx context.Context, ids id.AssetIDList) (map[id.AssetID]*asset.File, error) { + if r.err != nil { + return nil, r.err + } + + filesMap := make(map[id.AssetID]*asset.File) + for _, id := range ids { + f := r.data.Find(func(key asset.ID, value *asset.File) bool { + return key == id + }).Clone() + fs := r.files.Find(func(key asset.ID, value []*asset.File) bool { + return key == id + }) + if len(fs) > 0 { + f.SetFiles(fs) + } + if f == nil { + return nil, rerror.ErrNotFound + } + filesMap[id] = f + } + + return filesMap, nil +} + + func (r *AssetFile) Save(ctx context.Context, id id.AssetID, file *asset.File) error { if r.err != nil { return r.err diff --git a/server/internal/infrastructure/mongo/asset_file.go b/server/internal/infrastructure/mongo/asset_file.go index ddf5c532db..48eb1992fd 100644 --- a/server/internal/infrastructure/mongo/asset_file.go +++ b/server/internal/infrastructure/mongo/asset_file.go @@ -74,6 +74,52 @@ func (r *AssetFile) FindByID(ctx context.Context, id id.AssetID) (*asset.File, e return f, nil } +func (r *AssetFile) FindByIDs(ctx context.Context, ids id.AssetIDList) (map[id.AssetID]*asset.File, error) { + filesMap := make(map[id.AssetID]*asset.File) + + c := &mongodoc.AssetAndFileConsumer{} + if err := r.client.Find(ctx, bson.M{ + "id": bson.M{"$in": ids.Strings()}, + }, c, options.Find().SetProjection(bson.M{ + "id": 1, + "file": 1, + "flatfiles": 1, + })); err != nil { + return nil, err + } + + for _, result := range c.Result { + assetID := result.ID + f := result.File.Model() + if f == nil { + return nil, rerror.ErrNotFound + } + + if result.FlatFiles { + var afc mongodoc.AssetFilesConsumer + if err := r.assetFilesClient.Find(ctx, bson.M{ + "assetid": assetID, + }, &afc, options.Find().SetSort(bson.D{ + {Key: "page", Value: 1}, + })); err != nil { + return nil, err + } + files := afc.Result().Model() + f.SetFiles(files) + } else if len(f.Children()) > 0 { + f.SetFiles(f.FlattenChildren()) + } + + aId, err := id.AssetIDFrom(assetID) + if err != nil { + return nil, err + } + filesMap[aId] = f + } + + return filesMap, nil +} + func (r *AssetFile) Save(ctx context.Context, id id.AssetID, file *asset.File) error { doc := mongodoc.NewFile(file) _, err := r.client.Client().UpdateOne(ctx, bson.M{ diff --git a/server/internal/usecase/interactor/asset.go b/server/internal/usecase/interactor/asset.go index 0551fe30c2..79815b6085 100644 --- a/server/internal/usecase/interactor/asset.go +++ b/server/internal/usecase/interactor/asset.go @@ -69,6 +69,20 @@ func (i *Asset) FindFileByID(ctx context.Context, aid id.AssetID, _ *usecase.Ope return files, nil } +func (i *Asset) FindFilesByIDs(ctx context.Context, ids id.AssetIDList, _ *usecase.Operator) (map[id.AssetID]*asset.File, error) { + _, err := i.repos.Asset.FindByIDs(ctx, ids) + if err != nil { + return nil, err + } + + files, err := i.repos.AssetFile.FindByIDs(ctx, ids) + if err != nil { + return nil, err + } + + return files, nil +} + func (i *Asset) DownloadByID(ctx context.Context, aid id.AssetID, _ *usecase.Operator) (io.ReadCloser, error) { a, err := i.repos.Asset.FindByID(ctx, aid) if err != nil { diff --git a/server/internal/usecase/interfaces/asset.go b/server/internal/usecase/interfaces/asset.go index 7fafca5e55..958258306e 100644 --- a/server/internal/usecase/interfaces/asset.go +++ b/server/internal/usecase/interfaces/asset.go @@ -61,6 +61,7 @@ type Asset interface { FindByIDs(context.Context, []id.AssetID, *usecase.Operator) (asset.List, error) FindByProject(context.Context, id.ProjectID, AssetFilter, *usecase.Operator) (asset.List, *usecasex.PageInfo, error) FindFileByID(context.Context, id.AssetID, *usecase.Operator) (*asset.File, error) + FindFilesByIDs(context.Context, id.AssetIDList, *usecase.Operator) (map[id.AssetID]*asset.File, error) DownloadByID(context.Context, id.AssetID, *usecase.Operator) (io.ReadCloser, error) GetURL(*asset.Asset) string Create(context.Context, CreateAssetParam, *usecase.Operator) (*asset.Asset, *asset.File, error) diff --git a/server/internal/usecase/repo/asset.go b/server/internal/usecase/repo/asset.go index 67cb1275e0..a7bc23b2dd 100644 --- a/server/internal/usecase/repo/asset.go +++ b/server/internal/usecase/repo/asset.go @@ -25,6 +25,7 @@ type Asset interface { type AssetFile interface { FindByID(context.Context, id.AssetID) (*asset.File, error) + FindByIDs(context.Context, id.AssetIDList) (map[id.AssetID]*asset.File, error) Save(context.Context, id.AssetID, *asset.File) error SaveFlat(context.Context, id.AssetID, *asset.File, []*asset.File) error }