mirror of https://github.com/goharbor/harbor.git
141 lines
3.9 KiB
Go
141 lines
3.9 KiB
Go
// Copyright Project Harbor Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package cached
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/goharbor/harbor/src/lib/cache"
|
|
"github.com/goharbor/harbor/src/lib/errors"
|
|
"github.com/goharbor/harbor/src/lib/orm"
|
|
)
|
|
|
|
// innerCache is the default cache client,
|
|
// actually it is a wrapper for cache.LayerCache().
|
|
var innerCache cache.Cache = &cacheClient{}
|
|
|
|
// cacheClient is a interceptor for cache.CacheLayer, in order to implement specific
|
|
// case for cache layer.
|
|
type cacheClient struct{}
|
|
|
|
func (*cacheClient) Contains(ctx context.Context, key string) bool {
|
|
return cache.LayerCache().Contains(ctx, key)
|
|
}
|
|
|
|
func (*cacheClient) Delete(ctx context.Context, key string) error {
|
|
return cache.LayerCache().Delete(ctx, key)
|
|
}
|
|
|
|
func (*cacheClient) Fetch(ctx context.Context, key string, value interface{}) error {
|
|
return cache.LayerCache().Fetch(ctx, key, value)
|
|
}
|
|
|
|
func (*cacheClient) Ping(ctx context.Context) error {
|
|
return cache.LayerCache().Ping(ctx)
|
|
}
|
|
|
|
func (*cacheClient) Save(ctx context.Context, key string, value interface{}, expiration ...time.Duration) error {
|
|
// intercept here
|
|
// it should ignore save cache if this request is wrapped by orm.Transaction,
|
|
// because if tx rollback, we can not rollback cache,
|
|
// identify whether in transaction by checking the commitedKey in context.
|
|
// commitedKey is a context value which be injected in the transaction middleware.
|
|
if orm.HasCommittedKey(ctx) {
|
|
return nil
|
|
}
|
|
|
|
return cache.LayerCache().Save(ctx, key, value, expiration...)
|
|
}
|
|
|
|
func (*cacheClient) Scan(ctx context.Context, match string) (cache.Iterator, error) {
|
|
return cache.LayerCache().Scan(ctx, match)
|
|
}
|
|
|
|
var _ Manager = &BaseManager{}
|
|
|
|
// BaseManager is the base manager for cache and implement the cache manager interface.
|
|
type BaseManager struct {
|
|
resourceType string
|
|
cacheClient cache.Cache
|
|
}
|
|
|
|
// NewBaseManager returns a instance of base manager.
|
|
func NewBaseManager(resourceType string) *BaseManager {
|
|
return &BaseManager{
|
|
resourceType: resourceType,
|
|
cacheClient: innerCache,
|
|
}
|
|
}
|
|
|
|
// WithCacheClient can override the default cache client.
|
|
func (bm *BaseManager) WithCacheClient(cc cache.Cache) *BaseManager {
|
|
bm.cacheClient = cc
|
|
return bm
|
|
}
|
|
|
|
// CacheClient returns the cache client.
|
|
func (bm *BaseManager) CacheClient(_ context.Context) cache.Cache {
|
|
return bm.cacheClient
|
|
}
|
|
|
|
// ResourceType returns the resource type.
|
|
func (bm *BaseManager) ResourceType(_ context.Context) string {
|
|
return bm.resourceType
|
|
}
|
|
|
|
// CountCache returns current this resource occupied cache count.
|
|
func (bm *BaseManager) CountCache(ctx context.Context) (int64, error) {
|
|
var count int64
|
|
// prefix is resource type
|
|
iter, err := bm.CacheClient(ctx).Scan(ctx, bm.ResourceType(ctx))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
for iter.Next(ctx) {
|
|
count++
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// DeleteCache deletes specific cache by key.
|
|
func (bm *BaseManager) DeleteCache(ctx context.Context, key string) error {
|
|
return bm.CacheClient(ctx).Delete(ctx, key)
|
|
}
|
|
|
|
// FlushAll flush this resource's all cache.
|
|
func (bm *BaseManager) FlushAll(ctx context.Context) error {
|
|
// prefix is resource type
|
|
iter, err := bm.CacheClient(ctx).Scan(ctx, bm.ResourceType(ctx))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var errs errors.Errors
|
|
for iter.Next(ctx) {
|
|
if err = bm.CacheClient(ctx).Delete(ctx, iter.Val()); err != nil {
|
|
errs = append(errs, err)
|
|
}
|
|
}
|
|
|
|
if errs.Len() > 0 {
|
|
return errs
|
|
}
|
|
|
|
return nil
|
|
}
|