resource_cache.go - hugo - [fork] hugo port for 9front
HTML git clone https://git.drkhsh.at/hugo.git
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
resource_cache.go (4790B)
---
1 // Copyright 2019 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package resources
15
16 import (
17 "context"
18 "encoding/json"
19 "io"
20 "path"
21 "path/filepath"
22 "strings"
23 "sync"
24
25 "github.com/gohugoio/hugo/resources/resource"
26
27 "github.com/gohugoio/hugo/cache/dynacache"
28 "github.com/gohugoio/hugo/cache/filecache"
29 )
30
31 func newResourceCache(rs *Spec, memCache *dynacache.Cache) *ResourceCache {
32 return &ResourceCache{
33 fileCache: rs.FileCaches.AssetsCache(),
34 cacheResource: dynacache.GetOrCreatePartition[string, resource.Resource](
35 memCache,
36 "/res1",
37 dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 40},
38 ),
39 cacheResourceFile: dynacache.GetOrCreatePartition[string, resource.Resource](
40 memCache,
41 "/res2",
42 dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 40},
43 ),
44 CacheResourceRemote: dynacache.GetOrCreatePartition[string, resource.Resource](
45 memCache,
46 "/resr",
47 dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 40},
48 ),
49 cacheResources: dynacache.GetOrCreatePartition[string, resource.Resources](
50 memCache,
51 "/ress",
52 dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnRebuild, Weight: 40},
53 ),
54 cacheResourceTransformation: dynacache.GetOrCreatePartition[string, *resourceAdapterInner](
55 memCache,
56 "/res1/tra",
57 dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 40},
58 ),
59 }
60 }
61
62 type ResourceCache struct {
63 sync.RWMutex
64
65 cacheResource *dynacache.Partition[string, resource.Resource]
66 cacheResourceFile *dynacache.Partition[string, resource.Resource]
67 CacheResourceRemote *dynacache.Partition[string, resource.Resource]
68 cacheResources *dynacache.Partition[string, resource.Resources]
69 cacheResourceTransformation *dynacache.Partition[string, *resourceAdapterInner]
70
71 fileCache *filecache.Cache
72 }
73
74 func (c *ResourceCache) cleanKey(key string) string {
75 return strings.TrimPrefix(path.Clean(strings.ToLower(filepath.ToSlash(key))), "/")
76 }
77
78 func (c *ResourceCache) Get(ctx context.Context, key string) (resource.Resource, bool) {
79 return c.cacheResource.Get(ctx, key)
80 }
81
82 func (c *ResourceCache) GetOrCreate(key string, f func() (resource.Resource, error)) (resource.Resource, error) {
83 return c.cacheResource.GetOrCreate(key, func(key string) (resource.Resource, error) {
84 return f()
85 })
86 }
87
88 func (c *ResourceCache) GetOrCreateFile(key string, f func() (resource.Resource, error)) (resource.Resource, error) {
89 return c.cacheResourceFile.GetOrCreate(key, func(key string) (resource.Resource, error) {
90 return f()
91 })
92 }
93
94 func (c *ResourceCache) GetOrCreateResources(key string, f func() (resource.Resources, error)) (resource.Resources, error) {
95 return c.cacheResources.GetOrCreate(key, func(key string) (resource.Resources, error) {
96 return f()
97 })
98 }
99
100 func (c *ResourceCache) getFilenames(key string) (string, string) {
101 filenameMeta := key + ".json"
102 filenameContent := key + ".content"
103
104 return filenameMeta, filenameContent
105 }
106
107 func (c *ResourceCache) getFromFile(key string) (filecache.ItemInfo, io.ReadCloser, transformedResourceMetadata, bool) {
108 c.RLock()
109 defer c.RUnlock()
110
111 var meta transformedResourceMetadata
112 filenameMeta, filenameContent := c.getFilenames(key)
113
114 _, jsonContent, _ := c.fileCache.GetBytes(filenameMeta)
115 if jsonContent == nil {
116 return filecache.ItemInfo{}, nil, meta, false
117 }
118
119 if err := json.Unmarshal(jsonContent, &meta); err != nil {
120 return filecache.ItemInfo{}, nil, meta, false
121 }
122
123 fi, rc, _ := c.fileCache.Get(filenameContent)
124
125 return fi, rc, meta, rc != nil
126 }
127
128 // writeMeta writes the metadata to file and returns a writer for the content part.
129 func (c *ResourceCache) writeMeta(key string, meta transformedResourceMetadata) (filecache.ItemInfo, io.WriteCloser, error) {
130 filenameMeta, filenameContent := c.getFilenames(key)
131 raw, err := json.Marshal(meta)
132 if err != nil {
133 return filecache.ItemInfo{}, nil, err
134 }
135
136 _, fm, err := c.fileCache.WriteCloser(filenameMeta)
137 if err != nil {
138 return filecache.ItemInfo{}, nil, err
139 }
140 defer fm.Close()
141
142 if _, err := fm.Write(raw); err != nil {
143 return filecache.ItemInfo{}, nil, err
144 }
145
146 fi, fc, err := c.fileCache.WriteCloser(filenameContent)
147
148 return fi, fc, err
149 }