cache.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package app
  2. import (
  3. "context"
  4. "sync"
  5. "time"
  6. "github.com/maxence-charriere/go-app/v9/pkg/cache"
  7. )
  8. // PreRenderCache is the interface that describes a cache that stores
  9. // pre-rendered resources.
  10. type PreRenderCache interface {
  11. // Get returns the item at the given path.
  12. Get(ctx context.Context, path string) (PreRenderedItem, bool)
  13. // Set stored the item at the given path.
  14. Set(ctx context.Context, i PreRenderedItem)
  15. }
  16. // PreRenderedItem represent an item that is stored in a PreRenderCache.
  17. type PreRenderedItem struct {
  18. // The request path.
  19. Path string
  20. // The response content type.
  21. ContentType string
  22. // The response content encoding.
  23. ContentEncoding string
  24. // The response body.
  25. Body []byte
  26. }
  27. // Len return the body length.
  28. func (r PreRenderedItem) Size() int {
  29. return len(r.Body)
  30. }
  31. // NewPreRenderLRUCache creates an in memory LRU cache that stores items for the
  32. // given duration. If provided, on eviction functions are called when item are
  33. // evicted.
  34. func NewPreRenderLRUCache(size int, itemTTL time.Duration, onEvict ...func(path string, i PreRenderedItem)) PreRenderCache {
  35. return &preRenderLRUCache{
  36. LRU: cache.LRU{
  37. MaxSize: size,
  38. ItemTTL: itemTTL,
  39. OnEvict: func(path string, i cache.Item) {
  40. item := i.(PreRenderedItem)
  41. for _, fn := range onEvict {
  42. fn(path, item)
  43. }
  44. },
  45. },
  46. }
  47. }
  48. type preRenderLRUCache struct {
  49. cache.LRU
  50. }
  51. func (c *preRenderLRUCache) Get(ctx context.Context, path string) (PreRenderedItem, bool) {
  52. i, ok := c.LRU.Get(ctx, path)
  53. if !ok {
  54. return PreRenderedItem{}, false
  55. }
  56. return i.(PreRenderedItem), true
  57. }
  58. func (c *preRenderLRUCache) Set(ctx context.Context, i PreRenderedItem) {
  59. c.LRU.Set(ctx, i.Path, i)
  60. }
  61. type preRenderCache struct {
  62. mu sync.RWMutex
  63. items map[string]PreRenderedItem
  64. }
  65. func newPreRenderCache(size int) *preRenderCache {
  66. return &preRenderCache{
  67. items: make(map[string]PreRenderedItem, size),
  68. }
  69. }
  70. func (c *preRenderCache) Set(ctx context.Context, i PreRenderedItem) {
  71. c.mu.Lock()
  72. c.items[i.Path] = i
  73. c.mu.Unlock()
  74. }
  75. func (c *preRenderCache) Get(ctx context.Context, path string) (PreRenderedItem, bool) {
  76. c.mu.Lock()
  77. i, ok := c.items[path]
  78. c.mu.Unlock()
  79. return i, ok
  80. }