github.com/polarismesh/polaris@v1.17.8/store/mysql/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 sqldb
    19  
    20  import (
    21  	"database/sql"
    22  	"errors"
    23  	"fmt"
    24  	"time"
    25  
    26  	"go.uber.org/zap"
    27  
    28  	"github.com/polarismesh/polaris/common/model"
    29  	"github.com/polarismesh/polaris/store"
    30  )
    31  
    32  var _ store.RoutingConfigStoreV2 = (*routingConfigStoreV2)(nil)
    33  
    34  // RoutingConfigStoreV2 impl
    35  type routingConfigStoreV2 struct {
    36  	master *BaseDB
    37  	slave  *BaseDB
    38  }
    39  
    40  // CreateRoutingConfigV2 Add a new routing configuration
    41  func (r *routingConfigStoreV2) CreateRoutingConfigV2(conf *model.RouterConfig) error {
    42  	if conf.ID == "" || conf.Revision == "" {
    43  		log.Errorf("[Store][boltdb] create routing config v2 missing id or revision")
    44  		return store.NewStatusError(store.EmptyParamsErr, "missing id or revision")
    45  	}
    46  	if conf.Policy == "" || conf.Config == "" {
    47  		log.Errorf("[Store][boltdb] create routing config v2 missing params")
    48  		return store.NewStatusError(store.EmptyParamsErr, "missing some params")
    49  	}
    50  
    51  	err := RetryTransaction("CreateRoutingConfigV2", func() error {
    52  		tx, err := r.master.Begin()
    53  		if err != nil {
    54  			return err
    55  		}
    56  
    57  		defer func() {
    58  			_ = tx.Rollback()
    59  		}()
    60  		if err := r.createRoutingConfigV2Tx(tx, conf); err != nil {
    61  			return err
    62  		}
    63  
    64  		if err := tx.Commit(); err != nil {
    65  			log.Errorf("[Store][database] create routing config v2(%+v) commit: %s", conf, err.Error())
    66  			return store.Error(err)
    67  		}
    68  
    69  		return nil
    70  	})
    71  
    72  	return store.Error(err)
    73  }
    74  
    75  func (r *routingConfigStoreV2) CreateRoutingConfigV2Tx(tx store.Tx, conf *model.RouterConfig) error {
    76  	if tx == nil {
    77  		return errors.New("tx is nil")
    78  	}
    79  
    80  	dbTx := tx.GetDelegateTx().(*BaseTx)
    81  	return r.createRoutingConfigV2Tx(dbTx, conf)
    82  }
    83  
    84  func (r *routingConfigStoreV2) createRoutingConfigV2Tx(tx *BaseTx, conf *model.RouterConfig) error {
    85  	// 删除无效的数据
    86  	if _, err := tx.Exec("DELETE FROM routing_config_v2 WHERE id = ? AND flag = 1", conf.ID); err != nil {
    87  		log.Errorf("[Store][database] create routing v2(%+v) err: %s", conf, err.Error())
    88  		return store.Error(err)
    89  	}
    90  
    91  	insertSQL := "INSERT INTO routing_config_v2(id, namespace, name, policy, config, enable, " +
    92  		" priority, revision, description, ctime, mtime, etime) VALUES (?,?,?,?,?,?,?,?,?,sysdate(),sysdate(),%s)"
    93  
    94  	var enable int
    95  	if conf.Enable {
    96  		enable = 1
    97  		insertSQL = fmt.Sprintf(insertSQL, "sysdate()")
    98  	} else {
    99  		enable = 0
   100  		insertSQL = fmt.Sprintf(insertSQL, emptyEnableTime)
   101  	}
   102  
   103  	log.Debug("[Store][database] create routing v2", zap.String("sql", insertSQL))
   104  
   105  	if _, err := tx.Exec(insertSQL, conf.ID, conf.Namespace, conf.Name, conf.Policy,
   106  		conf.Config, enable, conf.Priority, conf.Revision, conf.Description); err != nil {
   107  		log.Errorf("[Store][database] create routing v2(%+v) err: %s", conf, err.Error())
   108  		return store.Error(err)
   109  	}
   110  	return nil
   111  }
   112  
   113  // UpdateRoutingConfigV2 Update a routing configuration
   114  func (r *routingConfigStoreV2) UpdateRoutingConfigV2(conf *model.RouterConfig) error {
   115  
   116  	tx, err := r.master.Begin()
   117  	if err != nil {
   118  		return err
   119  	}
   120  
   121  	defer func() {
   122  		_ = tx.Rollback()
   123  	}()
   124  
   125  	if err := r.updateRoutingConfigV2Tx(tx, conf); err != nil {
   126  		return err
   127  	}
   128  
   129  	if err := tx.Commit(); err != nil {
   130  		log.Errorf("[Store][database] update routing config v2(%+v) commit: %s", conf, err.Error())
   131  		return store.Error(err)
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func (r *routingConfigStoreV2) UpdateRoutingConfigV2Tx(tx store.Tx, conf *model.RouterConfig) error {
   138  	if tx == nil {
   139  		return errors.New("tx is nil")
   140  	}
   141  
   142  	dbTx := tx.GetDelegateTx().(*BaseTx)
   143  	return r.updateRoutingConfigV2Tx(dbTx, conf)
   144  }
   145  
   146  func (r *routingConfigStoreV2) updateRoutingConfigV2Tx(tx *BaseTx, conf *model.RouterConfig) error {
   147  	if conf.ID == "" || conf.Revision == "" {
   148  		log.Errorf("[Store][database] update routing config v2 missing id or revision")
   149  		return store.NewStatusError(store.EmptyParamsErr, "missing id or revision")
   150  	}
   151  	if conf.Policy == "" || conf.Config == "" {
   152  		log.Errorf("[Store][boltdb] create routing config v2 missing params")
   153  		return store.NewStatusError(store.EmptyParamsErr, "missing some params")
   154  	}
   155  
   156  	str := "update routing_config_v2 set name = ?, policy = ?, config = ?, revision = ?, priority = ?, " +
   157  		" description = ?, mtime = sysdate() where id = ?"
   158  	if _, err := tx.Exec(str, conf.Name, conf.Policy, conf.Config, conf.Revision, conf.Priority, conf.Description,
   159  		conf.ID); err != nil {
   160  		log.Errorf("[Store][database] update routing config v2(%+v) exec err: %s", conf, err.Error())
   161  		return store.Error(err)
   162  	}
   163  	return nil
   164  }
   165  
   166  // EnableRateLimit Enable current limit rules
   167  func (r *routingConfigStoreV2) EnableRouting(conf *model.RouterConfig) error {
   168  	if conf.ID == "" || conf.Revision == "" {
   169  		return errors.New("[Store][database] enable routing config v2 missing some params")
   170  	}
   171  
   172  	err := RetryTransaction("EnableRouting", func() error {
   173  		var (
   174  			enable   int
   175  			etimeStr string
   176  		)
   177  		if conf.Enable {
   178  			enable = 1
   179  			etimeStr = "sysdate()"
   180  		} else {
   181  			enable = 0
   182  			etimeStr = emptyEnableTime
   183  		}
   184  		str := fmt.Sprintf(
   185  			`update routing_config_v2 set enable = ?, revision = ?, mtime = sysdate(), etime=%s where id = ?`, etimeStr)
   186  		if _, err := r.master.Exec(str, enable, conf.Revision, conf.ID); err != nil {
   187  			log.Errorf("[Store][database] update outing config v2(%+v), sql %s, err: %s", conf, str, err)
   188  			return err
   189  		}
   190  
   191  		return nil
   192  	})
   193  
   194  	return store.Error(err)
   195  }
   196  
   197  // DeleteRoutingConfigV2 Delete a routing configuration
   198  func (r *routingConfigStoreV2) DeleteRoutingConfigV2(ruleID string) error {
   199  
   200  	if ruleID == "" {
   201  		log.Errorf("[Store][database] delete routing config v2 missing service id")
   202  		return store.NewStatusError(store.EmptyParamsErr, "missing service id")
   203  	}
   204  
   205  	str := `update routing_config_v2 set flag = 1, mtime = sysdate() where id = ?`
   206  	if _, err := r.master.Exec(str, ruleID); err != nil {
   207  		log.Errorf("[Store][database] delete routing config v2(%s) err: %s", ruleID, err.Error())
   208  		return store.Error(err)
   209  	}
   210  
   211  	return nil
   212  }
   213  
   214  // GetRoutingConfigsV2ForCache Pull the incremental routing configuration information through mtime
   215  func (r *routingConfigStoreV2) GetRoutingConfigsV2ForCache(
   216  	mtime time.Time, firstUpdate bool) ([]*model.RouterConfig, error) {
   217  	str := `select id, name, policy, config, enable, revision, flag, priority, description,
   218  	unix_timestamp(ctime), unix_timestamp(mtime), unix_timestamp(etime)  
   219  	from routing_config_v2 where mtime > FROM_UNIXTIME(?) `
   220  
   221  	if firstUpdate {
   222  		str += " and flag != 1"
   223  	}
   224  	rows, err := r.slave.Query(str, timeToTimestamp(mtime))
   225  	if err != nil {
   226  		log.Errorf("[Store][database] query routing configs v2 with mtime err: %s", err.Error())
   227  		return nil, err
   228  	}
   229  	out, err := fetchRoutingConfigV2Rows(rows)
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  
   234  	return out, nil
   235  }
   236  
   237  // GetRoutingConfigV2WithID Pull the routing configuration according to the rules ID
   238  func (r *routingConfigStoreV2) GetRoutingConfigV2WithID(ruleID string) (*model.RouterConfig, error) {
   239  
   240  	tx, err := r.master.Begin()
   241  	if err != nil {
   242  		return nil, err
   243  	}
   244  
   245  	defer func() {
   246  		_ = tx.Rollback()
   247  	}()
   248  	return r.getRoutingConfigV2WithIDTx(tx, ruleID)
   249  }
   250  
   251  // GetRoutingConfigV2WithIDTx Pull the routing configuration according to the rules ID
   252  func (r *routingConfigStoreV2) GetRoutingConfigV2WithIDTx(tx store.Tx, ruleID string) (*model.RouterConfig, error) {
   253  
   254  	if tx == nil {
   255  		return nil, errors.New("transaction is nil")
   256  	}
   257  
   258  	dbTx := tx.GetDelegateTx().(*BaseTx)
   259  	return r.getRoutingConfigV2WithIDTx(dbTx, ruleID)
   260  }
   261  
   262  func (r *routingConfigStoreV2) getRoutingConfigV2WithIDTx(tx *BaseTx, ruleID string) (*model.RouterConfig, error) {
   263  
   264  	str := `select id, name, policy, config, enable, revision, flag, priority, description,
   265  	unix_timestamp(ctime), unix_timestamp(mtime), unix_timestamp(etime)
   266  	from routing_config_v2 
   267  	where id = ? and flag = 0`
   268  	rows, err := tx.Query(str, ruleID)
   269  	if err != nil {
   270  		log.Errorf("[Store][database] query routing v2 with id(%s) err: %s", ruleID, err.Error())
   271  		return nil, err
   272  	}
   273  
   274  	out, err := fetchRoutingConfigV2Rows(rows)
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  
   279  	if len(out) == 0 {
   280  		return nil, nil
   281  	}
   282  
   283  	return out[0], nil
   284  }
   285  
   286  // fetchRoutingConfigRows Read the data of the database and release ROWS
   287  func fetchRoutingConfigV2Rows(rows *sql.Rows) ([]*model.RouterConfig, error) {
   288  	defer rows.Close()
   289  	var out []*model.RouterConfig
   290  	for rows.Next() {
   291  		var (
   292  			entry               model.RouterConfig
   293  			flag, enable        int
   294  			ctime, mtime, etime int64
   295  		)
   296  
   297  		err := rows.Scan(&entry.ID, &entry.Name, &entry.Policy, &entry.Config, &enable, &entry.Revision,
   298  			&flag, &entry.Priority, &entry.Description, &ctime, &mtime, &etime)
   299  		if err != nil {
   300  			log.Errorf("[database][store] fetch routing config v2 scan err: %s", err.Error())
   301  			return nil, err
   302  		}
   303  
   304  		entry.CreateTime = time.Unix(ctime, 0)
   305  		entry.ModifyTime = time.Unix(mtime, 0)
   306  		entry.EnableTime = time.Unix(etime, 0)
   307  		entry.Valid = true
   308  		if flag == 1 {
   309  			entry.Valid = false
   310  		}
   311  		entry.Enable = enable == 1
   312  
   313  		out = append(out, &entry)
   314  	}
   315  	if err := rows.Err(); err != nil {
   316  		log.Errorf("[database][store] fetch routing config v2 next err: %s", err.Error())
   317  		return nil, err
   318  	}
   319  
   320  	return out, nil
   321  }