fix: add job limits for thumbnails to prevent out of memory errors

This commit is contained in:
Louis Dalibard 2024-06-10 21:55:03 +02:00
parent db4aae2e5b
commit 76f1dcf83e
3 changed files with 41 additions and 3 deletions

View File

@ -9,6 +9,7 @@ import (
type ConfigS struct {
Host string `json:"host"`
ThumbnailJobLimit int `json:"thumbnailjoblimit"`
ServeDirs map[string]string `json:"servedirs"`
}

View File

@ -1,5 +1,6 @@
{
"host": ":3125",
"thumbnailjoblimit": "5",
"servedirs": {
"leech": "/home/ontake/Dev/go/leech"
}

View File

@ -27,35 +27,69 @@ var thumbnailSize = 24
var thumbnailCache = map[string][]byte{}
var thumbnailCacheMutex = &sync.RWMutex{}
var jobLimit = 5
var memLimiterMutex = &sync.RWMutex{}
var jobCounter = 0
var checkAgain = make(chan bool, 5)
func IsSupportedFileType(completePath string) bool {
fileExt := filepath.Ext(completePath)
return slices.Contains(SupportedFileTypes, fileExt)
}
func WaitForAvailable() {
memLimiterMutex.RLock()
for jobLimit == jobCounter {
memLimiterMutex.RUnlock()
<-checkAgain
memLimiterMutex.RLock()
}
memLimiterMutex.RUnlock()
memLimiterMutex.Lock()
jobCounter += 1
memLimiterMutex.Unlock()
}
func Free() {
memLimiterMutex.Lock()
jobCounter -= 1
memLimiterMutex.Unlock()
select {
case checkAgain <- true:
return
default:
return
}
}
func GetThumbnail(c *fiber.Ctx, completePath string) {
WaitForAvailable()
c.Set(fiber.HeaderContentType, "image")
thumbnailCacheMutex.RLock()
bytesThumb, ok := thumbnailCache[completePath]
thumbnailCacheMutex.RUnlock()
if ok {
c.Write(bytesThumb)
Free()
return
}
fileExt := filepath.Ext(completePath)
if !slices.Contains(SupportedFileTypes, fileExt) {
Free()
return
}
f, err := os.Open(completePath)
if err != nil {
Free()
return
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
Free()
return
}
f.Close()
// load images and make 64x64 thumbnails of them
thumbnail := imaging.Thumbnail(img, thumbnailSize, thumbnailSize, imaging.CatmullRom)
// create a new blank image
@ -70,10 +104,12 @@ func GetThumbnail(c *fiber.Ctx, completePath string) {
err = imaging.Encode(&buf, dst, FileTypesMap[fileExt])
}
if err != nil {
Free()
return
}
thumbnailCacheMutex.Lock()
thumbnailCache[completePath] = buf.Bytes()
thumbnailCacheMutex.Unlock()
c.Write(buf.Bytes())
Free()
}