Skip to content
Snippets Groups Projects
Select Git revision
  • d38dacdb7ea76b2aabaff8974c9593add20abb90
  • master default protected
  • fix/PRXS-3401-ValidateValidationOpts
  • feature/PRXS-3383-CollectionsRankSortAPI
  • feature/3149-LocaleCodeAsID-Feature
  • feature/PRXS-3383-CollectionsSort
  • feature/3109-SerializeFeature
  • release/0.33
  • feature/3109-RecoverySchema
  • feature/3109-feature
  • fix/PRXS-3369-ValidateFields
  • refactor/PRXS-3306-MovePkgGroup1
  • refactor/6-pkg-refactor-expr
  • fix/PRXS-3360-TemplateBuilderPatch
  • feature/3293-MongoV2
  • feature/3272-GoVersionUp
  • feature/PRXS-3218-HideTemplateActions
  • feature/PRXS-3234-PruneIdents
  • feature/3146-UpdateItemStorageInterface
  • feature/3274-ObjectIndexesFixes
  • feature/PRXS-3143-3235-ReferenceOptions
  • v0.33.1
  • v0.32.0
  • v0.31.1
  • v0.31.0
  • v0.30.0
  • v0.29.0
  • v0.28.0
  • v0.27.0-alpha.1+16
  • v0.27.0-alpha.1+15
  • v0.27.0-alpha.1+14
  • v0.27.0-alpha.1+13
  • v0.27.0-alpha.1+12
  • v0.27.0-alpha.1+11
  • v0.27.0-alpha.1+10
  • v0.27.0-alpha.1+9
  • v0.27.0-alpha.1+8
  • v0.27.0-alpha.1+7
  • v0.27.0-alpha.1+6
  • v0.27.0-alpha.1+5
  • v0.27.0-alpha.1+4
41 results

collection.go

