github.com/polarismesh/polaris@v1.17.8/store/boltdb/routing_config_v2.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  	"time"
    23  
    24  	bolt "go.etcd.io/bbolt"
    25  	"go.uber.org/zap"
    26  
    27  	"github.com/polarismesh/polaris/common/model"
    28  	"github.com/polarismesh/polaris/store"
    29  )
    30  
    31  var _ store.RoutingConfigStoreV2 = (*routingStoreV2)(nil)
    32  
    33  var (
    34  	// ErrMultipleRoutingV2Found 多个路由配置
    35  	ErrMultipleRoutingV2Found = errors.New("multiple routing v2 found")
    36  )
    37  
    38  const (
    39  	tblNameRoutingV2 = "routing_config_v2"
    40  
    41  	routingV2FieldID          = "ID"
    42  	routingV2FieldName        = "Name"
    43  	routingV2FieldNamespace   = "Namespace"
    44  	routingV2FieldPolicy      = "Policy"
    45  	routingV2FieldConfig      = "Config"
    46  	routingV2FieldEnable      = "Enable"
    47  	routingV2FieldRevision    = "Revision"
    48  	routingV2FieldCreateTime  = "CreateTime"
    49  	routingV2FieldModifyTime  = "ModifyTime"
    50  	routingV2FieldEnableTime  = "EnableTime"
    51  	routingV2FieldValid       = "Valid"
    52  	routingV2FieldPriority    = "Priority"
    53  	routingV2FieldDescription = "Description"
    54  )
    55  
    56  type routingStoreV2 struct {
    57  	handler BoltHandler
    58  }
    59  
    60  // CreateRoutingConfigV2 新增一个路由配置
    61  func (r *routingStoreV2) CreateRoutingConfigV2(conf *model.RouterConfig) error {
    62  	if conf.ID == "" || conf.Revision == "" {
    63  		log.Errorf("[Store][boltdb] create routing config v2 missing id or revision")
    64  		return store.NewStatusError(store.EmptyParamsErr, "missing id or revision")
    65  	}
    66  	if conf.Policy == "" || conf.Config == "" {
    67  		log.Errorf("[Store][boltdb] create routing config v2 missing params")
    68  		return store.NewStatusError(store.EmptyParamsErr, "missing some params")
    69  	}
    70  
    71  	return r.handler.Execute(true, func(tx *bolt.Tx) error {
    72  		return r.createRoutingConfigV2(tx, conf)
    73  	})
    74  }
    75  
    76  // cleanRoutingConfig 从数据库彻底清理路由配置
    77  func (r *routingStoreV2) cleanRoutingConfig(tx *bolt.Tx, ruleID string) error {
    78  	err := deleteValues(tx, tblNameRoutingV2, []string{ruleID})
    79  	if err != nil {
    80  		log.Errorf("[Store][boltdb] delete invalid route config v2 error, %v", err)
    81  		return err
    82  	}
    83  	return nil
    84  }
    85  
    86  func (r *routingStoreV2) CreateRoutingConfigV2Tx(tx store.Tx, conf *model.RouterConfig) error {
    87  	if tx == nil {
    88  		return errors.New("transaction is nil")
    89  	}
    90  
    91  	dbTx := tx.GetDelegateTx().(*bolt.Tx)
    92  	return r.createRoutingConfigV2(dbTx, conf)
    93  }
    94  
    95  func (r *routingStoreV2) createRoutingConfigV2(tx *bolt.Tx, conf *model.RouterConfig) error {
    96  	if err := r.cleanRoutingConfig(tx, conf.ID); err != nil {
    97  		return err
    98  	}
    99  
   100  	currTime := time.Now()
   101  	conf.CreateTime = currTime
   102  	conf.ModifyTime = currTime
   103  	conf.EnableTime = time.Time{}
   104  	conf.Valid = true
   105  
   106  	if conf.Enable {
   107  		conf.EnableTime = time.Now()
   108  	} else {
   109  		conf.EnableTime = time.Time{}
   110  	}
   111  
   112  	err := saveValue(tx, tblNameRoutingV2, conf.ID, conf)
   113  	if err != nil {
   114  		log.Errorf("[Store][boltdb] add routing config v2 to kv error, %v", err)
   115  		return err
   116  	}
   117  	return nil
   118  }
   119  
   120  // UpdateRoutingConfigV2 更新一个路由配置
   121  func (r *routingStoreV2) UpdateRoutingConfigV2(conf *model.RouterConfig) error {
   122  	if conf.ID == "" || conf.Revision == "" {
   123  		log.Errorf("[Store][boltdb] update routing config v2 missing id or revision")
   124  		return store.NewStatusError(store.EmptyParamsErr, "missing id or revision")
   125  	}
   126  	if conf.Policy == "" || conf.Config == "" {
   127  		log.Errorf("[Store][boltdb] create routing config v2 missing params")
   128  		return store.NewStatusError(store.EmptyParamsErr, "missing some params")
   129  	}
   130  
   131  	return r.handler.Execute(true, func(tx *bolt.Tx) error {
   132  		return r.updateRoutingConfigV2Tx(tx, conf)
   133  	})
   134  }
   135  
   136  func (r *routingStoreV2) UpdateRoutingConfigV2Tx(tx store.Tx, conf *model.RouterConfig) error {
   137  	if tx == nil {
   138  		return errors.New("tx is nil")
   139  	}
   140  
   141  	dbTx := tx.GetDelegateTx().(*bolt.Tx)
   142  	return r.updateRoutingConfigV2Tx(dbTx, conf)
   143  }
   144  
   145  func (r *routingStoreV2) updateRoutingConfigV2Tx(tx *bolt.Tx, conf *model.RouterConfig) error {
   146  	properties := make(map[string]interface{})
   147  	properties[routingV2FieldEnable] = conf.Enable
   148  	properties[routingV2FieldName] = conf.Name
   149  	properties[routingV2FieldPolicy] = conf.Policy
   150  	properties[routingV2FieldConfig] = conf.Config
   151  	properties[routingV2FieldPriority] = conf.Priority
   152  	properties[routingV2FieldRevision] = conf.Revision
   153  	properties[routingV2FieldDescription] = conf.Description
   154  	properties[routingV2FieldModifyTime] = time.Now()
   155  
   156  	err := updateValue(tx, tblNameRoutingV2, conf.ID, properties)
   157  	if err != nil {
   158  		log.Errorf("[Store][boltdb] update route config v2 to kv error, %v", err)
   159  		return err
   160  	}
   161  	return nil
   162  }
   163  
   164  // EnableRouting
   165  func (r *routingStoreV2) EnableRouting(conf *model.RouterConfig) error {
   166  	if conf.ID == "" || conf.Revision == "" {
   167  		return errors.New("[Store][database] enable routing config v2 missing some params")
   168  	}
   169  
   170  	if conf.Enable {
   171  		conf.EnableTime = time.Now()
   172  	} else {
   173  		conf.EnableTime = time.Time{}
   174  	}
   175  
   176  	properties := make(map[string]interface{})
   177  	properties[routingV2FieldEnable] = conf.Enable
   178  	properties[routingV2FieldEnableTime] = conf.EnableTime
   179  	properties[routingV2FieldRevision] = conf.Revision
   180  	properties[routingV2FieldModifyTime] = time.Now()
   181  
   182  	err := r.handler.UpdateValue(tblNameRoutingV2, conf.ID, properties)
   183  	if err != nil {
   184  		log.Errorf("[Store][boltdb] enable route config v2 to kv error, %v", err)
   185  		return err
   186  	}
   187  	return nil
   188  }
   189  
   190  // DeleteRoutingConfigV2 删除一个路由配置
   191  func (r *routingStoreV2) DeleteRoutingConfigV2(ruleID string) error {
   192  	if ruleID == "" {
   193  		log.Errorf("[Store][boltdb] update routing config v2 missing id")
   194  		return store.NewStatusError(store.EmptyParamsErr, "missing id")
   195  	}
   196  	properties := make(map[string]interface{})
   197  	properties[routingV2FieldValid] = false
   198  	properties[routingV2FieldModifyTime] = time.Now()
   199  
   200  	err := r.handler.UpdateValue(tblNameRoutingV2, ruleID, properties)
   201  	if err != nil {
   202  		log.Errorf("[Store][boltdb] update route config v2 to kv error, %v", err)
   203  		return err
   204  	}
   205  	return nil
   206  }
   207  
   208  // GetRoutingConfigsV2ForCache 通过mtime拉取增量的路由配置信息
   209  // 此方法用于 cache 增量更新,需要注意 mtime 应为数据库时间戳
   210  func (r *routingStoreV2) GetRoutingConfigsV2ForCache(mtime time.Time, firstUpdate bool) ([]*model.RouterConfig, error) {
   211  	if firstUpdate {
   212  		mtime = time.Time{}
   213  	}
   214  
   215  	fields := []string{routingV2FieldModifyTime}
   216  
   217  	routes, err := r.handler.LoadValuesByFilter(tblNameRoutingV2, fields, &model.RouterConfig{},
   218  		func(m map[string]interface{}) bool {
   219  			rMtime, ok := m[routingV2FieldModifyTime]
   220  			if !ok {
   221  				return false
   222  			}
   223  			routeMtime := rMtime.(time.Time)
   224  			return !routeMtime.Before(mtime)
   225  		})
   226  	if err != nil {
   227  		log.Errorf("[Store][boltdb] load route config v2 from kv error, %v", err)
   228  		return nil, err
   229  	}
   230  
   231  	return toRouteConfV2(routes), nil
   232  }
   233  
   234  func toRouteConfV2(m map[string]interface{}) []*model.RouterConfig {
   235  	var routeConf []*model.RouterConfig
   236  	for _, r := range m {
   237  		routeConf = append(routeConf, r.(*model.RouterConfig))
   238  	}
   239  
   240  	return routeConf
   241  }
   242  
   243  // GetRoutingConfigV2WithID 根据服务ID拉取路由配置
   244  func (r *routingStoreV2) GetRoutingConfigV2WithID(id string) (*model.RouterConfig, error) {
   245  	tx, err := r.handler.StartTx()
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  
   250  	boldTx := tx.GetDelegateTx().(*bolt.Tx)
   251  	defer func() {
   252  		_ = boldTx.Rollback()
   253  	}()
   254  
   255  	return r.getRoutingConfigV2WithIDTx(boldTx, id)
   256  }
   257  
   258  // GetRoutingConfigV2WithIDTx 根据服务ID拉取路由配置
   259  func (r *routingStoreV2) GetRoutingConfigV2WithIDTx(tx store.Tx, id string) (*model.RouterConfig, error) {
   260  
   261  	if tx == nil {
   262  		return nil, errors.New("tx is nil")
   263  	}
   264  
   265  	boldTx := tx.GetDelegateTx().(*bolt.Tx)
   266  	return r.getRoutingConfigV2WithIDTx(boldTx, id)
   267  }
   268  
   269  func (r *routingStoreV2) getRoutingConfigV2WithIDTx(tx *bolt.Tx, id string) (*model.RouterConfig, error) {
   270  	ret := make(map[string]interface{})
   271  	if err := loadValues(tx, tblNameRoutingV2, []string{id}, &model.RouterConfig{}, ret); err != nil {
   272  		log.Error("[Store][boltdb] load route config v2 from kv", zap.String("routing-id", id), zap.Error(err))
   273  		return nil, err
   274  	}
   275  
   276  	if len(ret) == 0 {
   277  		return nil, nil
   278  	}
   279  
   280  	if len(ret) > 1 {
   281  		return nil, ErrMultipleRoutingV2Found
   282  	}
   283  
   284  	val := ret[id].(*model.RouterConfig)
   285  	if !val.Valid {
   286  		return nil, nil
   287  	}
   288  
   289  	return val, nil
   290  }