From 34d0879c1651d2703f94c1b653227c718aac475f Mon Sep 17 00:00:00 2001 From: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com> Date: Wed, 8 Nov 2023 22:37:35 +0000 Subject: [PATCH] [bugfix] fix poll vote count responses on client and fedi API vote creation (#2343) * increment poll votes *before* enqueuing vote to client API worker * increment vote counts before federating status update after vote in local poll * improved vote count calculation during backend -> frontend model conversion --- internal/processing/polls/vote.go | 10 +++--- internal/processing/workers/fromfediapi.go | 4 +++ internal/typeutils/internaltofrontend.go | 37 +++++++++++----------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/internal/processing/polls/vote.go b/internal/processing/polls/vote.go index 8c8f22225..c4a8a12a4 100644 --- a/internal/processing/polls/vote.go +++ b/internal/processing/polls/vote.go @@ -90,6 +90,11 @@ func (p *Processor) PollVote(ctx context.Context, requester *gtsmodel.Account, p return nil, gtserror.NewErrorInternalError(err) } + // Before enqueuing it, increment the poll + // vote counts on the copy attached to the + // PollVote (that we also later return). + poll.IncrementVotes(choices) + // Enqueue worker task to handle side-effects of user poll vote(s). p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{ APActivityType: ap.ActivityCreate, @@ -98,11 +103,6 @@ func (p *Processor) PollVote(ctx context.Context, requester *gtsmodel.Account, p OriginAccount: requester, }) - // Before returning the converted poll model, - // increment the vote counts on our local copy - // to get latest, instead of another db query. - poll.IncrementVotes(choices) - // Return converted API model poll. return p.toAPIPoll(ctx, requester, poll) } diff --git a/internal/processing/workers/fromfediapi.go b/internal/processing/workers/fromfediapi.go index 2b0bfa9fa..9558bf8b7 100644 --- a/internal/processing/workers/fromfediapi.go +++ b/internal/processing/workers/fromfediapi.go @@ -233,6 +233,10 @@ func (p *fediAPI) CreatePollVote(ctx context.Context, fMsg messages.FromFediAPI) p.surface.invalidateStatusFromTimelines(ctx, vote.Poll.StatusID) if *status.Local { + // Before federating it, increment the + // poll vote counts on our local copy. + status.Poll.IncrementVotes(vote.Choices) + // These were poll votes in a local status, we need to // federate the updated status model with latest vote counts. if err := p.federate.UpdateStatus(ctx, status); err != nil { diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 6a374bbde..0a79defc7 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -1310,13 +1310,21 @@ func (c *Converter) PollToAPIPoll(ctx context.Context, requester *gtsmodel.Accou } var ( + options []apimodel.PollOption totalVotes int totalVoters int - voteCounts []int ownChoices []int isAuthor bool ) + // Preallocate a slice of frontend model poll choices. + options = make([]apimodel.PollOption, len(poll.Options)) + + // Add the titles to all of the options. + for i, title := range poll.Options { + options[i].Title = title + } + if requester != nil { // Get vote by requester in poll (if any). vote, err := c.state.DB.GetPollVoteBy(ctx, @@ -1335,37 +1343,28 @@ func (c *Converter) PollToAPIPoll(ctx context.Context, requester *gtsmodel.Accou // case that counts are hidden. totalVotes = len(vote.Choices) totalVoters = 1 + for _, choice := range ownChoices { + options[choice].VotesCount++ + } } // Check if requester is author of source status. isAuthor = (requester.ID == poll.Status.AccountID) } - // Preallocate a slice of frontend model poll choices. - options := make([]apimodel.PollOption, len(poll.Options)) - - // Add the titles to all of the options. - for i, title := range poll.Options { - options[i].Title = title - } - if isAuthor || !*poll.HideCounts { // A remote status, // the simple route! // // Pull cached remote values. - totalVoters = *poll.Voters - voteCounts = poll.Votes - - // Accumulate total from all counts. - for _, count := range poll.Votes { - totalVotes += count - } + totalVoters = (*poll.Voters) // When this is status author, or hide counts - // is disabled, set the counts known per vote. - for i, count := range voteCounts { + // is disabled, set the counts known per vote, + // and accumulate all the vote totals. + for i, count := range poll.Votes { options[i].VotesCount = count + totalVotes += count } } @@ -1373,7 +1372,7 @@ func (c *Converter) PollToAPIPoll(ctx context.Context, requester *gtsmodel.Accou ID: poll.ID, ExpiresAt: util.FormatISO8601(poll.ExpiresAt), Expired: poll.Closed(), - Multiple: *poll.Multiple, + Multiple: (*poll.Multiple), VotesCount: totalVotes, VotersCount: totalVoters, Voted: (isAuthor || len(ownChoices) > 0),