MCPcopy Index your code
hub / github.com/cshum/imagor / loadOrCache

Method loadOrCache

processor/vipsprocessor/cache.go:53–163  ·  view source on GitHub ↗

loadOrCache returns a cached blob for the given image path, using the image cache. Cache key is image path only, so the same source serves all requested sizes. If load is non-nil and blob is nil, load is called inside the singleflight to fetch the blob, deduplicating network requests across concurre

(
	blob *imagor.Blob, imagePath string, n int, load imagor.LoadFunc,
)

Source from the content-addressed store, hash-verified

51// Returns (nil, nil, nil) if cache is disabled or the source is animated
52// (multi-page structure cannot be preserved in the cache).
53func (v *Processor) loadOrCache(
54 blob *imagor.Blob, imagePath string, n int, load imagor.LoadFunc,
55) (*imagor.Blob, *imagor.Blob, error) {
56 if v.cache == nil {
57 return nil, nil, nil
58 }
59
60 // Fast path: cache hit — return immediately without singleflight overhead.
61 if memBlob, ok := v.cache.Get(imagePath); ok {
62 return memBlob, nil, nil
63 }
64
65 // Deduplicate concurrent cache misses for the same image path.
66 result, err, _ := v.cacheSF.Do(imagePath, func() (any, error) {
67 // Re-check after acquiring the singleflight group.
68 if memBlob, ok := v.cache.Get(imagePath); ok {
69 return &loadOrCacheResult{memBlob: memBlob}, nil
70 }
71
72 // If blob not provided, fetch it inside the singleflight so concurrent
73 // cache misses share a single network request.
74 if blob == nil {
75 if load == nil {
76 return &loadOrCacheResult{}, nil
77 }
78 var err error
79 blob, err = load(imagePath)
80 if err != nil {
81 return nil, err
82 }
83 }
84
85 // Decode at maxW×maxH with SizeDown. Fresh context so the VipsSource
86 // is released immediately after serialization.
87 decodeCtx := withContext(context.Background())
88
89 img, err := v.NewThumbnail(decodeCtx, blob, v.CacheMaxWidth, v.CacheMaxHeight,
90 vips.InterestingNone, vips.SizeDown, n, 1, 0)
91 if err != nil {
92 contextDone(decodeCtx)
93 return nil, err
94 }
95
96 // Animated source: multi-page structure cannot be preserved in the cache.
97 // Return the original blob so the caller can serve it directly.
98 if img.Height() != img.PageHeight() {
99 img.Close()
100 contextDone(decodeCtx)
101 return &loadOrCacheResult{origBlob: blob}, nil
102 }
103
104 // Static image: serialize to Go-owned bytes, release libvips resources.
105 // Storage format is controlled by CacheFormat:
106 // BlobTypeWEBP → WebpsaveBuffer (lossy, smaller memory, slight quality difference)
107 // BlobTypePNG → PngsaveBuffer (lossless, smaller memory, pixel-identical)
108 // default → WriteToMemory (raw pixels, fastest hit, most memory)
109 imgW, imgH := img.Width(), img.PageHeight()
110

Callers 3

loadOverlayImageMethod · 0.95
loadFilterImageMethod · 0.95
ProcessMethod · 0.95

Implementers 4

cacherProcessorimagor_test.go
Processorprocessor/vipsprocessor/processor.go
testProcessorserver/server_test.go
slowTestProcessorserver/server_test.go

Calls 10

NewThumbnailMethod · 0.95
NewBlobFromBytesFunction · 0.92
NewBlobFromMemoryFunction · 0.92
contextDoneFunction · 0.85
normalizeSrgbFunction · 0.85
DoMethod · 0.80
SetMethod · 0.80
withContextFunction · 0.70
GetMethod · 0.65
CloseMethod · 0.45

Tested by

no test coverage detected