[bugfix] fix emoji recaching operations (#3167)

* add test for emoji update image

* update emoji recache to set the instance account id

* don't refresh emoji if only not cached. in that case literally just recache

* code comment

* rename + move a few things

* add some more code comments, and rename some functions to make logic a bit clearer

* remove unnecessary nil check (the value can be nil)

* comment wording

* remove test data output

* handle the case of caching an emoji which has been refreshed then uncached

* allow overwriting on testrig storage as we do now on regular storage

* fix emoji category ID not getting updated

---------

Co-authored-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
kim 2024-08-03 17:05:38 +00:00 committed by GitHub
commit b85a9983d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 305 additions and 91 deletions

View file

@ -134,11 +134,6 @@ func (d *Dereferencer) RefreshEmoji(
*gtsmodel.Emoji,
error,
) {
// Can't refresh local.
if emoji.IsLocal() {
return emoji, nil
}
// Check emoji is up-to-date
// with provided extra info.
switch {
@ -156,8 +151,18 @@ func (d *Dereferencer) RefreshEmoji(
force = true
}
// Check if needs updating.
if *emoji.Cached && !force {
// Check if needs
// force refresh.
if !force {
// We still want to make sure
// the emoji is cached. Simply
// check whether emoji is cached.
return d.RecacheEmoji(ctx, emoji)
}
// Can't refresh local.
if emoji.IsLocal() {
return emoji, nil
}
@ -191,8 +196,8 @@ func (d *Dereferencer) RefreshEmoji(
return tsport.DereferenceMedia(ctx, url, int64(maxsz))
}
// Refresh emoji with prepared info.
return d.mediaManager.RefreshEmoji(ctx,
// Update emoji with prepared info.
return d.mediaManager.UpdateEmoji(ctx,
emoji,
data,
info,
@ -201,6 +206,72 @@ func (d *Dereferencer) RefreshEmoji(
)
}
// RecacheEmoji handles the simplest case which is that
// of an existing emoji that only needs to be recached.
// It handles the case of both local emojis, and those
// already cached as no-ops.
//
// Please note that even if an error is returned,
// an emoji model may still be returned if the error
// was only encountered during actual dereferencing.
// In this case, it will act as a placeholder.
func (d *Dereferencer) RecacheEmoji(
ctx context.Context,
emoji *gtsmodel.Emoji,
) (
*gtsmodel.Emoji,
error,
) {
// Can't recache local.
if emoji.IsLocal() {
return emoji, nil
}
if *emoji.Cached {
// Already cached.
return emoji, nil
}
// Get shortcode domain for locks + logging.
shortcodeDomain := emoji.ShortcodeDomain()
// Ensure we have a valid image remote URL.
url, err := url.Parse(emoji.ImageRemoteURL)
if err != nil {
err := gtserror.Newf("invalid image remote url %s for emoji %s: %w", emoji.ImageRemoteURL, shortcodeDomain, err)
return nil, err
}
// Pass along for safe processing.
return d.processEmojiSafely(ctx,
shortcodeDomain,
func() (*media.ProcessingEmoji, error) {
// Acquire new instance account transport for emoji dereferencing.
tsport, err := d.transportController.NewTransportForUsername(ctx, "")
if err != nil {
err := gtserror.Newf("error getting instance transport: %w", err)
return nil, err
}
// Get maximum supported remote emoji size.
maxsz := config.GetMediaEmojiRemoteMaxSize()
// Prepare data function to dereference remote emoji media.
data := func(context.Context) (io.ReadCloser, error) {
return tsport.DereferenceMedia(ctx, url, int64(maxsz))
}
// Recache emoji with prepared info.
return d.mediaManager.CacheEmoji(ctx,
emoji,
data,
)
},
)
}
// processingEmojiSafely provides concurrency-safe processing of
// an emoji with given shortcode+domain. if a copy of the emoji is
// not already being processed, the given 'process' callback will

View file

@ -172,7 +172,7 @@ func (d *Dereferencer) RefreshMedia(
// Recache media with prepared info,
// this will also update media in db.
return d.mediaManager.RecacheMedia(
return d.mediaManager.CacheMedia(
attach,
func(ctx context.Context) (io.ReadCloser, error) {
return tsport.DereferenceMedia(ctx, url, int64(maxsz))