github.com/gogf/gf/v2@v2.7.4/os/gfile/gfile_cache.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gfile
     8  
     9  import (
    10  	"context"
    11  	"time"
    12  
    13  	"github.com/gogf/gf/v2/errors/gcode"
    14  	"github.com/gogf/gf/v2/errors/gerror"
    15  	"github.com/gogf/gf/v2/internal/command"
    16  	"github.com/gogf/gf/v2/internal/intlog"
    17  	"github.com/gogf/gf/v2/os/gcache"
    18  	"github.com/gogf/gf/v2/os/gfsnotify"
    19  )
    20  
    21  const (
    22  	defaultCacheDuration  = "1m"             // defaultCacheExpire is the expire time for file content caching in seconds.
    23  	commandEnvKeyForCache = "gf.gfile.cache" // commandEnvKeyForCache is the configuration key for command argument or environment configuring cache expire duration.
    24  )
    25  
    26  var (
    27  	// Default expire time for file content caching.
    28  	cacheDuration = getCacheDuration()
    29  
    30  	// internalCache is the memory cache for internal usage.
    31  	internalCache = gcache.New()
    32  )
    33  
    34  func getCacheDuration() time.Duration {
    35  	cacheDurationConfigured := command.GetOptWithEnv(commandEnvKeyForCache, defaultCacheDuration)
    36  	d, err := time.ParseDuration(cacheDurationConfigured)
    37  	if err != nil {
    38  		panic(gerror.WrapCodef(
    39  			gcode.CodeInvalidConfiguration,
    40  			err,
    41  			`error parsing string "%s" to time duration`,
    42  			cacheDurationConfigured,
    43  		))
    44  	}
    45  	return d
    46  }
    47  
    48  // GetContentsWithCache returns string content of given file by `path` from cache.
    49  // If there's no content in the cache, it will read it from disk file specified by `path`.
    50  // The parameter `expire` specifies the caching time for this file content in seconds.
    51  func GetContentsWithCache(path string, duration ...time.Duration) string {
    52  	return string(GetBytesWithCache(path, duration...))
    53  }
    54  
    55  // GetBytesWithCache returns []byte content of given file by `path` from cache.
    56  // If there's no content in the cache, it will read it from disk file specified by `path`.
    57  // The parameter `expire` specifies the caching time for this file content in seconds.
    58  func GetBytesWithCache(path string, duration ...time.Duration) []byte {
    59  	var (
    60  		ctx      = context.Background()
    61  		expire   = cacheDuration
    62  		cacheKey = commandEnvKeyForCache + path
    63  	)
    64  
    65  	if len(duration) > 0 {
    66  		expire = duration[0]
    67  	}
    68  	r, _ := internalCache.GetOrSetFuncLock(ctx, cacheKey, func(ctx context.Context) (interface{}, error) {
    69  		b := GetBytes(path)
    70  		if b != nil {
    71  			// Adding this `path` to gfsnotify,
    72  			// it will clear its cache if there's any changes of the file.
    73  			_, _ = gfsnotify.Add(path, func(event *gfsnotify.Event) {
    74  				_, err := internalCache.Remove(ctx, cacheKey)
    75  				if err != nil {
    76  					intlog.Errorf(ctx, `%+v`, err)
    77  				}
    78  				gfsnotify.Exit()
    79  			})
    80  		}
    81  		return b, nil
    82  	}, expire)
    83  	if r != nil {
    84  		return r.Bytes()
    85  	}
    86  	return nil
    87  }