fix(stock): 7-day heartbeat write bypasses dedup for stale observations

upsertStockObservation dedup guard was preventing writes for unchanged
stock data (e.g. ATGBICS all-OOS for 55d), causing v_scraper_health to
mark sources as dead even when scrapers run normally. Skip dedup when
last observation is >7 days old so health view stays current.
This commit is contained in:
root 2026-07-07 11:39:38 +00:00
parent 86d1531d52
commit 73ad10f1a6

View File

@ -417,9 +417,11 @@ export async function upsertStockObservation(params: {
return false; return false;
} }
// Compare against the last observation to avoid duplicate writes // Compare against the last observation to avoid duplicate writes.
// Bypass dedup if last observation is older than 7 days (heartbeat to keep health view alive).
const STOCK_REFRESH_DAYS = 7;
const lastObs = await pool.query( const lastObs = await pool.query(
`SELECT warehouse_de_qty, warehouse_global_qty, backorder_qty, units_sold, quantity_available `SELECT warehouse_de_qty, warehouse_global_qty, backorder_qty, units_sold, quantity_available, time
FROM stock_observations FROM stock_observations
WHERE transceiver_id = $1 AND source_vendor_id = $2 WHERE transceiver_id = $1 AND source_vendor_id = $2
ORDER BY time DESC LIMIT 1`, ORDER BY time DESC LIMIT 1`,
@ -428,6 +430,9 @@ export async function upsertStockObservation(params: {
if (lastObs.rows.length > 0) { if (lastObs.rows.length > 0) {
const r = lastObs.rows[0]; const r = lastObs.rows[0];
const ageMs = Date.now() - new Date(r.time).getTime();
const ageDays = ageMs / (1000 * 60 * 60 * 24);
if (ageDays < STOCK_REFRESH_DAYS) {
const unchanged = const unchanged =
(r.warehouse_de_qty ?? null) === (params.warehouseDeQty ?? null) && (r.warehouse_de_qty ?? null) === (params.warehouseDeQty ?? null) &&
(r.warehouse_global_qty ?? null) === (params.warehouseGlobalQty ?? null) && (r.warehouse_global_qty ?? null) === (params.warehouseGlobalQty ?? null) &&
@ -436,6 +441,7 @@ export async function upsertStockObservation(params: {
(r.quantity_available ?? null) === (params.quantityAvailable ?? null); (r.quantity_available ?? null) === (params.quantityAvailable ?? null);
if (unchanged) return false; if (unchanged) return false;
} }
}
const inStock = const inStock =
((params.warehouseDeQty ?? 0) + (params.warehouseGlobalQty ?? 0) + (params.quantityAvailable ?? 0)) > 0; ((params.warehouseDeQty ?? 0) + (params.warehouseGlobalQty ?? 0) + (params.quantityAvailable ?? 0)) > 0;