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 }