Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions layers/registry/server/utils/trending-awards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import type { TrendingAward, TrendingAwardBoard } from '#shared/trending-award'
import type { SkillRef } from './trending-admission'
import { loadTrendingBoard } from '#shared/server/trending-board'
import { loadTrendingBoardSkills } from '#shared/server/trending-board'
import { compareTrendingAwards, TRENDING_AWARD_BOARDS, trendingAwardPeriod } from '#shared/trending-award'
import { TRENDING_BOARD_LIMIT, trendingRangeMeta } from '#shared/trending-range'
import { admissionKey } from './trending-admission'
Expand Down Expand Up @@ -41,7 +41,7 @@ export async function loadAwardSightings(db: D1Database, now: number): Promise<A
const windowHours = trendingRangeMeta(board).windowHours
if (windowHours === null)
continue
const { namedSkills } = await loadTrendingBoard({ db, now, limit: TRENDING_BOARD_LIMIT, windowHours })
const namedSkills = await loadTrendingBoardSkills({ db, now, limit: TRENDING_BOARD_LIMIT, windowHours })
namedSkills.forEach((entry, index) => {
const evidenced = entry.evidence !== null || (entry.github?.latestGain ?? null) !== null
if (evidenced)
Expand Down
14 changes: 12 additions & 2 deletions shared/server/trending-board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,18 @@ export interface LoadTrendingBoardOptions {
windowHours: number
}

/** The named rows used by both the public board and its awards. */
export async function loadTrendingBoardSkills(
options: LoadTrendingBoardOptions,
deprioritizeRepositories?: ReadonlySet<string>,
): Promise<TrendingSkill[]> {
const demoted = deprioritizeRepositories
?? await loadTopStarredRepositories(options.db, DEMOTED_STARRED_REPOSITORIES)
return loadTrendingSkills({ ...options, deprioritizeRepositories: demoted })
}

export async function loadTrendingBoard(options: LoadTrendingBoardOptions): Promise<TrendingBoard> {
const { db, now, limit, windowHours } = options
const { db, now, limit } = options
// The page header states this demotion, so it reads the same constant.
const deprioritizeRepositories = await loadTopStarredRepositories(db, DEMOTED_STARRED_REPOSITORIES)
const [entries, namedSkills] = await Promise.all([
Expand All @@ -61,7 +71,7 @@ export async function loadTrendingBoard(options: LoadTrendingBoardOptions): Prom
}),
// Same `limit` the repository half gets. A hardcoded 12 here once made the
// caller's `?limit=` a lie for the collection the page renders.
loadTrendingSkills({ db, now, windowHours, limit, deprioritizeRepositories }),
loadTrendingBoardSkills(options, deprioritizeRepositories),
])

const fallback = namedSkills.length >= MIN_BEFORE_FALLBACK
Expand Down
48 changes: 47 additions & 1 deletion test/unit/trending-awards.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import type { SqliteD1 } from './helpers/d1-sqlite'
import { afterEach, describe, expect, it } from 'vitest'
import { parseSkillTrendingAwards, planAwardWrites, recordTrendingAwards, SKILL_TRENDING_AWARDS_SQL } from '../../layers/registry/server/utils/trending-awards'
import { loadAwardSightings, parseSkillTrendingAwards, planAwardWrites, recordTrendingAwards, SKILL_TRENDING_AWARDS_SQL } from '../../layers/registry/server/utils/trending-awards'
import { createSkillBadgeResponse, loadSkillBadgeAward } from '../../server/utils/skill-badge'
import { loadTrendingBoard } from '../../shared/server/trending-board'
import { skillBadgeImagePath } from '../../shared/skill-badge'
import {
headlineTrendingAward,
trendingAwardBadgeLabel,
trendingAwardLabel,
trendingAwardPeriod,
} from '../../shared/trending-award'
import { TRENDING_BOARD_LIMIT, trendingRangeMeta } from '../../shared/trending-range'
import { allMigrations, createSqliteD1 } from './helpers/d1-sqlite'

// Wednesday 1 Oct 2026, 12:00 UTC.
Expand Down Expand Up @@ -123,6 +125,50 @@ describe('planAwardWrites', () => {
})

describe('recordTrendingAwards', () => {
it('loads awards within twelve reads without loading unused Repository boards', async () => {
harness = createSqliteD1(allMigrations(), { maximumQueries: 12 })
addSkill({ owner: 'a', repo: 'one', name: 'first' })
mention({ owner: 'a', repo: 'one', name: 'first', handle: 'h1', at: NOW - 3600 })

expect(await loadAwardSightings(db().db, NOW)).toEqual([
{ board: 'week', rank: 1, skill: { owner: 'a', repo: 'one', name: 'first' } },
{ board: 'month', rank: 1, skill: { owner: 'a', repo: 'one', name: 'first' } },
])
})

it('matches full board positions across demotion, windows, and GitHub evidence', async () => {
for (let i = 0; i < 20; i++)
addSkill({ owner: `quiet${i}`, repo: 'repo', name: 'filler', stars: 100_000 })
addSkill({ owner: 'known', repo: 'repo', name: 'popular', stars: 1_000_000 })
addSkill({ owner: 'new', repo: 'repo', name: 'discovery' })
addSkill({ owner: 'old', repo: 'repo', name: 'monthly' })
addSkill({ owner: 'surging', repo: 'repo', name: 'github' })
mention({ owner: 'known', repo: 'repo', name: 'popular', handle: 'h1', at: NOW - 3600 })
mention({ owner: 'known', repo: 'repo', name: 'popular', handle: 'h2', at: NOW - 3600 })
mention({ owner: 'new', repo: 'repo', name: 'discovery', handle: 'h3', at: NOW - 3600 })
mention({ owner: 'old', repo: 'repo', name: 'monthly', handle: 'h4', at: NOW - 8 * DAY })
db().raw.prepare(`INSERT INTO repo_star_surges
(owner, repo, observed_day, latest_gain, baseline_gain, stars, detected_at)
VALUES ('surging', 'repo', ?, 900, 10, 1000, ?)`).run(Math.floor((NOW - DAY) / DAY) * DAY, NOW - DAY)

const sightings = await loadAwardSightings(db().db, NOW)
for (const board of ['week', 'month'] as const) {
const { namedSkills } = await loadTrendingBoard({
db: db().db,
now: NOW,
limit: TRENDING_BOARD_LIMIT,
windowHours: trendingRangeMeta(board).windowHours!,
})
expect(sightings.filter(sighting => sighting.board === board)).toEqual(
namedSkills.flatMap((entry, index) => entry.evidence !== null || entry.github?.latestGain != null
? [{ board, rank: index + 1, skill: { owner: entry.owner, repo: entry.repo, name: entry.slug } }]
: []),
)
}
expect(sightings.filter(s => s.board === 'week').map(s => s.skill.owner)).toEqual(['new', 'surging', 'known'])
expect(sightings.filter(s => s.skill.owner === 'old').map(s => s.board)).toEqual(['month'])
})

it('awards evidenced rows by board position and keeps the award after they leave', async () => {
addSkill({ owner: 'anthropics', repo: 'skills', name: 'frontend-design' })
addSkill({ owner: 'emil', repo: 'skills', name: 'animate' })
Expand Down
Loading