mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-01-19 02:14:28 -06:00
implemented waiting for free thumb generator
Signed-off-by: Aleksandr Dubovikov <d.lexand@gmail.com>
This commit is contained in:
parent
5845244aa9
commit
46473c1bf0
|
@ -27,9 +27,12 @@ import (
|
||||||
"golang.org/x/net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrorMissingUrl = errors.New("missing url")
|
var (
|
||||||
var ErrorUnsupportedContentType = errors.New("unsupported content type")
|
ErrorMissingUrl = errors.New("missing url")
|
||||||
var ErrorFileTooLarge = errors.New("file too large")
|
ErrorUnsupportedContentType = errors.New("unsupported content type")
|
||||||
|
ErrorFileTooLarge = errors.New("file too large")
|
||||||
|
ErrorTimeoutThumbnailGenerator = errors.New("timeout waiting for thumbnail generator")
|
||||||
|
)
|
||||||
|
|
||||||
func makeUrlPreviewHandler(
|
func makeUrlPreviewHandler(
|
||||||
cfg *config.MediaAPI,
|
cfg *config.MediaAPI,
|
||||||
|
@ -138,16 +141,23 @@ func makeUrlPreviewHandler(
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var result *types.UrlPreview
|
var result *types.UrlPreview
|
||||||
|
var err error
|
||||||
|
var imgUrl *url.URL
|
||||||
var imgReader *http.Response
|
var imgReader *http.Response
|
||||||
|
var mediaData *types.MediaMetadata
|
||||||
|
|
||||||
if strings.HasPrefix(resp.Header.Get("Content-Type"), "text/html") {
|
if strings.HasPrefix(resp.Header.Get("Content-Type"), "text/html") {
|
||||||
result, err = getPreviewFromHTML(resp, pUrl)
|
result, err = getPreviewFromHTML(resp, pUrl)
|
||||||
if err == nil && result.ImageUrl != "" {
|
if err == nil && result.ImageUrl != "" {
|
||||||
if imgUrl, err := url.Parse(result.ImageUrl); err == nil {
|
if imgUrl, err = url.Parse(result.ImageUrl); err == nil {
|
||||||
imgReader, err = downloadUrl(result.ImageUrl, time.Duration(cfg.UrlPreviewTimeout)*time.Second)
|
imgReader, err = downloadUrl(result.ImageUrl, time.Duration(cfg.UrlPreviewTimeout)*time.Second)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
mediaData, err := downloadAndStoreImage(imgUrl.Path, req.Context(), imgReader, cfg, device, db, activeThumbnailGeneration, logger)
|
mediaData, err = downloadAndStoreImage(imgUrl.Path, req.Context(), imgReader, cfg, device, db, activeThumbnailGeneration, logger)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
result.ImageUrl = fmt.Sprintf("mxc://%s/%s", mediaData.Origin, mediaData.MediaID)
|
result.ImageUrl = fmt.Sprintf("mxc://%s/%s", mediaData.Origin, mediaData.MediaID)
|
||||||
|
} else {
|
||||||
|
// We don't show the orginal URL as it is insecure for the room users
|
||||||
|
result.ImageUrl = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,6 +316,22 @@ func downloadAndStoreImage(
|
||||||
|
|
||||||
// Create a thumbnail from the image
|
// Create a thumbnail from the image
|
||||||
thumbnailPath := tmpFileName + ".thumbnail"
|
thumbnailPath := tmpFileName + ".thumbnail"
|
||||||
|
|
||||||
|
// Check if we have too many thumbnail generators running
|
||||||
|
// If so, wait up to 30 seconds for one to finish
|
||||||
|
timeout := time.After(30 * time.Second)
|
||||||
|
for {
|
||||||
|
if len(activeThumbnailGeneration.PathToResult) < cfg.MaxThumbnailGenerators {
|
||||||
|
activeThumbnailGeneration.Lock()
|
||||||
|
activeThumbnailGeneration.PathToResult[string(hash)] = nil
|
||||||
|
activeThumbnailGeneration.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
activeThumbnailGeneration.Lock()
|
||||||
|
delete(activeThumbnailGeneration.PathToResult, string(hash))
|
||||||
|
activeThumbnailGeneration.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
err = thumbnailer.CreateThumbnailFromFile(types.Path(tmpFileName), types.Path(thumbnailPath), types.ThumbnailSize(cfg.UrlPreviewThumbnailSize), logger)
|
err = thumbnailer.CreateThumbnailFromFile(types.Path(tmpFileName), types.Path(thumbnailPath), types.ThumbnailSize(cfg.UrlPreviewThumbnailSize), logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, thumbnailer.ErrThumbnailTooLarge) {
|
if errors.Is(err, thumbnailer.ErrThumbnailTooLarge) {
|
||||||
|
@ -315,7 +341,18 @@ func downloadAndStoreImage(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Debug("thumbnail created", thumbnailPath)
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timeout:
|
||||||
|
logger.Error("timed out waiting for thumbnail generator")
|
||||||
|
return nil, ErrorTimeoutThumbnailGenerator
|
||||||
|
default:
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
thumbnailFileInfo, err := os.Stat(string(thumbnailPath))
|
thumbnailFileInfo, err := os.Stat(string(thumbnailPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Error("unable to get thumbnail file info")
|
logger.WithError(err).Error("unable to get thumbnail file info")
|
||||||
|
@ -345,7 +382,7 @@ func downloadAndStoreImage(
|
||||||
Base64Hash: hash,
|
Base64Hash: hash,
|
||||||
UserID: userid,
|
UserID: userid,
|
||||||
}
|
}
|
||||||
fmt.Println("mediaMetaData", mediaMetaData)
|
|
||||||
finalPath, err := fileutils.GetPathFromBase64Hash(mediaMetaData.Base64Hash, cfg.AbsBasePath)
|
finalPath, err := fileutils.GetPathFromBase64Hash(mediaMetaData.Base64Hash, cfg.AbsBasePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Error("unable to get path from base64 hash")
|
logger.WithError(err).Error("unable to get path from base64 hash")
|
||||||
|
|
Loading…
Reference in a new issue