Compare commits

...
2 changed files with 122 additions and 2 deletions
+91
View File
@@ -1309,6 +1309,97 @@ describe("public skill list deterministic cursors", () => {
expect(result.items[0]).toMatchObject({ latestVersion: null });
});
it("falls back to the general trending snapshot during non-suspicious rollout", async () => {
const digest = makeSearchDigest();
const requestedKinds: string[] = [];
const ctx = {
db: {
query: vi.fn((table: string) => {
if (table === "skillLeaderboards") {
return {
withIndex: vi.fn(
(
_indexName: string,
builder: (q: { eq: (field: string, value: string) => unknown }) => unknown,
) => {
const queryBuilder = {
eq: (_field: string, value: string) => {
requestedKinds.push(value);
return queryBuilder;
},
};
builder(queryBuilder);
return {
order: () => ({
first: async () =>
requestedKinds.at(-1) === "trending_non_suspicious"
? null
: { items: [{ skillId: "skills:demo" }] },
}),
};
},
),
};
}
if (table === "skillSearchDigest") {
return {
withIndex: () => ({
unique: async () => digest,
}),
};
}
throw new Error(`unexpected table ${table}`);
}),
},
};
const result = await listPublicTrendingPageHandler(ctx as never, {
limit: 10,
nonSuspiciousOnly: true,
});
expect(requestedKinds).toEqual(["trending_non_suspicious", "trending"]);
expect(result.items).toHaveLength(1);
expect(result.items[0]).toMatchObject({ skill: { slug: "demo" } });
});
it("warms trending with recent public skills before the first snapshot exists", async () => {
const digest = makeSearchDigest({ updatedAt: 12 });
const ctx = {
db: {
query: vi.fn((table: string) => {
if (table === "skillLeaderboards") {
return {
withIndex: () => ({
order: () => ({
first: async () => null,
}),
}),
};
}
if (table === "skillSearchDigest") {
return {
withIndex: () => ({
order: () => ({
take: async () => [digest],
}),
}),
};
}
throw new Error(`unexpected table ${table}`);
}),
},
};
const result = await listPublicTrendingPageHandler(ctx as never, {
limit: 10,
nonSuspiciousOnly: true,
});
expect(result.items).toHaveLength(1);
expect(result.items[0]).toMatchObject({ skill: { slug: "demo" } });
});
it("keeps verified legacy trending latest versions without owner markers", async () => {
const legacyDigest = makeSearchDigest({
latestVersionSkillId: undefined,
+31 -2
View File
@@ -5868,13 +5868,42 @@ export const listPublicTrendingPage = query({
const kind = args.nonSuspiciousOnly
? TRENDING_NON_SUSPICIOUS_LEADERBOARD_KIND
: TRENDING_LEADERBOARD_KIND;
const leaderboard = await ctx.db
let leaderboard = await ctx.db
.query("skillLeaderboards")
.withIndex("by_kind", (q) => q.eq("kind", kind))
.order("desc")
.first();
if (!leaderboard) return { items: [], nextCursor: null };
// Older deployments may have the general snapshot but not the
// non-suspicious snapshot yet. Keep trending populated during rollout.
if (!leaderboard && args.nonSuspiciousOnly) {
leaderboard = await ctx.db
.query("skillLeaderboards")
.withIndex("by_kind", (q) => q.eq("kind", TRENDING_LEADERBOARD_KIND))
.order("desc")
.first();
}
if (!leaderboard) {
// The first leaderboard snapshot may not exist yet after deployment.
// Use a bounded recent catalog warm-up instead of rendering an empty page.
const fallbackDigests = await ctx.db
.query("skillSearchDigest")
.withIndex("by_active_updated", (q) => q.eq("softDeletedAt", undefined))
.order("desc")
.take(Math.min(Math.max(limit * 8, limit), 200));
const fallbackItems: PublicSkillEntry[] = [];
for (const digest of fallbackDigests) {
if (args.nonSuspiciousOnly && digest.isSuspicious) continue;
if (categorySlug && !resolveStoredSkillCategories(digest).includes(categorySlug)) continue;
if (topic && !getCatalogTopicSlugs(digest.topics).includes(topic)) continue;
const item = await buildPublicSkillEntryFromDigest(ctx, digest);
if (!item) continue;
fallbackItems.push(item);
if (fallbackItems.length >= limit) break;
}
return { items: fallbackItems, nextCursor: null };
}
const items: PublicSkillEntry[] = [];
for (const entry of leaderboard.items) {