Skip to content

Commit 5d3d19e

Browse files
committed
fix: filter deleted ranges in reads, fix reclaim + updated_at (CM-1258)
Signed-off-by: Uroš Marolt <uros@marolt.me>
1 parent 4c75c2d commit 5d3d19e

2 files changed

Lines changed: 18 additions & 9 deletions

File tree

  • services/libs/data-access-layer/src

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ export async function getAdvisoriesByPackageId(
10091009
${ADVISORY_RESOLUTION_EXPR} AS resolution
10101010
FROM advisory_packages ap
10111011
JOIN advisories a ON a.id = ap.advisory_id
1012-
LEFT JOIN advisory_affected_ranges ar ON ar.advisory_package_id = ap.id
1012+
LEFT JOIN advisory_affected_ranges ar ON ar.advisory_package_id = ap.id AND ar.deleted_at IS NULL
10131013
JOIN packages p ON p.id = ap.package_id
10141014
WHERE ap.package_id = $(packageId)::bigint
10151015
GROUP BY a.osv_id, a.severity, a.is_critical, p.latest_version
@@ -1117,7 +1117,7 @@ export async function getAdvisoriesByPurls(
11171117
FROM packages p
11181118
LEFT JOIN advisory_packages ap ON ap.package_id = p.id
11191119
LEFT JOIN advisories a ON a.id = ap.advisory_id
1120-
LEFT JOIN advisory_affected_ranges ar ON ar.advisory_package_id = ap.id
1120+
LEFT JOIN advisory_affected_ranges ar ON ar.advisory_package_id = ap.id AND ar.deleted_at IS NULL
11211121
WHERE p.purl = ANY($(purls))
11221122
GROUP BY p.purl, p.latest_version, a.osv_id, a.severity, a.is_critical
11231123
ORDER BY

services/libs/data-access-layer/src/packages/osv.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,12 @@ export async function upsertAdvisoryPackage(
150150
// produces zero writes: matching tuples are left untouched (not even an
151151
// `updated_at` bump), so no Sequin/Tinybird event fires for them either.
152152
//
153-
// Tuple in both old and new -> untouched. Tuple only in new -> upserted
154-
// (INSERT ON CONFLICT, clearing deleted_at in case it was previously
155-
// soft-deleted and OSV brought it back). Tuple only in old -> soft-deleted.
153+
// Tuple in both old and new, already a clean live OSV row -> untouched.
154+
// Tuple only in new, or matching a live deps.dev raw row on the same key ->
155+
// upserted (INSERT ON CONFLICT; clears deleted_at in case it was previously
156+
// soft-deleted, and clears range_raw/unaffected_raw to reclaim the row from
157+
// deps.dev — OSV wins on key overlap per ADR-0001 §Write semantics). Tuple
158+
// only in old -> soft-deleted.
156159
// Soft-delete (not hard-delete) is required because the unique key is the
157160
// value tuple itself: when OSV corrects a range, the corrected tuple has no
158161
// successor row to collapse into, so without deleted_at the stale tuple
@@ -181,8 +184,12 @@ export async function reconcileOsvRanges(
181184
ON CONFLICT (advisory_package_id, COALESCE(introduced_version, ''), COALESCE(fixed_version, ''), COALESCE(last_affected, ''))
182185
DO UPDATE SET
183186
updated_at = NOW(),
184-
deleted_at = NULL
187+
deleted_at = NULL,
188+
range_raw = NULL,
189+
unaffected_raw = NULL
185190
WHERE advisory_affected_ranges.deleted_at IS NOT NULL
191+
OR advisory_affected_ranges.range_raw IS NOT NULL
192+
OR advisory_affected_ranges.unaffected_raw IS NOT NULL
186193
`,
187194
{ advisoryPackageId, values: JSON.stringify(values) },
188195
)
@@ -191,7 +198,8 @@ export async function reconcileOsvRanges(
191198
await qx.result(
192199
`
193200
UPDATE advisory_affected_ranges ar
194-
SET deleted_at = NOW()
201+
SET deleted_at = NOW(),
202+
updated_at = NOW()
195203
WHERE ar.advisory_package_id = $(advisoryPackageId)
196204
AND ar.deleted_at IS NULL
197205
AND ar.range_raw IS NULL
@@ -225,7 +233,8 @@ export async function supersedeDepsDevRanges(
225233
await qx.result(
226234
`
227235
UPDATE advisory_affected_ranges
228-
SET deleted_at = NOW()
236+
SET deleted_at = NOW(),
237+
updated_at = NOW()
229238
WHERE advisory_package_id = $(advisoryPackageId)
230239
AND deleted_at IS NULL
231240
AND (range_raw IS NOT NULL OR unaffected_raw IS NOT NULL)
@@ -288,7 +297,7 @@ export async function getRangesForPackages(qx: QueryExecutor, ids: number[]): Pr
288297
a.osv_id
289298
FROM advisory_packages ap
290299
JOIN advisories a ON a.id = ap.advisory_id
291-
JOIN advisory_affected_ranges ar ON ar.advisory_package_id = ap.id
300+
JOIN advisory_affected_ranges ar ON ar.advisory_package_id = ap.id AND ar.deleted_at IS NULL
292301
WHERE ap.package_id IN ($(ids:csv))
293302
AND (a.is_critical = TRUE OR a.osv_id LIKE 'MAL-%')
294303
`,

0 commit comments

Comments
 (0)