URI: 
       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 }