Skip to content

Commit 5644f7a

Browse files
committed
fix: fixed scan model update issue
1 parent 8f1ae00 commit 5644f7a

4 files changed

Lines changed: 16 additions & 4 deletions

File tree

backend/src/routes/scans.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Prisma } from '@prisma/client';
12
import { Router } from 'express';
23
import { prisma } from '../db.js';
34
import {
@@ -161,7 +162,10 @@ export async function patchScanIfPresent(tx, scanId, body, { assertAvailable, av
161162
}
162163
data.status = status;
163164
if (status === 'pending' && existing.status !== 'pending') {
164-
data.reasoning = null;
165+
// Nullable Prisma JSON fields distinguish SQL NULL from the JSON scalar
166+
// `null`. Scan reasoning is either an object or SQL NULL; storing a JSON
167+
// scalar here breaks engine-side nested warning updates.
168+
data.reasoning = Prisma.DbNull;
165169
data.lastResumedAt = new Date();
166170
}
167171
}

backend/test/dataIntegrity.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import test from 'node:test';
22
import assert from 'node:assert/strict';
3+
import { Prisma } from '@prisma/client';
34

45
import { prismaUniqueConflict } from '../src/app.js';
56
import { DEFAULT_WORKFLOW_NAMES } from '../src/lib/defaultWorkflows.js';
@@ -338,7 +339,7 @@ test('failed scans resume through pending and establish a new error-history boun
338339
assert.equal(result.kind, 'updated');
339340
assert.equal(calls[0], 'lock');
340341
assert.equal(calls[1].data.status, 'pending');
341-
assert.equal(calls[1].data.reasoning, null);
342+
assert.equal(calls[1].data.reasoning, Prisma.DbNull);
342343
assert.ok(calls[1].data.lastResumedAt instanceof Date);
343344
});
344345

engine/open_kritt_engine/db.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,10 @@ def set_scan_storage_warning(
497497
"""
498498
UPDATE public.scans
499499
SET reasoning = jsonb_set(
500-
coalesce(reasoning, '{}'::jsonb),
500+
CASE
501+
WHEN jsonb_typeof(reasoning) = 'object' THEN reasoning
502+
ELSE '{}'::jsonb
503+
END,
501504
'{storage_warning}',
502505
%s::jsonb,
503506
true
@@ -519,6 +522,7 @@ def clear_scan_storage_warning(self, conn, scan_id: int) -> bool:
519522
SET reasoning = nullif(reasoning - 'storage_warning', '{}'::jsonb),
520523
updated_at = now()
521524
WHERE id = %s
525+
AND jsonb_typeof(reasoning) = 'object'
522526
AND reasoning ? 'storage_warning'
523527
RETURNING id
524528
""",

engine/tests/test_worker_backoff.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ def test_worker_clears_storage_warning_before_launching_after_recovery(monkeypat
350350
assert database.cleared == [58]
351351

352352

353-
def test_storage_warning_is_persisted_inside_scan_reasoning():
353+
def test_storage_warning_is_persisted_inside_object_normalized_scan_reasoning():
354354
conn = _RecordingConnection(rows=({"id": 58},))
355355

356356
assert Database("").set_scan_storage_warning(
@@ -362,6 +362,8 @@ def test_storage_warning_is_persisted_inside_scan_reasoning():
362362

363363
query, params = conn.calls[0]
364364
assert "'{storage_warning}'" in query
365+
assert "jsonb_typeof(reasoning) = 'object'" in query
366+
assert "ELSE '{}'::jsonb" in query
365367
assert "status IN ('prewarming_cache', 'running', 'post_processing')" in query
366368
assert params[0].obj["code"] == "low_storage"
367369
assert params[0].obj["free_bytes"] == 12 * 1024**3
@@ -375,6 +377,7 @@ def test_storage_warning_clear_preserves_other_scan_reasoning():
375377

376378
query, params = conn.calls[0]
377379
assert "reasoning - 'storage_warning'" in query
380+
assert "jsonb_typeof(reasoning) = 'object'" in query
378381
assert params == (58,)
379382

380383

0 commit comments

Comments
 (0)