gfile_cache.go 2.7 KB

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