diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index 36b561e27..0352f71f0 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -1309,6 +1309,7 @@ export type HomeItem = { likeCount?: Maybe; previewContent?: Maybe; saveCount?: Maybe; + score: Scalars['Float']; seen_at?: Maybe; slug?: Maybe; source?: Maybe; @@ -2872,6 +2873,7 @@ export type SearchItem = { readingProgressTopPercent?: Maybe; recommendations?: Maybe>; savedAt: Scalars['Date']; + score?: Maybe; shortId?: Maybe; siteIcon?: Maybe; siteName?: Maybe; @@ -6075,6 +6077,7 @@ export type HomeItemResolvers, ParentType, ContextType>; previewContent?: Resolver, ParentType, ContextType>; saveCount?: Resolver, ParentType, ContextType>; + score?: Resolver; seen_at?: Resolver, ParentType, ContextType>; slug?: Resolver, ParentType, ContextType>; source?: Resolver, ParentType, ContextType>; @@ -6859,6 +6862,7 @@ export type SearchItemResolvers, ParentType, ContextType>; recommendations?: Resolver>, ParentType, ContextType>; savedAt?: Resolver; + score?: Resolver, ParentType, ContextType>; shortId?: Resolver, ParentType, ContextType>; siteIcon?: Resolver, ParentType, ContextType>; siteName?: Resolver, ParentType, ContextType>; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index 2226d1d2a..29a98e88c 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -1178,6 +1178,7 @@ type HomeItem { likeCount: Int previewContent: String saveCount: Int + score: Float! seen_at: Date slug: String source: HomeItemSource @@ -2214,6 +2215,7 @@ type SearchItem { readingProgressTopPercent: Float recommendations: [Recommendation!] savedAt: Date! + score: Float shortId: String siteIcon: String siteName: String diff --git a/packages/api/src/jobs/update_home.ts b/packages/api/src/jobs/update_home.ts index f2d6d5e59..cd3afdb40 100644 --- a/packages/api/src/jobs/update_home.ts +++ b/packages/api/src/jobs/update_home.ts @@ -5,7 +5,7 @@ import { User } from '../entity/user' import { redisDataSource } from '../redis_data_source' import { findUnseenPublicItems } from '../services/home' import { searchLibraryItems } from '../services/library_item' -import { Feature, getScores, ScoreApiResponse } from '../services/score' +import { Feature, getScores } from '../services/score' import { findSubscriptionsByNames } from '../services/subscriptions' import { findActiveUser } from '../services/user' import { lanaugeToCode } from '../utils/helpers' @@ -34,7 +34,7 @@ interface Candidate { siteIcon?: string siteName?: string folder?: string - score?: number + score: number publishedAt?: Date subscription?: { name: string @@ -45,6 +45,7 @@ interface Candidate { interface Item { id: string type: string + score: number } interface Section { @@ -71,7 +72,7 @@ const libraryItemToCandidate = ( siteName: item.siteName || undefined, siteIcon: item.siteIcon || undefined, folder: item.folder, - score: item.score, + score: item.score || 0, publishedAt: item.publishedAt || undefined, subscription: subscriptions.find( (subscription) => @@ -100,6 +101,7 @@ const publicItemToCandidate = (item: PublicItem): Candidate => ({ name: item.source.name, type: item.source.type, }, + score: 0, }) const selectCandidates = async (user: User): Promise> => { @@ -157,14 +159,7 @@ const rankCandidates = async ( userId: string, candidates: Array ): Promise> => { - if (candidates.length <= 10) { - // no need to rank if there are less than 10 candidates - return candidates - } - - const unscoredCandidates = candidates.filter( - (item) => item.score === undefined - ) + const unscoredCandidates = candidates.filter((item) => item.score === 0) const data = { user_id: userId, @@ -190,21 +185,13 @@ const rankCandidates = async ( } const newScores = await getScores(data) - const preCalculatedScores = candidates - .filter((item) => item.score !== undefined) - .reduce((acc, item) => { - acc[item.id] = item.score as number - return acc - }, {} as ScoreApiResponse) - const scores = { ...preCalculatedScores, ...newScores } + // update scores for candidates + candidates.forEach((item) => { + item.score = newScores[item.id] || 0 + }) // rank candidates by score in ascending order - candidates.sort((a, b) => { - const scoreA = scores[a.id] || 0 - const scoreB = scores[b.id] || 0 - - return scoreA - scoreB - }) + candidates.sort((a, b) => a.score - b.score) return candidates } @@ -360,6 +347,7 @@ const mixHomeItems = (rankedHomeItems: Array): Array
=> { items: batch.slice(0, 5).map((item) => ({ id: item.id, type: item.type, + score: item.score, })), layout: 'quick links', }) @@ -367,7 +355,7 @@ const mixHomeItems = (rankedHomeItems: Array): Array
=> { // create a section for each long item sections.push( ...batch.slice(5).map((item) => ({ - items: [{ id: item.id, type: item.type }], + items: [{ id: item.id, type: item.type, score: item.score }], layout: 'long', })) ) @@ -391,6 +379,11 @@ export const updateHome = async (data: UpdateHomeJobData) => { const candidates = await selectCandidates(user) logger.info(`Found ${candidates.length} candidates`) + if (candidates.length <= 10) { + logger.info('Not enough candidates found') + return + } + // TODO: integrity check on candidates logger.info('Ranking candidates') diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index 5681597d7..45bfc9dfd 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -636,7 +636,11 @@ export const functionResolvers = { HomeSection: { async items( section: { - items: Array<{ id: string; type: 'library_item' | 'public_item' }> + items: Array<{ + id: string + type: 'library_item' | 'public_item' + score: number + }> }, _: unknown, ctx: WithDataSourcesContext @@ -687,6 +691,7 @@ export const functionResolvers = { siteName: libraryItem.siteName, siteIcon: libraryItem.siteIcon, slug: libraryItem.slug, + score: item.score, } } @@ -713,6 +718,7 @@ export const functionResolvers = { likeCount: publicItem.stats.likeCount, saveCount: publicItem.stats.saveCount, source: publicItem.source, + score: item.score, } } }) diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index 000a628cb..c0986f4a3 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -1676,6 +1676,7 @@ const schema = gql` aiSummary: String directionality: DirectionalityType format: String + score: Float } type SearchItemEdge { @@ -3145,6 +3146,7 @@ const schema = gql` canShare: Boolean canArchive: Boolean canDelete: Boolean + score: Float! } type HomeSection {