github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/document/repository.go (about) 1 package document 2 3 import ( 4 "context" 5 6 "github.com/kyma-incubator/compass/components/director/pkg/pagination" 7 8 "github.com/kyma-incubator/compass/components/director/pkg/log" 9 10 "github.com/kyma-incubator/compass/components/director/pkg/resource" 11 12 "github.com/kyma-incubator/compass/components/director/internal/repo" 13 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 14 15 "github.com/pkg/errors" 16 17 "github.com/kyma-incubator/compass/components/director/internal/model" 18 ) 19 20 const documentTable = "public.documents" 21 22 var ( 23 documentColumns = []string{"id", "bundle_id", "app_id", "app_template_version_id", "title", "display_name", "description", "format", "kind", "data", "ready", "created_at", "updated_at", "deleted_at", "error"} 24 bundleIDColumn = "bundle_id" 25 orderByColumns = repo.OrderByParams{repo.NewAscOrderBy("bundle_id"), repo.NewAscOrderBy("id")} 26 ) 27 28 // Converter missing godoc 29 // 30 //go:generate mockery --name=Converter --output=automock --outpkg=automock --case=underscore --disable-version-string 31 type Converter interface { 32 ToEntity(in *model.Document) (*Entity, error) 33 FromEntity(in *Entity) (*model.Document, error) 34 } 35 36 type repository struct { 37 existQuerier repo.ExistQuerier 38 singleGetter repo.SingleGetter 39 unionLister repo.UnionLister 40 deleter repo.Deleter 41 pageableQuerier repo.PageableQuerier 42 creator repo.Creator 43 creatorGlobal repo.CreatorGlobal 44 45 conv Converter 46 } 47 48 // NewRepository missing godoc 49 func NewRepository(conv Converter) *repository { 50 return &repository{ 51 existQuerier: repo.NewExistQuerier(documentTable), 52 singleGetter: repo.NewSingleGetter(documentTable, documentColumns), 53 unionLister: repo.NewUnionLister(documentTable, documentColumns), 54 deleter: repo.NewDeleter(documentTable), 55 pageableQuerier: repo.NewPageableQuerier(documentTable, documentColumns), 56 creator: repo.NewCreator(documentTable, documentColumns), 57 creatorGlobal: repo.NewCreatorGlobal(resource.Document, documentTable, documentColumns), 58 conv: conv, 59 } 60 } 61 62 // DocumentCollection missing godoc 63 type DocumentCollection []Entity 64 65 // Len missing godoc 66 func (d DocumentCollection) Len() int { 67 return len(d) 68 } 69 70 // Exists missing godoc 71 func (r *repository) Exists(ctx context.Context, tenant, id string) (bool, error) { 72 return r.existQuerier.Exists(ctx, resource.Document, tenant, repo.Conditions{repo.NewEqualCondition("id", id)}) 73 } 74 75 // GetByID missing godoc 76 func (r *repository) GetByID(ctx context.Context, tenant, id string) (*model.Document, error) { 77 var entity Entity 78 if err := r.singleGetter.Get(ctx, resource.Document, tenant, repo.Conditions{repo.NewEqualCondition("id", id)}, repo.NoOrderBy, &entity); err != nil { 79 return nil, err 80 } 81 82 docModel, err := r.conv.FromEntity(&entity) 83 if err != nil { 84 return nil, errors.Wrap(err, "while converting Document entity to model") 85 } 86 87 return docModel, nil 88 } 89 90 // GetForBundle missing godoc 91 func (r *repository) GetForBundle(ctx context.Context, tenant string, id string, bundleID string) (*model.Document, error) { 92 var ent Entity 93 94 conditions := repo.Conditions{ 95 repo.NewEqualCondition("id", id), 96 repo.NewEqualCondition("bundle_id", bundleID), 97 } 98 if err := r.singleGetter.Get(ctx, resource.Document, tenant, conditions, repo.NoOrderBy, &ent); err != nil { 99 return nil, err 100 } 101 102 documentModel, err := r.conv.FromEntity(&ent) 103 if err != nil { 104 return nil, errors.Wrap(err, "while converting Document entity to model") 105 } 106 107 return documentModel, nil 108 } 109 110 // Create missing godoc 111 func (r *repository) Create(ctx context.Context, tenant string, item *model.Document) error { 112 if item == nil { 113 return apperrors.NewInternalError("Document cannot be empty") 114 } 115 116 entity, err := r.conv.ToEntity(item) 117 if err != nil { 118 return errors.Wrap(err, "while creating Document entity from model") 119 } 120 121 log.C(ctx).Debugf("Persisting Document entity with id %s to db", item.ID) 122 return r.creator.Create(ctx, resource.Document, tenant, entity) 123 } 124 125 // CreateGlobal creates a document without a tenant isolation 126 func (r *repository) CreateGlobal(ctx context.Context, item *model.Document) error { 127 if item == nil { 128 return apperrors.NewInternalError("Document cannot be empty") 129 } 130 131 entity, err := r.conv.ToEntity(item) 132 if err != nil { 133 return errors.Wrap(err, "while creating Document entity from model") 134 } 135 136 log.C(ctx).Debugf("Persisting Document entity with id %s to db", item.ID) 137 return r.creatorGlobal.Create(ctx, entity) 138 } 139 140 // CreateMany missing godoc 141 func (r *repository) CreateMany(ctx context.Context, tenant string, items []*model.Document) error { 142 for _, item := range items { 143 if item == nil { 144 return apperrors.NewInternalError("Document cannot be empty") 145 } 146 err := r.Create(ctx, tenant, item) 147 if err != nil { 148 return errors.Wrapf(err, "while creating Document with ID %s", item.ID) 149 } 150 } 151 152 return nil 153 } 154 155 // Delete missing godoc 156 func (r *repository) Delete(ctx context.Context, tenant, id string) error { 157 return r.deleter.DeleteOne(ctx, resource.Document, tenant, repo.Conditions{repo.NewEqualCondition("id", id)}) 158 } 159 160 // ListByBundleIDs missing godoc 161 func (r *repository) ListByBundleIDs(ctx context.Context, tenantID string, bundleIDs []string, pageSize int, cursor string) ([]*model.DocumentPage, error) { 162 var documentCollection DocumentCollection 163 counts, err := r.unionLister.List(ctx, resource.Document, tenantID, bundleIDs, bundleIDColumn, pageSize, cursor, orderByColumns, &documentCollection) 164 if err != nil { 165 return nil, err 166 } 167 168 documentByID := map[string][]*model.Document{} 169 for _, documentEnt := range documentCollection { 170 m, err := r.conv.FromEntity(&documentEnt) 171 if err != nil { 172 return nil, errors.Wrap(err, "while creating Document model from entity") 173 } 174 documentByID[documentEnt.BndlID] = append(documentByID[documentEnt.BndlID], m) 175 } 176 177 offset, err := pagination.DecodeOffsetCursor(cursor) 178 if err != nil { 179 return nil, errors.Wrap(err, "while decoding page cursor") 180 } 181 182 documentPages := make([]*model.DocumentPage, 0, len(bundleIDs)) 183 for _, bndlID := range bundleIDs { 184 totalCount := counts[bndlID] 185 hasNextPage := false 186 endCursor := "" 187 if totalCount > offset+len(documentByID[bndlID]) { 188 hasNextPage = true 189 endCursor = pagination.EncodeNextOffsetCursor(offset, pageSize) 190 } 191 192 page := &pagination.Page{ 193 StartCursor: cursor, 194 EndCursor: endCursor, 195 HasNextPage: hasNextPage, 196 } 197 198 documentPages = append(documentPages, &model.DocumentPage{Data: documentByID[bndlID], TotalCount: totalCount, PageInfo: page}) 199 } 200 201 return documentPages, nil 202 }