Skip to content

Commit ec419bc

Browse files
committed
fix: cache logic
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
1 parent a21c949 commit ec419bc

4 files changed

Lines changed: 29 additions & 10 deletions

File tree

services/apps/packages_worker/src/maven/README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,15 @@ critical packages, where data quality matters.
5050

5151
Parent POMs are shared across many artifacts of the same namespace (`org.apache:apache`,
5252
`org.springframework.boot:spring-boot-starter-parent`, `com.google.cloud:google-cloud-shared-config`, …).
53-
Because the queue is ordered by `rank_in_ecosystem`, those siblings are processed close
54-
together. A module-level, coordinate-keyed in-process cache in `extract.ts` collapses the
55-
repeated parent fetches into a **single** HTTP request, and also removes the redundant second
56-
fetch of each artifact's own POM (`extractArtifact` fetches the leaf, then
57-
`resolveWithInheritance` would fetch it again at depth 0). This is the **single biggest lever
58-
against Maven Central rate limiting** — and it works _because_ of the namespace clustering, so
59-
shuffling the batch (which the queue's `rank` ordering produces) would be counter-productive.
53+
The batch is **selected** by criticality (`rank_in_ecosystem` / `criticality_score` via the SQL
54+
`LIMIT`), but that ordering does **not** group same-namespace siblings — so before processing,
55+
`processPackages` re-sorts each critical batch by `(namespace, name)`. That sort is what puts the
56+
siblings adjacent, so a parent fetched for one is still cached when the next arrives. A
57+
module-level, coordinate-keyed in-process cache in `extract.ts` then collapses the repeated parent
58+
fetches into a **single** HTTP request, and also removes the redundant second fetch of each
59+
artifact's own POM (`extractArtifact` fetches the leaf, then `resolveWithInheritance` would fetch
60+
it again at depth 0). This is the **single biggest lever against Maven Central rate limiting** — and
61+
it works _because_ of the namespace sort, so re-shuffling the batch would be counter-productive.
6062

6163
- **Only successful fetches are cached.** `fetchPom` returns `null` for both a real 404 and a
6264
transient failure (throttle/timeout), so caching `null` would poison the cache — it is never

services/apps/packages_worker/src/maven/runMavenEnrichmentLoop.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ async function processCriticalPackage(
283283
allVersions.map((v) => ({
284284
packageId,
285285
ecosystem: 'maven',
286+
namespace: groupId,
286287
name: artifactId,
287288
number: v,
288289
isLatest: v === metadata.releaseVersion,
@@ -378,6 +379,18 @@ async function processPackages(
378379
if (packages.length === 0)
379380
return { processed: 0, skipped: 0, error: 0, unchanged: 0, hopLimitReached: 0 }
380381

382+
// Cluster the batch by namespace so artifacts sharing a parent POM are processed
383+
// adjacently — this is what makes the parent-POM cache effective. The criticality
384+
// ordering only decides *which* packages are in the batch (via the SQL LIMIT);
385+
// it does not group same-namespace siblings, so we reorder here. Only matters on
386+
// the critical path (the non-critical path issues no POM/parent HTTP).
387+
if (isCritical) {
388+
packages.sort(
389+
(a, b) =>
390+
(a.namespace ?? '').localeCompare(b.namespace ?? '') || a.name.localeCompare(b.name),
391+
)
392+
}
393+
381394
log.info({ count: packages.length, isCritical }, 'Batch started')
382395

383396
const counts = { processed: 0, skipped: 0, error: 0, unchanged: 0, hopLimitReached: 0 }

services/libs/data-access-layer/src/osspckgs/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export type IDbPackageMaintainerUpsert = {
5959
export type IDbVersionUpsert = {
6060
packageId: number
6161
ecosystem: string
62+
namespace: string | null
6263
name: string
6364
number: string
6465
isLatest: boolean

services/libs/data-access-layer/src/osspckgs/versions.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,23 @@ export async function upsertVersionsBatch(
3535
WHERE package_id = $(packageId)::bigint AND number = ANY($(numbers)::text[])
3636
),
3737
ins AS (
38-
INSERT INTO versions (package_id, ecosystem, name, number, is_latest, is_prerelease, licenses, last_synced_at)
38+
INSERT INTO versions (package_id, ecosystem, namespace, name, number, is_latest, is_prerelease, licenses, last_synced_at)
3939
SELECT
40-
t.package_id, t.ecosystem, t.name, t.number, t.is_latest, t.is_prerelease,
40+
t.package_id, t.ecosystem, t.namespace, t.name, t.number, t.is_latest, t.is_prerelease,
4141
CASE WHEN t.license IS NULL THEN NULL ELSE ARRAY[t.license] END,
4242
NOW()
4343
FROM UNNEST(
4444
$(packageIds)::bigint[],
4545
$(ecosystems)::text[],
46+
$(namespaces)::text[],
4647
$(names)::text[],
4748
$(numbers)::text[],
4849
$(isLatests)::bool[],
4950
$(isPreleases)::bool[],
5051
$(licenses)::text[]
51-
) AS t(package_id, ecosystem, name, number, is_latest, is_prerelease, license)
52+
) AS t(package_id, ecosystem, namespace, name, number, is_latest, is_prerelease, license)
5253
ON CONFLICT (package_id, number) DO UPDATE SET
54+
namespace = COALESCE(EXCLUDED.namespace, versions.namespace),
5355
is_latest = EXCLUDED.is_latest,
5456
is_prerelease = EXCLUDED.is_prerelease,
5557
licenses = COALESCE(EXCLUDED.licenses, versions.licenses),
@@ -68,6 +70,7 @@ export async function upsertVersionsBatch(
6870
packageId: versions[0].packageId,
6971
packageIds: versions.map((v) => v.packageId),
7072
ecosystems: versions.map((v) => v.ecosystem),
73+
namespaces: versions.map((v) => v.namespace),
7174
names: versions.map((v) => v.name),
7275
numbers: versions.map((v) => v.number),
7376
isLatests: versions.map((v) => v.isLatest),

0 commit comments

Comments
 (0)