Newer
Older
package thumbnails
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/turt2live/matrix-media-repo/common"
"github.com/turt2live/matrix-media-repo/common/rcontext"
"github.com/turt2live/matrix-media-repo/database"
"github.com/turt2live/matrix-media-repo/datastores"
"github.com/turt2live/matrix-media-repo/metrics"
"github.com/turt2live/matrix-media-repo/pipelines/_steps/datastore_op"
"github.com/turt2live/matrix-media-repo/pipelines/_steps/download"
"github.com/turt2live/matrix-media-repo/pool"
"github.com/turt2live/matrix-media-repo/thumbnailing"
"github.com/turt2live/matrix-media-repo/thumbnailing/m"
"github.com/turt2live/matrix-media-repo/util"
)
type generateResult struct {
i *m.Thumbnail
err error
}
func Generate(ctx rcontext.RequestContext, mediaRecord *database.DbMedia, width int, height int, method string, animated bool) (*database.DbThumbnail, io.ReadCloser, error) {
ch := make(chan generateResult)
defer close(ch)
fn := func() {
metric := metrics.ThumbnailsGenerated.With(prometheus.Labels{
"width": strconv.Itoa(width),
"height": strconv.Itoa(height),
"method": method,
"animated": strconv.FormatBool(animated),
"origin": mediaRecord.Origin,
})
mediaStream, err := download.OpenStream(ctx, mediaRecord.Locatable)
if err != nil {
ch <- generateResult{err: err}
return
}
fixedContentType := util.FixContentType(mediaRecord.ContentType)
i, err := thumbnailing.GenerateThumbnail(mediaStream, fixedContentType, width, height, method, animated, ctx)
if err != nil {
if errors.Is(err, common.ErrMediaDimensionsTooSmall) {
metric.Inc()
}
ch <- generateResult{err: err}
return
}
ch <- generateResult{i: i}
}
if err := pool.ThumbnailQueue.Schedule(fn); err != nil {
return nil, nil, err
}
res := <-ch
if res.err != nil {
return nil, nil, res.err
}
if res.i == nil {
// Couldn't generate a thumbnail
return nil, nil, common.ErrMediaNotFound
}
// At this point, res.i is our thumbnail
thumbMediaRecord, thumbStream, err := datastore_op.PutAndReturnStream(ctx, ctx.Request.Host, "", res.i.Reader, res.i.ContentType, "", datastores.ThumbnailsKind)
if err != nil {
return nil, nil, err
}
// Create a DbThumbnail
newRecord := &database.DbThumbnail{
Origin: mediaRecord.Origin,
MediaId: mediaRecord.MediaId,
ContentType: thumbMediaRecord.ContentType,
Width: width,
Height: height,
Method: method,
Animated: res.i.Animated,
SizeBytes: thumbMediaRecord.SizeBytes,
CreationTs: thumbMediaRecord.CreationTs,
Locatable: &database.Locatable{
Sha256Hash: thumbMediaRecord.Sha256Hash,
DatastoreId: thumbMediaRecord.DatastoreId,
Location: thumbMediaRecord.Location,
},
}
err = database.GetInstance().Thumbnails.Prepare(ctx).Insert(newRecord)
if err != nil {
defer thumbStream.Close()
return nil, nil, err
}
return newRecord, thumbStream, nil
}