Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 3x 61x 61x 31x 31x 6x 4x 61x | import { and, desc, eq, inArray, isNotNull } from "drizzle-orm";
import type { getDb } from "../../db";
import { projects } from "../../db/schema/projects";
// D1 allows 100 bound parameters per statement; the WHERE below adds one
// (status), so 90 ids per query leaves headroom.
const PRO_ID_CHUNK = 90;
/**
* Newest published project cover per pro, for the search index. Shared by the
* hourly cron and the admin rebuild route; chunked because an unchunked
* `inArray` fails ("too many SQL variables") once the catalog passes ~98 pros.
*/
export async function loadFirstCoverByProId(
db: ReturnType<typeof getDb>,
proIds: string[],
): Promise<Map<string, string>> {
const firstCoverByProId = new Map<string, string>();
for (let i = 0; i < proIds.length; i += PRO_ID_CHUNK) {
const rows = await db
.select({ proId: projects.proId, coverImage: projects.coverImage })
.from(projects)
.where(
and(
inArray(projects.proId, proIds.slice(i, i + PRO_ID_CHUNK)),
eq(projects.status, "published"),
isNotNull(projects.coverImage),
),
)
.orderBy(desc(projects.dateCreated));
for (const row of rows) {
if (row.coverImage && !firstCoverByProId.has(row.proId)) {
firstCoverByProId.set(row.proId, row.coverImage);
}
}
}
return firstCoverByProId;
}
|