github.com/polarismesh/polaris@v1.17.8/store/boltdb/client.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  	"encoding/json"
    22  	"time"
    23  
    24  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    25  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    26  	bolt "go.etcd.io/bbolt"
    27  	"go.uber.org/zap"
    28  
    29  	"github.com/polarismesh/polaris/common/model"
    30  	commontime "github.com/polarismesh/polaris/common/time"
    31  	"github.com/polarismesh/polaris/common/utils"
    32  )
    33  
    34  const (
    35  	tblClient string = "client"
    36  
    37  	ClientFieldHost       string = "Host"
    38  	ClientFieldType       string = "Type"
    39  	ClientFieldVersion    string = "Version"
    40  	ClientFieldLocation   string = "Location"
    41  	ClientFieldId         string = "Id"
    42  	ClientFieldStatArrStr string = "StatArrStr"
    43  	ClientFieldCtime      string = "Ctime"
    44  	ClientFieldMtime      string = "Mtime"
    45  	ClientFieldValid      string = "Valid"
    46  )
    47  
    48  type clientObject struct {
    49  	Host       string
    50  	Type       string
    51  	Version    string
    52  	Location   map[string]string
    53  	Id         string
    54  	Ctime      time.Time
    55  	Mtime      time.Time
    56  	StatArrStr string
    57  	Valid      bool
    58  }
    59  
    60  type clientStore struct {
    61  	handler BoltHandler
    62  }
    63  
    64  // BatchAddClients insert the client info
    65  func (cs *clientStore) BatchAddClients(clients []*model.Client) error {
    66  	if err := cs.handler.Execute(true, func(tx *bolt.Tx) error {
    67  		for i := range clients {
    68  			client := clients[i]
    69  			saveVal, err := convertToClientObject(client)
    70  			if err != nil {
    71  				return err
    72  			}
    73  
    74  			if err := saveValue(tx, tblClient, saveVal.Id, saveVal); err != nil {
    75  				return err
    76  			}
    77  		}
    78  		return nil
    79  	}); err != nil {
    80  		log.Error("[Client] batch add clients", zap.Error(err))
    81  		return err
    82  	}
    83  
    84  	return nil
    85  }
    86  
    87  // BatchDeleteClients delete the client info
    88  func (cs *clientStore) BatchDeleteClients(ids []string) error {
    89  	err := cs.handler.Execute(true, func(tx *bolt.Tx) error {
    90  		for i := range ids {
    91  			properties := make(map[string]interface{})
    92  			properties[ClientFieldValid] = false
    93  			properties[ClientFieldMtime] = time.Now()
    94  
    95  			if err := updateValue(tx, tblClient, ids[i], properties); err != nil {
    96  				log.Error("[Client] batch delete clients", zap.Error(err))
    97  				return err
    98  			}
    99  		}
   100  
   101  		return nil
   102  	})
   103  
   104  	return err
   105  }
   106  
   107  // GetMoreClients 根据mtime获取增量clients,返回所有store的变更信息
   108  func (cs *clientStore) GetMoreClients(mtime time.Time, firstUpdate bool) (map[string]*model.Client, error) {
   109  	fields := []string{ClientFieldMtime}
   110  	ret, err := cs.handler.LoadValuesByFilter(tblClient, fields, &clientObject{}, func(m map[string]interface{}) bool {
   111  		if firstUpdate {
   112  			return true
   113  		}
   114  		return m[ClientFieldMtime].(time.Time).After(mtime)
   115  	})
   116  
   117  	if err != nil {
   118  		log.Error("[Client] get more clients for cache", zap.Error(err))
   119  		return nil, err
   120  	}
   121  
   122  	clients := make(map[string]*model.Client, len(ret))
   123  	for k, v := range ret {
   124  		client, err := convertToModelClient(v.(*clientObject))
   125  		if err != nil {
   126  			log.Error("[Client] convert clientObject to model.Client", zap.Error(err))
   127  			return nil, err
   128  		}
   129  
   130  		clients[k] = client
   131  	}
   132  
   133  	return clients, nil
   134  }
   135  
   136  func convertToClientObject(client *model.Client) (*clientObject, error) {
   137  	stat := client.Proto().Stat
   138  	data, err := json.Marshal(stat)
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	tn := time.Now()
   143  	return &clientObject{
   144  		Host:    client.Proto().GetHost().GetValue(),
   145  		Type:    client.Proto().GetType().String(),
   146  		Version: client.Proto().GetVersion().GetValue(),
   147  		Location: map[string]string{
   148  			"region": client.Proto().GetLocation().GetRegion().GetValue(),
   149  			"zone":   client.Proto().GetLocation().GetZone().GetValue(),
   150  			"campus": client.Proto().GetLocation().GetCampus().GetValue(),
   151  		},
   152  		Id:         client.Proto().GetId().GetValue(),
   153  		Ctime:      tn,
   154  		Mtime:      tn,
   155  		StatArrStr: string(data),
   156  		Valid:      true,
   157  	}, nil
   158  }
   159  
   160  func convertToModelClient(client *clientObject) (*model.Client, error) {
   161  	stat := make([]*apiservice.StatInfo, 0, 4)
   162  	err := json.Unmarshal([]byte(client.StatArrStr), &stat)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  
   167  	c := &apiservice.Client{
   168  		Id:      utils.NewStringValue(client.Id),
   169  		Host:    utils.NewStringValue(client.Host),
   170  		Type:    apiservice.Client_ClientType(apiservice.Client_ClientType_value[client.Type]),
   171  		Version: utils.NewStringValue(client.Version),
   172  		Ctime:   utils.NewStringValue(commontime.Time2String(client.Ctime)),
   173  		Mtime:   utils.NewStringValue(commontime.Time2String(client.Mtime)),
   174  		Location: &apimodel.Location{
   175  			Region: utils.NewStringValue(client.Location["region"]),
   176  			Zone:   utils.NewStringValue(client.Location["zone"]),
   177  			Campus: utils.NewStringValue(client.Location["campus"]),
   178  		},
   179  		Stat: stat,
   180  	}
   181  
   182  	mc := model.NewClient(c)
   183  	mc.SetValid(client.Valid)
   184  	return mc, nil
   185  }