github.com/polarismesh/polaris@v1.17.8/store/boltdb/config_file_group.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package boltdb
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  	"sort"
    24  	"strings"
    25  	"time"
    26  
    27  	bolt "go.etcd.io/bbolt"
    28  	"go.uber.org/zap"
    29  
    30  	"github.com/polarismesh/polaris/common/model"
    31  	"github.com/polarismesh/polaris/store"
    32  )
    33  
    34  const (
    35  	tblConfigFileGroup string = "ConfigFileGroup"
    36  
    37  	FileGroupFieldId         string = "Id"
    38  	FileGroupFieldName       string = "Name"
    39  	FileGroupFieldNamespace  string = "Namespace"
    40  	FileGroupFieldComment    string = "Comment"
    41  	FileGroupFieldCreateBy   string = "CreateBy"
    42  	FileGroupFieldModifyBy   string = "ModifyBy"
    43  	FileGroupFieldCreateTime string = "CreateTime"
    44  	FileGroupFieldModifyTime string = "ModifyTime"
    45  	FileGroupFieldValid      string = "Valid"
    46  	FileGroupFieldBusiness   string = "Business"
    47  	FileGroupFieldDepartment string = "Department"
    48  	FileGroupFieldMetadata   string = "Metadata"
    49  )
    50  
    51  var (
    52  	ErrMultipleConfigFileGroupFound error = errors.New("multiple config_file_group found")
    53  )
    54  
    55  type configFileGroupStore struct {
    56  	handler BoltHandler
    57  }
    58  
    59  func newConfigFileGroupStore(handler BoltHandler) *configFileGroupStore {
    60  	s := &configFileGroupStore{handler: handler}
    61  	return s
    62  }
    63  
    64  // CreateConfigFileGroup 创建配置文件组
    65  func (fg *configFileGroupStore) CreateConfigFileGroup(
    66  	fileGroup *model.ConfigFileGroup) (*model.ConfigFileGroup, error) {
    67  	if fileGroup.Namespace == "" || fileGroup.Name == "" {
    68  		return nil, store.NewStatusError(store.EmptyParamsErr, "ConfigFileGroup miss some param")
    69  	}
    70  
    71  	err := fg.handler.Execute(true, func(tx *bolt.Tx) error {
    72  		table, err := tx.CreateBucketIfNotExists([]byte(tblConfigFileGroup))
    73  		if err != nil {
    74  			return err
    75  		}
    76  		nextId, err := table.NextSequence()
    77  		if err != nil {
    78  			return err
    79  		}
    80  		fileGroup.Id = nextId
    81  		fileGroup.Valid = true
    82  		fileGroup.CreateTime = time.Now()
    83  		fileGroup.ModifyTime = fileGroup.CreateTime
    84  
    85  		key := fmt.Sprintf("%s@@%s", fileGroup.Namespace, fileGroup.Name)
    86  		if err := saveValue(tx, tblConfigFileGroup, key, fileGroup); err != nil {
    87  			log.Error("[ConfigFileGroup] save info", zap.Error(err))
    88  			return err
    89  		}
    90  		return nil
    91  	})
    92  	if err != nil {
    93  		return nil, store.Error(err)
    94  	}
    95  	return fileGroup, nil
    96  }
    97  
    98  // GetConfigFileGroup 获取配置文件组
    99  func (fg *configFileGroupStore) GetConfigFileGroup(namespace, name string) (*model.ConfigFileGroup, error) {
   100  	if namespace == "" || name == "" {
   101  		return nil, store.NewStatusError(store.EmptyParamsErr, "ConfigFileGroup miss some param")
   102  	}
   103  
   104  	key := fmt.Sprintf("%s@@%s", namespace, name)
   105  	ret, err := fg.handler.LoadValues(tblConfigFileGroup, []string{key}, &model.ConfigFileGroup{})
   106  	if err != nil {
   107  		log.Error("[ConfigFileGroup] find by namespace and name", zap.Error(err))
   108  		return nil, err
   109  	}
   110  	if len(ret) == 0 {
   111  		return nil, nil
   112  	}
   113  	val := ret[key]
   114  	if val == nil {
   115  		return nil, nil
   116  	}
   117  	cfg := val.(*model.ConfigFileGroup)
   118  	if !cfg.Valid {
   119  		return nil, nil
   120  	}
   121  
   122  	return cfg, nil
   123  }
   124  
   125  // QueryConfigFileGroups 翻页查询配置文件组, name 为模糊匹配关键字
   126  func (fg *configFileGroupStore) QueryConfigFileGroups(namespace, name string, offset, limit uint32) (uint32,
   127  	[]*model.ConfigFileGroup, error) {
   128  	var (
   129  		fields  = []string{FileGroupFieldNamespace, FileGroupFieldName, FileGroupFieldValid}
   130  		hasNs   = len(namespace) != 0
   131  		hasName = len(name) != 0
   132  	)
   133  	ret, err := fg.handler.LoadValuesByFilter(tblConfigFileGroup, fields, &model.ConfigFileGroup{},
   134  		func(m map[string]interface{}) bool {
   135  			valid, ok := m[FileGroupFieldValid].(bool)
   136  			if ok && !valid {
   137  				return false
   138  			}
   139  
   140  			saveNamespace, _ := m[FileGroupFieldNamespace].(string)
   141  			saveName, _ := m[FileGroupFieldName].(string)
   142  
   143  			if hasNs && strings.Compare(namespace, saveNamespace) != 0 {
   144  				return false
   145  			}
   146  
   147  			if hasName {
   148  				if !strings.Contains(saveName, name[:len(name)-1]) {
   149  					return false
   150  				}
   151  			}
   152  
   153  			return true
   154  		})
   155  
   156  	if err != nil {
   157  		log.Error("[ConfigFileGroup] find by page", zap.Error(err))
   158  		return 0, nil, err
   159  	}
   160  
   161  	return uint32(len(ret)), doConfigFileGroupPage(ret, offset, limit), nil
   162  }
   163  
   164  // DeleteConfigFileGroup 删除配置文件组
   165  func (fg *configFileGroupStore) DeleteConfigFileGroup(namespace, name string) error {
   166  	if namespace == "" || name == "" {
   167  		return store.NewStatusError(store.EmptyParamsErr, "ConfigFileGroup miss some param")
   168  	}
   169  
   170  	key := fmt.Sprintf("%s@@%s", namespace, name)
   171  	properties := make(map[string]interface{})
   172  	properties[FileGroupFieldValid] = false
   173  	properties[FileGroupFieldModifyTime] = time.Now()
   174  
   175  	if err := fg.handler.UpdateValue(tblConfigFileGroup, key, properties); err != nil {
   176  		log.Error("[ConfigFileGroup] do delete", zap.Error(err))
   177  		return store.Error(err)
   178  	}
   179  	return nil
   180  }
   181  
   182  // UpdateConfigFileGroup 更新配置文件组信息
   183  func (fg *configFileGroupStore) UpdateConfigFileGroup(fileGroup *model.ConfigFileGroup) error {
   184  	if fileGroup.Namespace == "" || fileGroup.Name == "" {
   185  		return store.NewStatusError(store.EmptyParamsErr, "ConfigFileGroup miss some param")
   186  	}
   187  
   188  	key := fmt.Sprintf("%s@@%s", fileGroup.Namespace, fileGroup.Name)
   189  	properties := make(map[string]interface{})
   190  	properties[FileGroupFieldComment] = fileGroup.Comment
   191  	properties[FileGroupFieldModifyBy] = fileGroup.ModifyBy
   192  	properties[FileGroupFieldBusiness] = fileGroup.Business
   193  	properties[FileGroupFieldDepartment] = fileGroup.Department
   194  	properties[FileGroupFieldMetadata] = fileGroup.Metadata
   195  	properties[FileGroupFieldModifyTime] = time.Now()
   196  
   197  	if err := fg.handler.UpdateValue(tblConfigFileGroup, key, properties); err != nil {
   198  		log.Error("[ConfigFileGroup] do update", zap.Error(err))
   199  		return store.Error(err)
   200  	}
   201  	return nil
   202  }
   203  
   204  func (fg *configFileGroupStore) GetMoreConfigGroup(firstUpdate bool,
   205  	mtime time.Time) ([]*model.ConfigFileGroup, error) {
   206  
   207  	if firstUpdate {
   208  		mtime = time.Time{}
   209  	}
   210  
   211  	fields := []string{FileGroupFieldModifyTime}
   212  	ret, err := fg.handler.LoadValuesByFilter(tblConfigFileGroup, fields, &model.ConfigFileGroup{},
   213  		func(m map[string]interface{}) bool {
   214  			saveMt, _ := m[FileGroupFieldModifyTime].(time.Time)
   215  			return !saveMt.Before(mtime)
   216  		})
   217  
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  
   222  	groups := make([]*model.ConfigFileGroup, 0, len(ret))
   223  	for _, v := range ret {
   224  		groups = append(groups, v.(*model.ConfigFileGroup))
   225  	}
   226  
   227  	return groups, nil
   228  }
   229  
   230  // CountConfigReleases count the release data
   231  func (fg *configFileGroupStore) CountConfigGroups(namespace string) (uint64, error) {
   232  	fields := []string{FileGroupFieldNamespace, FileGroupFieldValid}
   233  	ret, err := fg.handler.LoadValuesByFilter(tblConfigFileGroup, fields, &model.ConfigFileGroup{},
   234  		func(m map[string]interface{}) bool {
   235  			valid, _ := m[FileGroupFieldValid].(bool)
   236  			if !valid {
   237  				return false
   238  			}
   239  			saveNs, _ := m[FileGroupFieldNamespace].(string)
   240  			return saveNs == namespace
   241  		})
   242  	if err != nil {
   243  		return 0, err
   244  	}
   245  	return uint64(len(ret)), err
   246  }
   247  
   248  // doConfigFileGroupPage 进行分页
   249  func doConfigFileGroupPage(ret map[string]interface{}, offset, limit uint32) []*model.ConfigFileGroup {
   250  	var (
   251  		groups     = make([]*model.ConfigFileGroup, 0, len(ret))
   252  		beginIndex = offset
   253  		endIndex   = beginIndex + limit
   254  		totalCount = uint32(len(ret))
   255  	)
   256  	if totalCount == 0 {
   257  		return groups
   258  	}
   259  	if beginIndex >= endIndex {
   260  		return groups
   261  	}
   262  	if beginIndex >= totalCount {
   263  		return groups
   264  	}
   265  	if endIndex > totalCount {
   266  		endIndex = totalCount
   267  	}
   268  	for k := range ret {
   269  		groups = append(groups, ret[k].(*model.ConfigFileGroup))
   270  	}
   271  
   272  	sort.Slice(groups, func(i, j int) bool {
   273  		return groups[i].ModifyTime.After(groups[j].ModifyTime)
   274  	})
   275  
   276  	return groups[beginIndex:endIndex]
   277  }