github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/framework/cache/read_through.go (about)

     1  // The package is migrated from beego, you can get from following link:
     2  // import(
     3  //
     4  //	"github.com/beego/beego/v2/client/cache"
     5  //
     6  // )
     7  // Copyright 2023. All Rights Reserved.
     8  //
     9  // Licensed under the Apache License, Version 2.0 (the "License");
    10  // you may not use this file except in compliance with the License.
    11  // You may obtain a copy of the License at
    12  //
    13  //	http://www.apache.org/licenses/LICENSE-2.0
    14  //
    15  // Unless required by applicable law or agreed to in writing, software
    16  // distributed under the License is distributed on an "AS IS" BASIS,
    17  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18  // See the License for the specific language governing permissions and
    19  // limitations under the License.
    20  package cache
    21  
    22  import (
    23  	"context"
    24  	"time"
    25  
    26  	"github.com/mdaxf/iac/framework/berror"
    27  )
    28  
    29  // readThroughCache is a decorator
    30  // add the read through function to the original Cache function
    31  type readThroughCache struct {
    32  	Cache
    33  	expiration time.Duration
    34  	loadFunc   func(ctx context.Context, key string) (any, error)
    35  }
    36  
    37  // NewReadThroughCache create readThroughCache
    38  func NewReadThroughCache(cache Cache, expiration time.Duration,
    39  	loadFunc func(ctx context.Context, key string) (any, error),
    40  ) (Cache, error) {
    41  	if loadFunc == nil {
    42  		return nil, berror.Error(InvalidLoadFunc, "loadFunc cannot be nil")
    43  	}
    44  	return &readThroughCache{
    45  		Cache:      cache,
    46  		expiration: expiration,
    47  		loadFunc:   loadFunc,
    48  	}, nil
    49  }
    50  
    51  // Get will try to call the LoadFunc to load data if the Cache returns value nil or non-nil error.
    52  func (c *readThroughCache) Get(ctx context.Context, key string) (any, error) {
    53  	val, err := c.Cache.Get(ctx, key)
    54  	if val == nil || err != nil {
    55  		val, err = c.loadFunc(ctx, key)
    56  		if err != nil {
    57  			return nil, berror.Wrap(
    58  				err, LoadFuncFailed, "cache unable to load data")
    59  		}
    60  		err = c.Cache.Put(ctx, key, val, c.expiration)
    61  		if err != nil {
    62  			return val, err
    63  		}
    64  	}
    65  	return val, nil
    66  }