github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf. 6 7 package gfile 8 9 import ( 10 "context" 11 "time" 12 13 "github.com/wangyougui/gf/v2/errors/gcode" 14 "github.com/wangyougui/gf/v2/errors/gerror" 15 "github.com/wangyougui/gf/v2/internal/command" 16 "github.com/wangyougui/gf/v2/internal/intlog" 17 "github.com/wangyougui/gf/v2/os/gcache" 18 "github.com/wangyougui/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 }