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  }