diff options
author | 2024-06-26 15:01:16 +0000 | |
---|---|---|
committer | 2024-06-26 16:01:16 +0100 | |
commit | 21bb324156f582e918a097ea744e52fc21b2ddf4 (patch) | |
tree | 50db5cfd42e26224591f59ff62de14a3715677b5 /internal/federation/dereferencing/account.go | |
parent | [docs] restructure federation section (#3038) (diff) | |
download | gotosocial-21bb324156f582e918a097ea744e52fc21b2ddf4.tar.xz |
[chore] media and emoji refactoring (#3000)
* start updating media manager interface ready for storing attachments / emoji right away
* store emoji and media as uncached immediately, then (re-)cache on Processing{}.Load()
* remove now unused media workers
* fix tests and issues
* fix another test!
* fix emoji activitypub uri setting behaviour, fix remainder of test compilation issues
* fix more tests
* fix (most of) remaining tests, add debouncing to repeatedly failing media / emojis
* whoops, rebase issue
* remove kim's whacky experiments
* do some reshuffling, ensure emoji uri gets set
* ensure marked as not cached on cleanup
* tweaks to media / emoji processing to handle context canceled better
* ensure newly fetched emojis actually get set in returned slice
* use different varnames to be a bit more obvious
* move emoji refresh rate limiting to dereferencer
* add exported dereferencer functions for remote media, use these for recaching in processor
* add check for nil attachment in updateAttachment()
* remove unused emoji and media fields + columns
* see previous commit
* fix old migrations expecting image_updated_at to exists (from copies of old models)
* remove freshness checking code (seems to be broken...)
* fix error arg causing nil ptr exception
* finish documentating functions with comments, slight tweaks to media / emoji deref error logic
* remove some extra unneeded boolean checking
* finish writing documentation (code comments) for exported media manager methods
* undo changes to migration snapshot gtsmodels, updated failing migration to have its own snapshot
* move doesColumnExist() to util.go in migrations package
Diffstat (limited to 'internal/federation/dereferencing/account.go')
-rw-r--r-- | internal/federation/dereferencing/account.go | 184 |
1 files changed, 59 insertions, 125 deletions
diff --git a/internal/federation/dereferencing/account.go b/internal/federation/dereferencing/account.go index 069fca1bc..e48507124 100644 --- a/internal/federation/dereferencing/account.go +++ b/internal/federation/dereferencing/account.go @@ -33,7 +33,6 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/id" "github.com/superseriousbusiness/gotosocial/internal/log" "github.com/superseriousbusiness/gotosocial/internal/media" - "github.com/superseriousbusiness/gotosocial/internal/transport" "github.com/superseriousbusiness/gotosocial/internal/util" ) @@ -730,18 +729,18 @@ func (d *Dereferencer) enrichAccount( latestAcc.ID = account.ID latestAcc.FetchedAt = time.Now() - // Ensure the account's avatar media is populated, passing in existing to check for changes. - if err := d.fetchRemoteAccountAvatar(ctx, tsport, account, latestAcc); err != nil { + // Ensure the account's avatar media is populated, passing in existing to check for chages. + if err := d.fetchAccountAvatar(ctx, requestUser, account, latestAcc); err != nil { log.Errorf(ctx, "error fetching remote avatar for account %s: %v", uri, err) } - // Ensure the account's avatar media is populated, passing in existing to check for changes. - if err := d.fetchRemoteAccountHeader(ctx, tsport, account, latestAcc); err != nil { + // Ensure the account's avatar media is populated, passing in existing to check for chages. + if err := d.fetchAccountHeader(ctx, requestUser, account, latestAcc); err != nil { log.Errorf(ctx, "error fetching remote header for account %s: %v", uri, err) } // Fetch the latest remote account emoji IDs used in account display name/bio. - if _, err = d.fetchRemoteAccountEmojis(ctx, latestAcc, requestUser); err != nil { + if err = d.fetchAccountEmojis(ctx, account, latestAcc); err != nil { log.Errorf(ctx, "error fetching remote emojis for account %s: %v", uri, err) } @@ -779,9 +778,9 @@ func (d *Dereferencer) enrichAccount( return latestAcc, apubAcc, nil } -func (d *Dereferencer) fetchRemoteAccountAvatar( +func (d *Dereferencer) fetchAccountAvatar( ctx context.Context, - tsport transport.Transport, + requestUser string, existingAcc *gtsmodel.Account, latestAcc *gtsmodel.Account, ) error { @@ -808,7 +807,7 @@ func (d *Dereferencer) fetchRemoteAccountAvatar( // Ensuring existing attachment is up-to-date // and any recaching is performed if required. existing, err := d.updateAttachment(ctx, - tsport, + requestUser, existing, nil, ) @@ -830,18 +829,23 @@ func (d *Dereferencer) fetchRemoteAccountAvatar( } } - // Fetch newly changed avatar from remote. - attachment, err := d.loadAttachment(ctx, - tsport, + // Fetch newly changed avatar. + attachment, err := d.GetMedia(ctx, + requestUser, latestAcc.ID, latestAcc.AvatarRemoteURL, - &media.AdditionalMediaInfo{ + media.AdditionalMediaInfo{ Avatar: util.Ptr(true), RemoteURL: &latestAcc.AvatarRemoteURL, }, ) if err != nil { - return gtserror.Newf("error loading attachment %s: %w", latestAcc.AvatarRemoteURL, err) + if attachment == nil { + return gtserror.Newf("error loading attachment %s: %w", latestAcc.AvatarRemoteURL, err) + } + + // non-fatal error occurred during loading, still use it. + log.Warnf(ctx, "partially loaded attachment: %v", err) } // Set the avatar attachment on account model. @@ -851,9 +855,9 @@ func (d *Dereferencer) fetchRemoteAccountAvatar( return nil } -func (d *Dereferencer) fetchRemoteAccountHeader( +func (d *Dereferencer) fetchAccountHeader( ctx context.Context, - tsport transport.Transport, + requestUser string, existingAcc *gtsmodel.Account, latestAcc *gtsmodel.Account, ) error { @@ -880,7 +884,7 @@ func (d *Dereferencer) fetchRemoteAccountHeader( // Ensuring existing attachment is up-to-date // and any recaching is performed if required. existing, err := d.updateAttachment(ctx, - tsport, + requestUser, existing, nil, ) @@ -902,18 +906,23 @@ func (d *Dereferencer) fetchRemoteAccountHeader( } } - // Fetch newly changed header from remote. - attachment, err := d.loadAttachment(ctx, - tsport, + // Fetch newly changed header. + attachment, err := d.GetMedia(ctx, + requestUser, latestAcc.ID, latestAcc.HeaderRemoteURL, - &media.AdditionalMediaInfo{ + media.AdditionalMediaInfo{ Header: util.Ptr(true), RemoteURL: &latestAcc.HeaderRemoteURL, }, ) if err != nil { - return gtserror.Newf("error loading attachment %s: %w", latestAcc.HeaderRemoteURL, err) + if attachment == nil { + return gtserror.Newf("error loading attachment %s: %w", latestAcc.HeaderRemoteURL, err) + } + + // non-fatal error occurred during loading, still use it. + log.Warnf(ctx, "partially loaded attachment: %v", err) } // Set the header attachment on account model. @@ -923,119 +932,44 @@ func (d *Dereferencer) fetchRemoteAccountHeader( return nil } -func (d *Dereferencer) fetchRemoteAccountEmojis(ctx context.Context, targetAccount *gtsmodel.Account, requestingUsername string) (bool, error) { - maybeEmojis := targetAccount.Emojis - maybeEmojiIDs := targetAccount.EmojiIDs - - // It's possible that the account had emoji IDs set on it, but not Emojis - // themselves, depending on how it was fetched before being passed to us. - // - // If we only have IDs, fetch the emojis from the db. We know they're in - // there or else they wouldn't have IDs. - if len(maybeEmojiIDs) > len(maybeEmojis) { - maybeEmojis = make([]*gtsmodel.Emoji, 0, len(maybeEmojiIDs)) - for _, emojiID := range maybeEmojiIDs { - maybeEmoji, err := d.state.DB.GetEmojiByID(ctx, emojiID) - if err != nil { - return false, err - } - maybeEmojis = append(maybeEmojis, maybeEmoji) - } - } - - // For all the maybe emojis we have, we either fetch them from the database - // (if we haven't already), or dereference them from the remote instance. - gotEmojis, err := d.populateEmojis(ctx, maybeEmojis, requestingUsername) - if err != nil { - return false, err - } - - // Extract the ID of each fetched or dereferenced emoji, so we can attach - // this to the account if necessary. - gotEmojiIDs := make([]string, 0, len(gotEmojis)) - for _, e := range gotEmojis { - gotEmojiIDs = append(gotEmojiIDs, e.ID) - } - - var ( - changed = false // have the emojis for this account changed? - maybeLen = len(maybeEmojis) - gotLen = len(gotEmojis) +func (d *Dereferencer) fetchAccountEmojis( + ctx context.Context, + existing *gtsmodel.Account, + account *gtsmodel.Account, +) error { + // Fetch the updated emojis for our account. + emojis, changed, err := d.fetchEmojis(ctx, + existing.Emojis, + account.Emojis, ) - - // if the length of everything is zero, this is simple: - // nothing has changed and there's nothing to do - if maybeLen == 0 && gotLen == 0 { - return changed, nil - } - - // if the *amount* of emojis on the account has changed, then the got emojis - // are definitely different from the previous ones (if there were any) -- - // the account has either more or fewer emojis set on it now, so take the - // discovered emojis as the new correct ones. - if maybeLen != gotLen { - changed = true - targetAccount.Emojis = gotEmojis - targetAccount.EmojiIDs = gotEmojiIDs - return changed, nil + if err != nil { + return gtserror.Newf("error fetching emojis: %w", err) } - // if the lengths are the same but not all of the slices are - // zero, something *might* have changed, so we have to check - - // 1. did we have emojis before that we don't have now? - for _, maybeEmoji := range maybeEmojis { - var stillPresent bool - - for _, gotEmoji := range gotEmojis { - if maybeEmoji.URI == gotEmoji.URI { - // the emoji we maybe had is still present now, - // so we can stop checking gotEmojis - stillPresent = true - break - } - } - - if !stillPresent { - // at least one maybeEmoji is no longer present in - // the got emojis, so we can stop checking now - changed = true - targetAccount.Emojis = gotEmojis - targetAccount.EmojiIDs = gotEmojiIDs - return changed, nil - } + if !changed { + // Use existing account emoji objects. + account.EmojiIDs = existing.EmojiIDs + account.Emojis = existing.Emojis + return nil } - // 2. do we have emojis now that we didn't have before? - for _, gotEmoji := range gotEmojis { - var wasPresent bool - - for _, maybeEmoji := range maybeEmojis { - // check emoji IDs here as well, because unreferenced - // maybe emojis we didn't already have would not have - // had IDs set on them yet - if gotEmoji.URI == maybeEmoji.URI && gotEmoji.ID == maybeEmoji.ID { - // this got emoji was present already in the maybeEmoji, - // so we can stop checking through maybeEmojis - wasPresent = true - break - } - } + // Set latest emojis. + account.Emojis = emojis - if !wasPresent { - // at least one gotEmojis was not present in - // the maybeEmojis, so we can stop checking now - changed = true - targetAccount.Emojis = gotEmojis - targetAccount.EmojiIDs = gotEmojiIDs - return changed, nil - } + // Iterate over and set changed emoji IDs. + account.EmojiIDs = make([]string, len(emojis)) + for i, emoji := range emojis { + account.EmojiIDs[i] = emoji.ID } - return changed, nil + return nil } -func (d *Dereferencer) dereferenceAccountStats(ctx context.Context, requestUser string, account *gtsmodel.Account) error { +func (d *Dereferencer) dereferenceAccountStats( + ctx context.Context, + requestUser string, + account *gtsmodel.Account, +) error { // Ensure we have a stats model for this account. if account.Stats == nil { if err := d.state.DB.PopulateAccountStats(ctx, account); err != nil { |