github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/fetchrequest/repository.go (about) 1 package fetchrequest 2 3 import ( 4 "context" 5 6 "github.com/kyma-incubator/compass/components/director/pkg/resource" 7 8 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 9 10 "github.com/kyma-incubator/compass/components/director/internal/model" 11 "github.com/kyma-incubator/compass/components/director/internal/repo" 12 "github.com/pkg/errors" 13 ) 14 15 const fetchRequestTable string = `public.fetch_requests` 16 17 const documentIDColumn = "document_id" 18 const specIDColumn = "spec_id" 19 20 var ( 21 fetchRequestColumns = []string{"id", documentIDColumn, "url", "auth", "mode", "filter", "status_condition", "status_message", "status_timestamp", specIDColumn} 22 ) 23 24 // Converter missing godoc 25 // 26 //go:generate mockery --name=Converter --output=automock --outpkg=automock --case=underscore --disable-version-string 27 type Converter interface { 28 ToEntity(in *model.FetchRequest) (*Entity, error) 29 FromEntity(in *Entity, objectType model.FetchRequestReferenceObjectType) (*model.FetchRequest, error) 30 } 31 32 type repository struct { 33 creator repo.Creator 34 creatorGlobal repo.CreatorGlobal 35 singleGetter repo.SingleGetter 36 lister repo.Lister 37 listerGlobal repo.ListerGlobal 38 deleter repo.Deleter 39 deleterGlobal repo.DeleterGlobal 40 updater repo.Updater 41 updaterGlobal repo.UpdaterGlobal 42 conv Converter 43 } 44 45 // NewRepository missing godoc 46 func NewRepository(conv Converter) *repository { 47 return &repository{ 48 creator: repo.NewCreator(fetchRequestTable, fetchRequestColumns), 49 creatorGlobal: repo.NewCreatorGlobal(resource.FetchRequest, fetchRequestTable, fetchRequestColumns), 50 singleGetter: repo.NewSingleGetter(fetchRequestTable, fetchRequestColumns), 51 lister: repo.NewLister(fetchRequestTable, fetchRequestColumns), 52 listerGlobal: repo.NewListerGlobal(resource.FetchRequest, fetchRequestTable, fetchRequestColumns), 53 deleter: repo.NewDeleter(fetchRequestTable), 54 deleterGlobal: repo.NewDeleterGlobal(resource.FetchRequest, fetchRequestTable), 55 updater: repo.NewUpdater(fetchRequestTable, []string{"status_condition", "status_message", "status_timestamp"}, []string{"id"}), 56 updaterGlobal: repo.NewUpdaterGlobal(resource.FetchRequest, fetchRequestTable, []string{"status_condition", "status_message", "status_timestamp"}, []string{"id"}), 57 conv: conv, 58 } 59 } 60 61 // Create missing godoc 62 func (r *repository) Create(ctx context.Context, tenant string, item *model.FetchRequest) error { 63 if item == nil { 64 return apperrors.NewInternalError("item can not be empty") 65 } 66 67 entity, err := r.conv.ToEntity(item) 68 if err != nil { 69 return errors.Wrap(err, "while creating FetchRequest entity from model") 70 } 71 72 return r.creator.Create(ctx, item.ObjectType.GetResourceType(), tenant, entity) 73 } 74 75 // CreateGlobal creates a fetch request without tenant isolation 76 func (r *repository) CreateGlobal(ctx context.Context, item *model.FetchRequest) error { 77 if item == nil { 78 return apperrors.NewInternalError("item can not be empty") 79 } 80 81 entity, err := r.conv.ToEntity(item) 82 if err != nil { 83 return errors.Wrap(err, "while creating FetchRequest entity from model") 84 } 85 86 return r.creatorGlobal.Create(ctx, entity) 87 } 88 89 // GetByReferenceObjectID missing godoc 90 func (r *repository) GetByReferenceObjectID(ctx context.Context, tenant string, objectType model.FetchRequestReferenceObjectType, objectID string) (*model.FetchRequest, error) { 91 fieldName, err := r.referenceObjectFieldName(objectType) 92 if err != nil { 93 return nil, err 94 } 95 96 var entity Entity 97 if err := r.singleGetter.Get(ctx, objectType.GetResourceType(), tenant, repo.Conditions{repo.NewEqualCondition(fieldName, objectID)}, repo.NoOrderBy, &entity); err != nil { 98 return nil, err 99 } 100 101 frModel, err := r.conv.FromEntity(&entity, objectType) 102 if err != nil { 103 return nil, errors.Wrap(err, "while getting FetchRequest model from entity") 104 } 105 106 return frModel, nil 107 } 108 109 // Delete missing godoc 110 func (r *repository) Delete(ctx context.Context, tenant, id string, objectType model.FetchRequestReferenceObjectType) error { 111 return r.deleter.DeleteOne(ctx, objectType.GetResourceType(), tenant, repo.Conditions{repo.NewEqualCondition("id", id)}) 112 } 113 114 // DeleteByReferenceObjectID missing godoc 115 func (r *repository) DeleteByReferenceObjectID(ctx context.Context, tenant string, objectType model.FetchRequestReferenceObjectType, objectID string) error { 116 fieldName, err := r.referenceObjectFieldName(objectType) 117 if err != nil { 118 return err 119 } 120 121 return r.deleter.DeleteMany(ctx, objectType.GetResourceType(), tenant, repo.Conditions{repo.NewEqualCondition(fieldName, objectID)}) 122 } 123 124 // DeleteByReferenceObjectIDGlobal deletes fetch request by model.FetchRequestReferenceObjectType without tenant isolation 125 func (r *repository) DeleteByReferenceObjectIDGlobal(ctx context.Context, objectType model.FetchRequestReferenceObjectType, objectID string) error { 126 fieldName, err := r.referenceObjectFieldName(objectType) 127 if err != nil { 128 return err 129 } 130 131 return r.deleterGlobal.DeleteManyGlobal(ctx, repo.Conditions{repo.NewEqualCondition(fieldName, objectID)}) 132 } 133 134 // Update missing godoc 135 func (r *repository) Update(ctx context.Context, tenant string, item *model.FetchRequest) error { 136 if item == nil { 137 return apperrors.NewInternalError("item cannot be nil") 138 } 139 entity, err := r.conv.ToEntity(item) 140 if err != nil { 141 return err 142 } 143 return r.updater.UpdateSingle(ctx, item.ObjectType.GetResourceType(), tenant, entity) 144 } 145 146 // UpdateGlobal updates a fetch request globally without tenant isolation 147 func (r *repository) UpdateGlobal(ctx context.Context, item *model.FetchRequest) error { 148 if item == nil { 149 return apperrors.NewInternalError("item cannot be nil") 150 } 151 entity, err := r.conv.ToEntity(item) 152 if err != nil { 153 return err 154 } 155 return r.updaterGlobal.UpdateSingleGlobal(ctx, entity) 156 } 157 158 func (r *repository) ListByReferenceObjectIDs(ctx context.Context, tenant string, objectType model.FetchRequestReferenceObjectType, objectIDs []string) ([]*model.FetchRequest, error) { 159 fieldName, err := r.referenceObjectFieldName(objectType) 160 if err != nil { 161 return nil, err 162 } 163 164 conditions := r.buildConditionsForReferenceObjectIDs(objectIDs, fieldName) 165 166 var fetchRequestCollection FetchRequestsCollection 167 if err = r.lister.List(ctx, objectType.GetResourceType(), tenant, &fetchRequestCollection, conditions...); err != nil { 168 return nil, err 169 } 170 171 return r.enrichFetchRequestModel(fetchRequestCollection, fieldName, objectType, objectIDs) 172 } 173 174 // ListByReferenceObjectIDsGlobal lists fetch requests by reference objects IDs without tenant isolation 175 func (r *repository) ListByReferenceObjectIDsGlobal(ctx context.Context, objectType model.FetchRequestReferenceObjectType, objectIDs []string) ([]*model.FetchRequest, error) { 176 fieldName, err := r.referenceObjectFieldName(objectType) 177 if err != nil { 178 return nil, err 179 } 180 181 conditions := r.buildConditionsForReferenceObjectIDs(objectIDs, fieldName) 182 183 var fetchRequestCollection FetchRequestsCollection 184 if err = r.listerGlobal.ListGlobal(ctx, &fetchRequestCollection, conditions...); err != nil { 185 return nil, err 186 } 187 188 return r.enrichFetchRequestModel(fetchRequestCollection, fieldName, objectType, objectIDs) 189 } 190 191 func (r *repository) referenceObjectFieldName(objectType model.FetchRequestReferenceObjectType) (string, error) { 192 switch objectType { 193 case model.DocumentFetchRequestReference: 194 return documentIDColumn, nil 195 case model.EventSpecFetchRequestReference: 196 fallthrough 197 case model.APISpecFetchRequestReference: 198 return specIDColumn, nil 199 } 200 201 return "", apperrors.NewInternalError("Invalid type of the Fetch Request reference object") 202 } 203 204 func (r *repository) buildConditionsForReferenceObjectIDs(objectIDs []string, fieldName string) repo.Conditions { 205 var conditions repo.Conditions 206 if len(objectIDs) > 0 { 207 conditions = repo.Conditions{ 208 repo.NewInConditionForStringValues(fieldName, objectIDs), 209 } 210 } 211 212 return conditions 213 } 214 215 func (r *repository) enrichFetchRequestModel(fetchRequestCollection FetchRequestsCollection, fieldName string, objectType model.FetchRequestReferenceObjectType, objectIDs []string) ([]*model.FetchRequest, error) { 216 fetchRequestsByID := map[string]*model.FetchRequest{} 217 for _, fetchRequestEnt := range fetchRequestCollection { 218 m, err := r.conv.FromEntity(&fetchRequestEnt, objectType) 219 if err != nil { 220 return nil, errors.Wrap(err, "while creating FetchRequest model from entity") 221 } 222 223 if fieldName == specIDColumn { 224 fetchRequestsByID[fetchRequestEnt.SpecID.String] = m 225 } else if fieldName == documentIDColumn { 226 fetchRequestsByID[fetchRequestEnt.DocumentID.String] = m 227 } 228 } 229 230 fetchRequests := make([]*model.FetchRequest, 0, len(objectIDs)) 231 for _, objectID := range objectIDs { 232 fetchRequests = append(fetchRequests, fetchRequestsByID[objectID]) 233 } 234 235 return fetchRequests, nil 236 } 237 238 // FetchRequestsCollection missing godoc 239 type FetchRequestsCollection []Entity 240 241 // Len missing godoc 242 func (r FetchRequestsCollection) Len() int { 243 return len(r) 244 }