Blame
  • user avatar
    ko_oler authored
    Добавлен временный флаг для вызова метода SetSchema, с целью обновления всех коллекции расширений для установки в них метадаты
    d38dacdb
    History
    collection.go 7.89 KiB
    package setup
    
    import (
    	"context"
    	"reflect"
    	"strings"
    
    	"git.perx.ru/perxis/perxis-go/pkg/collections"
    	"git.perx.ru/perxis/perxis-go/pkg/data"
    	"git.perx.ru/perxis/perxis-go/pkg/environments"
    	"git.perx.ru/perxis/perxis-go/pkg/errors"
    	"git.perx.ru/perxis/perxis-go/pkg/extension"
    	"go.uber.org/zap"
    )
    
    var (
    	ErrCheckCollections     = errors.New("collections check error")
    	ErrInstallCollections   = errors.New("failed to install collections")
    	ErrUninstallCollections = errors.New("failed to uninstall collections")
    )
    
    type CollectionsOption func(c *CollectionConfig)
    type UpdateCollectionFn func(s *Setup, exist, new *collections.Collection) (coll *collections.Collection, upd bool, setSchema bool, err error)
    type DeleteCollectionFn func(s *Setup, col *collections.Collection) (bool, error)
    
    type CollectionConfig struct {
    	collection *collections.Collection
    	UpdateFn   UpdateCollectionFn
    	DeleteFn   DeleteCollectionFn
    }
    
    func NewCollectionConfig(collection *collections.Collection, opt ...CollectionsOption) CollectionConfig {
    	c := CollectionConfig{collection: collection}
    
    	DefaultUpdateCollectionStrategy()(&c)
    	DeleteCollectionIfRemove()(&c)
    
    	for _, o := range opt {
    		o(&c)
    	}
    
    	return c
    }
    
    func OverwriteCollection() CollectionsOption {
    	return func(c *CollectionConfig) {
    		c.UpdateFn = func(s *Setup, old, new *collections.Collection) (*collections.Collection, bool, bool, error) {
    			return new, true, true, nil
    		}
    	}
    }
    
    func KeepExistingCollection() CollectionsOption {
    	return func(c *CollectionConfig) {
    		c.UpdateFn = func(s *Setup, old, new *collections.Collection) (*collections.Collection, bool, bool, error) {
    			return old, false, false, nil
    		}
    	}
    }
    
    func DeleteCollection() CollectionsOption {
    	return func(c *CollectionConfig) {
    		c.DeleteFn = func(s *Setup, collection *collections.Collection) (bool, error) { return true, nil }
    	}
    }
    
    func DeleteCollectionIfRemove() CollectionsOption {
    	return func(c *CollectionConfig) {
    		c.DeleteFn = func(s *Setup, collection *collections.Collection) (bool, error) { return s.IsRemove(), nil }
    	}
    }
    
    func DefaultUpdateCollectionStrategy() CollectionsOption {
    	return func(c *CollectionConfig) {
    		c.UpdateFn = func(s *Setup, exist, collection *collections.Collection) (*collections.Collection, bool, bool, error) {
    
    			//todo добавлено в релизе v0.0.16: временный флаг для установки метадаты во все коллекции расширений
    			alwaysSetSchema := true
    
    			if !alwaysSetSchema && !s.IsForce() && !collection.IsView() && !exist.IsView() && collection.Schema.Metadata != nil && collection.Schema.Metadata[extension.ExtensionMetadataKey] != "" {
    				if exist.Schema.Metadata == nil || exist.Schema.Metadata[extension.ExtensionMetadataKey] != collection.Schema.Metadata[extension.ExtensionMetadataKey] {
    					return nil, false, false, errors.WithDetailf(collections.ErrAlreadyExists, "Коллекция с идентификатором '%s' "+
    						"уже существует. Удалите ее или вызовите установку расширения с флагом Force", collection.ID)
    				}
    			}
    
    			if len(exist.Tags) > 0 {
    				collection.Tags = data.SetFromSlice(append(exist.Tags, collection.Tags...))
    			}
    
    			var update, setSchema bool
    			update = collection.Name != exist.Name || collection.IsSingle() != exist.IsSingle() || collection.IsSystem() != exist.IsSystem() ||
    				collection.IsNoData() != exist.IsNoData() || collection.Hidden != exist.Hidden || collection.IsView() != exist.IsView() && data.ElementsMatch(exist.Tags, collection.Tags)
    
    			setSchema = alwaysSetSchema || !collection.IsView() && !reflect.DeepEqual(exist.Schema, collection.Schema)
    
    			return collection, update, setSchema, nil
    		}
    	}
    }
    
    func (s *Setup) InstallCollections(ctx context.Context) (err error) {
    	if len(s.Collections) == 0 {
    		return nil
    	}
    
    	s.logger.Debug("Install collections", zap.Int("Collections", len(s.Collections)))
    
    	var migrate, setSchema bool
    
    	for _, c := range s.Collections {
    		setSchema, err = s.InstallCollection(ctx, c)
    		if err != nil {
    			s.logger.Error("Failed to install collection",
    				zap.String("Collection ID", c.collection.ID),
    				zap.String("Collection Name", c.collection.Name),
    				zap.Error(err),
    			)
    			return errors.WithDetailf(errors.Wrap(err, "failed to install collection"), "Возникла ошибка при настройке коллекции %s(%s)", c.collection.Name, c.collection.ID)
    		}
    		if setSchema {
    			migrate = true
    		}
    	}
    
    	if migrate {
    		if err = s.content.Environments.Migrate(ctx, s.SpaceID, s.EnvironmentID, &environments.MigrateOptions{Wait: true}); err != nil {
    			s.logger.Error(
    				"Failed to migrate environment",
    				zap.String("Space ID", s.SpaceID),
    				zap.String("Environment ID", s.EnvironmentID),
    				zap.Error(err),
    			)
    
    			return errors.WithDetail(errors.Wrap(err, "migrate"), "Возникла ошибка при миграции данных")
    		}
    	}
    
    	return nil
    }
    
    func (s *Setup) InstallCollection(ctx context.Context, c CollectionConfig) (setSchema bool, err error) {
    	collection := c.collection
    	collection.SpaceID, collection.EnvID = s.SpaceID, s.EnvironmentID
    
    	var exist *collections.Collection
    	// isForce - не удалять коллекцию, если она уже существует
    	exist, err = s.content.Collections.Get(ctx, collection.SpaceID, collection.EnvID, collection.ID)
    	if err != nil && !strings.Contains(err.Error(), collections.ErrNotFound.Error()) {
    		return false, err
    	}
    
    	if exist == nil {
    		setSchema = !collection.IsView()
    		_, err = s.content.Collections.Create(ctx, collection)
    		if err != nil {
    			return false, err
    		}
    	} else {
    		var upd bool
    		collection, upd, setSchema, err = c.UpdateFn(s, exist, c.collection)
    		if err != nil {
    			return false, err
    		}
    		if upd {
    			if err = s.content.Collections.Update(ctx, collection); err != nil {
    				return false, err
    			}
    		}
    	}
    
    	if setSchema {
    		err = s.content.Collections.SetSchema(ctx, collection.SpaceID, collection.EnvID, collection.ID, collection.Schema)
    		if err != nil {
    			return false, err
    		}
    	}
    
    	return setSchema, nil
    }
    
    func (s *Setup) CheckCollections(ctx context.Context) error {
    	if len(s.Collections) == 0 {
    		return nil
    	}
    
    	s.logger.Debug("Check collections", zap.Int("Collections", len(s.Collections)))
    
    	var errs []error
    	for _, c := range s.Collections {
    		if err := s.CheckCollection(ctx, c); err != nil {
    			errs = append(errs, errors.WithDetailf(err, "Не найдена коллекция %s(%s)", c.collection.ID, c.collection.Name))
    		}
    	}
    
    	if len(errs) > 0 {
    		return errors.WithErrors(ErrCheckCollections, errs...)
    	}
    
    	return nil
    }
    
    func (s *Setup) CheckCollection(ctx context.Context, c CollectionConfig) (err error) {
    	_, err = s.content.Collections.Get(ctx, s.SpaceID, s.EnvironmentID, c.collection.ID)
    	return err
    }
    
    func (s *Setup) UninstallCollections(ctx context.Context) error {
    	if len(s.Collections) == 0 {
    		return nil
    	}
    
    	s.logger.Debug("Uninstall collections", zap.Int("Collections", len(s.Collections)))
    
    	for _, c := range s.Collections {
    		if err := s.UninstallCollection(ctx, c); err != nil {
    			s.logger.Error("Failed to uninstall collection",
    				zap.String("Collection ID", c.collection.ID),
    				zap.String("Collection Name", c.collection.Name),
    				zap.Error(err),
    			)
    			return errors.WithDetailf(errors.Wrap(err, "failed to uninstall collection"), "Возникла ошибка при удалении коллекции %s(%s)", c.collection.Name, c.collection.ID)
    		}
    	}
    
    	return nil
    }
    
    func (s *Setup) UninstallCollection(ctx context.Context, c CollectionConfig) error {
    	ok, err := c.DeleteFn(s, c.collection)
    	if err != nil {
    		return err
    	}
    	if ok {
    		if err = s.content.Collections.Delete(ctx, s.SpaceID, s.EnvironmentID, c.collection.ID); err != nil && !strings.Contains(err.Error(), collections.ErrNotFound.Error()) {
    			return err
    		}
    		s.removeItems(c.collection.ID) // после удаления коллекции нет смысла удалять ее элементы
    	}
    	return nil
    }