-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Frecency thread feeds (second try) #3798
Conversation
Generated by 🚫 dangerJS |
|
These are the results on a not-very-recent prod backup. Before: After: I don't really like these results much yet. The current algo indexes heavily on recent (i.e. last activity), but that means that a thread with 150 participants that's half a year old will shoot up to the top if a single person writes another message. 😕 I think we need to do time boxing when considering the raw content, and count messages that were sent a while ago a lot less than messages that were sent just now. We can do that now! Will dig into that. |
|
I edited the algorithm to exponentially bias towards recency, based on what Mozilla does. Here's what the results look like on a 15 minute old db backup; first image is sorted by latest, i.e. the old version, second image is trending, i.e. the new version: (note that being ~as good as the old version is good enough for the algorithm since we really just don't want people bumping shitty threads themselves) Figma Verdict: Not really a difference in terms of quality at this snapshot in time. Codepen Verdict: Algorithmic version seems a little bit better. React Verdict: Algorithmic versions looks better. styled-components Verdict: Algorithmic versions looks better. Based on those four hand-picked examples (I didn't check anything else) I say this algorithm looks good for now, let's ship it if the code looks good? |
|
Just realized my previous migration won't work in production—not sure what to do with all the existing threads just yet... |
| type GetThreadsByChannelPaginationOptions = { | ||
| first: number, | ||
| after: number, | ||
| sort: 'new' | 'trending' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we want these options to be defined and expand over time? Is trending the same as popular? Can we ever sort by date? e.g. trending this week/month/year
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll probably won't be able to do trending this week/month/year with this current setup since we only store the score right now. I think other than that we probably want "TOP", but that's a different calculation altogether.
Not sure, any thoguhts/ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure either, just trying to think ahead a bit for what other constrains might enter the mix. But also don't want to get too caught up to prevent this from moving forward :)
| export type CommunityThreadConnectionPaginationOptions = { | ||
| after: string, | ||
| first: number, | ||
| sort: 'NEW' | 'TRENDING', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above we had 'new' and 'trending' but here they are all caps. Should we be consistent with these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I don't think so? One is the GraphQL stuff (which has to be all caps) and one is internally the argument for the db query. (which we never do all caps)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Referring to this: https://github.com/withspectrum/spectrum/pull/3798/files#diff-8e46094eed25a21b0755138dc52cf17eR77
No worries either way
| export default async (root: DBCommunity, args: PaginationOptions, ctx: GraphQLContext) => { | ||
| const { first = 10, after } = args | ||
| export default async (root: DBCommunity, args: CommunityThreadConnectionPaginationOptions, ctx: GraphQLContext) => { | ||
| const { first = 10, after, sort = 'NEW' } = args |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto to caps vs lowercase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GraphQL stuff
| const threads = await getThreadsByChannels(channels, { | ||
| first, | ||
| after: lastThreadIndex, | ||
| sort: sort === 'NEW' ? 'new' : 'trending', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caps vs lowercase - then we could just say: { sort } if the sort argument is either new or trending
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This translates the external GraphQL stuff to the internal db query options.
api/types/Community.js
Outdated
| } | ||
| enum CommunityThreadConnectionSort { | ||
| NEW |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
caps vs lowercase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GraphQL stuff
api/types/Community.js
Outdated
| threadConnection( | ||
| first: Int = 10 | ||
| after: String | ||
| sort: CommunityThreadConnectionSort = NEW |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
caps vs lowercase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GraphQL stuff
|
Oh damn I thought all our GraphQL enums were purely uppercase, that's why I did the external stuff uppercase and internal stuff lowercase—but I just now realized GraphQL enums can also be lower case 🤦♂️ Thanks for calling me out on that, you're totally right those should be lower case. On it! |
|
This should be ready to go, assuming e2e tests pass. The only thing I'm not sure about is how we're going to handle assigning a score to all existing threads—should we just manually add a |
Seems fine to do?
|
|
Shipping mercury and the the API! |










Status
Deploy after merge (delete what needn't be deployed)
Deploy in that order!!
Related issues (delete if you don't know of any)
Supersedes and thus closes #3727
Supersedes and thus closes #3726
Closes #3718
Based on the conversations in #3727 here is a new approach to frecency thread feeds.
TODO
calculateThreadScorequeuescoreandscoreUpdatedAtfor each threadsortargument toCommunity.threadConnectionGraphQL typeAddsortargument toChannel.threadConnectionGraphQL type