github.com/polarismesh/polaris@v1.17.8/cache/api/types.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 api
    19  
    20  import (
    21  	"runtime"
    22  	"sync"
    23  	"time"
    24  
    25  	apisecurity "github.com/polarismesh/specification/source/go/api/v1/security"
    26  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    27  	apitraffic "github.com/polarismesh/specification/source/go/api/v1/traffic_manage"
    28  
    29  	"github.com/polarismesh/polaris/common/metrics"
    30  	"github.com/polarismesh/polaris/common/model"
    31  	"github.com/polarismesh/polaris/store"
    32  )
    33  
    34  const (
    35  	// NamespaceName cache name
    36  	NamespaceName = "namespace"
    37  	// ServiceName
    38  	ServiceName = "service"
    39  	// InstanceName instance name
    40  	InstanceName = "instance"
    41  	// L5Name l5 name
    42  	L5Name = "l5"
    43  	// RoutingConfigName router config name
    44  	RoutingConfigName = "routingConfig"
    45  	// RateLimitConfigName rate limit config name
    46  	RateLimitConfigName = "rateLimitConfig"
    47  	// CircuitBreakerName circuit breaker config name
    48  	CircuitBreakerName = "circuitBreakerConfig"
    49  	// FaultDetectRuleName fault detect config name
    50  	FaultDetectRuleName = "faultDetectRule"
    51  	// ConfigGroupCacheName config group config name
    52  	ConfigGroupCacheName = "configGroup"
    53  	// ConfigFileCacheName config file config name
    54  	ConfigFileCacheName = "configFile"
    55  	// ClientName client cache name
    56  	ClientName = "client"
    57  	// UsersName user data config name
    58  	UsersName = "users"
    59  	// StrategyRuleName strategy rule config name
    60  	StrategyRuleName = "strategyRule"
    61  )
    62  
    63  type CacheIndex int
    64  
    65  const (
    66  	// CacheNamespace int = iota
    67  	// CacheBusiness
    68  	CacheService CacheIndex = iota
    69  	CacheInstance
    70  	CacheRoutingConfig
    71  	CacheCL5
    72  	CacheRateLimit
    73  	CacheCircuitBreaker
    74  	CacheUser
    75  	CacheAuthStrategy
    76  	CacheNamespace
    77  	CacheClient
    78  	CacheConfigFile
    79  	CacheFaultDetector
    80  	CacheConfigGroup
    81  
    82  	CacheLast
    83  )
    84  
    85  // Cache 缓存接口
    86  type Cache interface {
    87  	// Initialize
    88  	Initialize(c map[string]interface{}) error
    89  	// AddListener 添加
    90  	AddListener(listeners []Listener)
    91  	// Update .
    92  	Update() error
    93  	// Clear .
    94  	Clear() error
    95  	// Name .
    96  	Name() string
    97  	// Close .
    98  	Close() error
    99  }
   100  
   101  // CacheManager
   102  type CacheManager interface {
   103  	// GetCacher
   104  	GetCacher(cacheIndex CacheIndex) Cache
   105  	// RegisterCacher
   106  	RegisterCacher(cacheIndex CacheIndex, item Cache)
   107  }
   108  
   109  type (
   110  	// NamespaceCache 命名空间的 Cache 接口
   111  	NamespaceCache interface {
   112  		Cache
   113  		// GetNamespace
   114  		GetNamespace(id string) *model.Namespace
   115  		// GetNamespacesByName
   116  		GetNamespacesByName(names []string) []*model.Namespace
   117  		// GetNamespaceList
   118  		GetNamespaceList() []*model.Namespace
   119  	}
   120  )
   121  
   122  type (
   123  	// ServiceIterProc 迭代回调函数
   124  	ServiceIterProc func(key string, value *model.Service) (bool, error)
   125  
   126  	// ServiceArgs 服务查询条件
   127  	ServiceArgs struct {
   128  		// Filter 普通服务字段条件
   129  		Filter map[string]string
   130  		// Metadata 元数据条件
   131  		Metadata map[string]string
   132  		// SvcIds 是否按照服务的ID进行等值查询
   133  		SvcIds map[string]struct{}
   134  		// WildName 是否进行名字的模糊匹配
   135  		WildName bool
   136  		// WildBusiness 是否进行业务的模糊匹配
   137  		WildBusiness bool
   138  		// WildNamespace 是否进行命名空间的模糊匹配
   139  		WildNamespace bool
   140  		// Namespace 条件中的命名空间
   141  		Namespace string
   142  		// Name 条件中的服务名
   143  		Name string
   144  		// EmptyCondition 是否是空条件,即只需要从所有服务或者某个命名空间下面的服务,进行不需要匹配的遍历,返回前面的服务即可
   145  		EmptyCondition bool
   146  	}
   147  
   148  	// ServiceCache 服务数据缓存接口
   149  	ServiceCache interface {
   150  		Cache
   151  		// GetNamespaceCntInfo Return to the service statistics according to the namespace,
   152  		// 	the count statistics and health instance statistics
   153  		GetNamespaceCntInfo(namespace string) model.NamespaceServiceCount
   154  		// GetAllNamespaces Return all namespaces
   155  		GetAllNamespaces() []string
   156  		// GetServiceByID According to ID query service information
   157  		GetServiceByID(id string) *model.Service
   158  		// GetServiceByName Inquiry service information according to service name
   159  		GetServiceByName(name string, namespace string) *model.Service
   160  		// IteratorServices Iterative Cache Service Information
   161  		IteratorServices(iterProc ServiceIterProc) error
   162  		// CleanNamespace Clear the cache of NameSpace
   163  		CleanNamespace(namespace string)
   164  		// GetServicesCount Get the number of services in the cache
   165  		GetServicesCount() int
   166  		// GetServiceByCl5Name Get the corresponding SID according to CL5name
   167  		GetServiceByCl5Name(cl5Name string) *model.Service
   168  		// GetServicesByFilter Serving the service filtering in the cache through Filter
   169  		GetServicesByFilter(serviceFilters *ServiceArgs,
   170  			instanceFilters *store.InstanceArgs, offset, limit uint32) (uint32, []*model.EnhancedService, error)
   171  		// ListServices get service list and revision by namespace
   172  		ListServices(ns string) (string, []*model.Service)
   173  		// ListAllServices get all service and revision
   174  		ListAllServices() (string, []*model.Service)
   175  		// ListServiceAlias list service link alias list
   176  		ListServiceAlias(namespace, name string) []*model.Service
   177  		// GetAliasFor get alias reference service info
   178  		GetAliasFor(name string, namespace string) *model.Service
   179  		// GetRevisionWorker .
   180  		GetRevisionWorker() ServiceRevisionWorker
   181  	}
   182  
   183  	// ServiceRevisionWorker
   184  	ServiceRevisionWorker interface {
   185  		// Notify
   186  		Notify(serviceID string, valid bool)
   187  		// GetServiceRevisionCount
   188  		GetServiceRevisionCount() int
   189  		// GetServiceInstanceRevision
   190  		GetServiceInstanceRevision(serviceID string) string
   191  	}
   192  )
   193  
   194  type (
   195  	// InstanceIterProc instance iter proc func
   196  	InstanceIterProc func(key string, value *model.Instance) (bool, error)
   197  
   198  	// InstanceCache 实例相关的缓存接口
   199  	InstanceCache interface {
   200  		// Cache 公共缓存接口
   201  		Cache
   202  		// GetInstance 根据实例ID获取实例数据
   203  		GetInstance(instanceID string) *model.Instance
   204  		// GetInstancesByServiceID 根据服务名获取实例,先查找服务名对应的服务ID,再找实例列表
   205  		GetInstancesByServiceID(serviceID string) []*model.Instance
   206  		// IteratorInstances 迭代
   207  		IteratorInstances(iterProc InstanceIterProc) error
   208  		// IteratorInstancesWithService 根据服务ID进行迭代
   209  		IteratorInstancesWithService(serviceID string, iterProc InstanceIterProc) error
   210  		// GetInstancesCount 获取instance的个数
   211  		GetInstancesCount() int
   212  		// GetInstancesCountByServiceID 根据服务ID获取实例数
   213  		GetInstancesCountByServiceID(serviceID string) model.InstanceCount
   214  		// GetServicePorts 根据服务ID获取端口号
   215  		GetServicePorts(serviceID string) []*model.ServicePort
   216  		// GetInstanceLabels Get the label of all instances under a service
   217  		GetInstanceLabels(serviceID string) *apiservice.InstanceLabels
   218  		// QueryInstances query instance for OSS
   219  		QueryInstances(filter, metaFilter map[string]string, offset, limit uint32) (uint32, []*model.Instance, error)
   220  	}
   221  )
   222  
   223  type (
   224  	// FaultDetectCache  fault detect rule cache service
   225  	FaultDetectCache interface {
   226  		Cache
   227  		// GetFaultDetectConfig 根据ServiceID获取探测配置
   228  		GetFaultDetectConfig(svcName string, namespace string) *model.ServiceWithFaultDetectRules
   229  	}
   230  )
   231  
   232  type (
   233  	// RoutingArgs Routing rules query parameters
   234  	RoutingArgs struct {
   235  		// Filter extend filter params
   236  		Filter map[string]string
   237  		// ID route rule id
   238  		ID string
   239  		// Name route rule name
   240  		Name string
   241  		// Service service name
   242  		Service string
   243  		// Namespace namesapce
   244  		Namespace string
   245  		// SourceService source service name
   246  		SourceService string
   247  		// SourceNamespace source service namespace
   248  		SourceNamespace string
   249  		// DestinationService destination service name
   250  		DestinationService string
   251  		// DestinationNamespace destination service namespace
   252  		DestinationNamespace string
   253  		// Enable
   254  		Enable *bool
   255  		// Offset
   256  		Offset uint32
   257  		// Limit
   258  		Limit uint32
   259  		// OrderField Sort field
   260  		OrderField string
   261  		// OrderType Sorting rules
   262  		OrderType string
   263  	}
   264  
   265  	// RouterRuleIterProc Method definition of routing rules
   266  	RouterRuleIterProc func(key string, value *model.ExtendRouterConfig)
   267  
   268  	// RoutingConfigCache Cache interface configured by routing
   269  	RoutingConfigCache interface {
   270  		Cache
   271  		// GetRouterConfig Obtain routing configuration based on serviceid
   272  		GetRouterConfig(id, service, namespace string) (*apitraffic.Routing, error)
   273  		// GetRouterConfig Obtain routing configuration based on serviceid
   274  		GetRouterConfigV2(id, service, namespace string) (*apitraffic.Routing, error)
   275  		// GetRoutingConfigCount Get the total number of routing configuration cache
   276  		GetRoutingConfigCount() int
   277  		// QueryRoutingConfigsV2 Query Route Configuration List
   278  		QueryRoutingConfigsV2(args *RoutingArgs) (uint32, []*model.ExtendRouterConfig, error)
   279  		// ListRouterRule list all router rule
   280  		ListRouterRule(service, namespace string) []*model.ExtendRouterConfig
   281  		// IsConvertFromV1 Whether the current routing rules are converted from the V1 rule
   282  		IsConvertFromV1(id string) (string, bool)
   283  		// IteratorRouterRule iterator router rule
   284  		IteratorRouterRule(iterProc RouterRuleIterProc)
   285  	}
   286  )
   287  
   288  type (
   289  	// RateLimitRuleArgs ratelimit rules query parameters
   290  	RateLimitRuleArgs struct {
   291  		// Filter extend filter params
   292  		Filter map[string]string
   293  		// ID route rule id
   294  		ID string
   295  		// Name route rule name
   296  		Name string
   297  		// Service service name
   298  		Service string
   299  		// Namespace namesapce
   300  		Namespace string
   301  		// Disable *bool
   302  		Disable *bool
   303  		// Offset
   304  		Offset uint32
   305  		// Limit
   306  		Limit uint32
   307  		// OrderField Sort field
   308  		OrderField string
   309  		// OrderType Sorting rules
   310  		OrderType string
   311  	}
   312  
   313  	// RateLimitIterProc rate limit iter func
   314  	RateLimitIterProc func(rateLimit *model.RateLimit)
   315  
   316  	// RateLimitCache rateLimit的cache接口
   317  	RateLimitCache interface {
   318  		Cache
   319  		// GetRateLimit 根据serviceID进行迭代回调
   320  		IteratorRateLimit(rateLimitIterProc RateLimitIterProc)
   321  		// GetRateLimitRules 根据serviceID获取限流数据
   322  		GetRateLimitRules(serviceKey model.ServiceKey) ([]*model.RateLimit, string)
   323  		// QueryRateLimitRules
   324  		QueryRateLimitRules(args RateLimitRuleArgs) (uint32, []*model.RateLimit, error)
   325  		// GetRateLimitsCount 获取限流规则总数
   326  		GetRateLimitsCount() int
   327  	}
   328  )
   329  
   330  type (
   331  	// L5Cache L5的cache接口
   332  	L5Cache interface {
   333  		Cache
   334  		// GetRouteByIP 根据IP获取访问关系
   335  		GetRouteByIP(ip uint32) []*model.Route
   336  		// CheckRouteExisted 检查IP对应的SID是否存在访问关系
   337  		CheckRouteExisted(ip uint32, modID uint32, cmdID uint32) bool
   338  		// GetPolicy 获取有状态路由信息policy
   339  		GetPolicy(modID uint32) *model.Policy
   340  		// GetSection 获取有状态路由信息policy
   341  		GetSection(modeID uint32) []*model.Section
   342  		// GetIPConfig 获取IpConfig
   343  		GetIPConfig(ip uint32) *model.IPConfig
   344  	}
   345  )
   346  
   347  type (
   348  	// CircuitBreakerCache  circuitBreaker配置的cache接口
   349  	CircuitBreakerCache interface {
   350  		Cache
   351  		// GetCircuitBreakerConfig 根据ServiceID获取熔断配置
   352  		GetCircuitBreakerConfig(svcName string, namespace string) *model.ServiceWithCircuitBreakerRules
   353  	}
   354  )
   355  
   356  type (
   357  	BaseConfigArgs struct {
   358  		// Namespace
   359  		Namespace string
   360  		// Group
   361  		Group string
   362  		// Offset
   363  		Offset uint32
   364  		// Limit
   365  		Limit uint32
   366  		// OrderField Sort field
   367  		OrderField string
   368  		// OrderType Sorting rules
   369  		OrderType string
   370  	}
   371  
   372  	ConfigFileArgs struct {
   373  		BaseConfigArgs
   374  		FileName string
   375  		Metadata map[string]string
   376  	}
   377  
   378  	ConfigReleaseArgs struct {
   379  		BaseConfigArgs
   380  		// FileName
   381  		FileName string
   382  		// ReleaseName
   383  		ReleaseName string
   384  		// OnlyActive
   385  		OnlyActive bool
   386  		// Metadata
   387  		Metadata map[string]string
   388  		// NoPage
   389  		NoPage bool
   390  	}
   391  
   392  	// ConfigGroupArgs
   393  	ConfigGroupArgs struct {
   394  		Namespace  string
   395  		Name       string
   396  		Business   string
   397  		Department string
   398  		Metadata   map[string]string
   399  		Offset     uint32
   400  		Limit      uint32
   401  		// OrderField Sort field
   402  		OrderField string
   403  		// OrderType Sorting rules
   404  		OrderType string
   405  	}
   406  
   407  	// ConfigGroupCache file cache
   408  	ConfigGroupCache interface {
   409  		Cache
   410  		// GetGroupByName
   411  		GetGroupByName(namespace, name string) *model.ConfigFileGroup
   412  		// GetGroupByID
   413  		GetGroupByID(id uint64) *model.ConfigFileGroup
   414  		// Query
   415  		Query(args *ConfigGroupArgs) (uint32, []*model.ConfigFileGroup, error)
   416  	}
   417  
   418  	// ConfigFileCache file cache
   419  	ConfigFileCache interface {
   420  		Cache
   421  		// GetActiveRelease
   422  		GetGroupActiveReleases(namespace, group string) ([]*model.ConfigFileRelease, string)
   423  		// GetActiveRelease
   424  		GetActiveRelease(namespace, group, fileName string) *model.ConfigFileRelease
   425  		// GetRelease
   426  		GetRelease(key model.ConfigFileReleaseKey) *model.ConfigFileRelease
   427  		// QueryReleases
   428  		QueryReleases(args *ConfigReleaseArgs) (uint32, []*model.SimpleConfigFileRelease, error)
   429  	}
   430  )
   431  
   432  type (
   433  	// UserCache User information cache
   434  	UserCache interface {
   435  		Cache
   436  		// GetAdmin 获取管理员信息
   437  		GetAdmin() *model.User
   438  		// GetUserByID
   439  		GetUserByID(id string) *model.User
   440  		// GetUserByName
   441  		GetUserByName(name, ownerName string) *model.User
   442  		// GetUserGroup
   443  		GetGroup(id string) *model.UserGroupDetail
   444  		// IsUserInGroup 判断 userid 是否在对应的 group 中
   445  		IsUserInGroup(userId, groupId string) bool
   446  		// IsOwner
   447  		IsOwner(id string) bool
   448  		// GetUserLinkGroupIds
   449  		GetUserLinkGroupIds(id string) []string
   450  	}
   451  
   452  	// StrategyCache is a cache for strategy rules.
   453  	StrategyCache interface {
   454  		Cache
   455  		// GetStrategyDetailsByUID
   456  		GetStrategyDetailsByUID(uid string) []*model.StrategyDetail
   457  		// GetStrategyDetailsByGroupID returns all strategy details of a group.
   458  		GetStrategyDetailsByGroupID(groupId string) []*model.StrategyDetail
   459  		// IsResourceLinkStrategy 该资源是否关联了鉴权策略
   460  		IsResourceLinkStrategy(resType apisecurity.ResourceType, resId string) bool
   461  		// IsResourceEditable 判断该资源是否可以操作
   462  		IsResourceEditable(principal model.Principal, resType apisecurity.ResourceType, resId string) bool
   463  		// ForceSync 强制同步鉴权策略到cache (串行)
   464  		ForceSync() error
   465  	}
   466  )
   467  
   468  type (
   469  
   470  	// ClientIterProc client iter proc func
   471  	ClientIterProc func(key string, value *model.Client) bool
   472  
   473  	// ClientCache 客户端的 Cache 接口
   474  	ClientCache interface {
   475  		Cache
   476  		// GetClient get client
   477  		GetClient(id string) *model.Client
   478  		// IteratorClients 迭代
   479  		IteratorClients(iterProc ClientIterProc)
   480  		// GetClientsByFilter Query client information
   481  		GetClientsByFilter(filters map[string]string, offset, limit uint32) (uint32, []*model.Client, error)
   482  	}
   483  )
   484  
   485  var (
   486  	// DefaultTimeDiff default time diff
   487  	DefaultTimeDiff = -5 * time.Second
   488  )
   489  
   490  // BaseCache 对于 Cache 中的一些 func 做统一实现,避免重复逻辑
   491  type BaseCache struct {
   492  	lock sync.RWMutex
   493  	// firtstUpdate Whether the cache is loaded for the first time
   494  	// this field can only make value on exec initialize/clean, and set it to false on exec update
   495  	firtstUpdate  bool
   496  	s             store.Store
   497  	lastFetchTime int64
   498  	lastMtimes    map[string]time.Time
   499  	Manager       *ListenerManager
   500  	CacheMgr      CacheManager
   501  }
   502  
   503  func NewBaseCache(s store.Store, cacheMgr CacheManager) *BaseCache {
   504  	c := &BaseCache{
   505  		s:        s,
   506  		CacheMgr: cacheMgr,
   507  	}
   508  
   509  	c.initialize()
   510  	return c
   511  }
   512  
   513  func (bc *BaseCache) initialize() {
   514  	bc.lock.Lock()
   515  	defer bc.lock.Unlock()
   516  
   517  	bc.lastFetchTime = 1
   518  	bc.firtstUpdate = true
   519  	bc.Manager = NewListenerManager()
   520  	bc.lastMtimes = map[string]time.Time{}
   521  }
   522  
   523  var (
   524  	zeroTime = time.Unix(0, 0)
   525  )
   526  
   527  func (bc *BaseCache) ResetLastMtime(label string) {
   528  	bc.lock.Lock()
   529  	defer bc.lock.Unlock()
   530  	bc.lastMtimes[label] = time.Unix(0, 0)
   531  }
   532  
   533  func (bc *BaseCache) ResetLastFetchTime() {
   534  	bc.lock.Lock()
   535  	defer bc.lock.Unlock()
   536  	bc.lastFetchTime = 1
   537  }
   538  
   539  func (bc *BaseCache) LastMtime(label string) time.Time {
   540  	bc.lock.RLock()
   541  	defer bc.lock.RUnlock()
   542  	v, ok := bc.lastMtimes[label]
   543  	if ok {
   544  		return v
   545  	}
   546  
   547  	return time.Unix(0, 0)
   548  }
   549  
   550  func (bc *BaseCache) LastFetchTime() time.Time {
   551  	lastTime := time.Unix(bc.lastFetchTime, 0)
   552  	tmp := lastTime.Add(DefaultTimeDiff)
   553  	if zeroTime.After(tmp) {
   554  		return lastTime
   555  	}
   556  	lastTime = tmp
   557  	return lastTime
   558  }
   559  
   560  // OriginLastFetchTime only for test
   561  func (bc *BaseCache) OriginLastFetchTime() time.Time {
   562  	lastTime := time.Unix(bc.lastFetchTime, 0)
   563  	return lastTime
   564  }
   565  
   566  func (bc *BaseCache) IsFirstUpdate() bool {
   567  	return bc.firtstUpdate
   568  }
   569  
   570  // update
   571  func (bc *BaseCache) DoCacheUpdate(name string, executor func() (map[string]time.Time, int64, error)) error {
   572  	if bc.IsFirstUpdate() {
   573  		log.Infof("[Cache][%s] begin run cache update work", name)
   574  	}
   575  
   576  	curStoreTime, err := bc.s.GetUnixSecond(0)
   577  	if err != nil {
   578  		curStoreTime = bc.lastFetchTime
   579  		log.Warnf("[Cache][%s] get store timestamp fail, skip update lastMtime, err : %v", name, err)
   580  	}
   581  	defer func() {
   582  		if err := recover(); err != nil {
   583  			var buf [4086]byte
   584  			n := runtime.Stack(buf[:], false)
   585  			log.Errorf("[Cache][%s] run cache update panic: %+v, stack\n%s\n", name, err, string(buf[:n]))
   586  		} else {
   587  			bc.lastFetchTime = curStoreTime
   588  		}
   589  	}()
   590  
   591  	start := time.Now()
   592  	lastMtimes, total, err := executor()
   593  	if err != nil {
   594  		return err
   595  	}
   596  
   597  	bc.lock.Lock()
   598  	defer bc.lock.Unlock()
   599  	if len(lastMtimes) != 0 {
   600  		if len(bc.lastMtimes) != 0 {
   601  			for label, lastMtime := range lastMtimes {
   602  				preLastMtime := bc.lastMtimes[label]
   603  				log.Infof("[Cache][%s] lastFetchTime %s, lastMtime update from %s to %s",
   604  					label, time.Unix(bc.lastFetchTime, 0), preLastMtime, lastMtime)
   605  			}
   606  		}
   607  		bc.lastMtimes = lastMtimes
   608  	}
   609  
   610  	if total >= 0 {
   611  		metrics.RecordCacheUpdateCost(time.Since(start), name, total)
   612  	}
   613  	bc.firtstUpdate = false
   614  	return nil
   615  }
   616  
   617  func (bc *BaseCache) Clear() {
   618  	bc.lock.Lock()
   619  	defer bc.lock.Unlock()
   620  	bc.lastMtimes = make(map[string]time.Time)
   621  	bc.lastFetchTime = 1
   622  	bc.firtstUpdate = true
   623  }
   624  
   625  // AddListener 添加
   626  func (bc *BaseCache) AddListener(listeners []Listener) {
   627  	bc.lock.Lock()
   628  	defer bc.lock.Unlock()
   629  	bc.Manager.Append(listeners...)
   630  }
   631  
   632  func (bc *BaseCache) Close() error {
   633  	return nil
   634  }