Merge pull request 'calculate_priority: resolve non-finite prices to 0 instead of crashing the monitor' (#25) from development into main

This commit was merged in pull request #25.
This commit is contained in:
dsql committed 2026-10-08 22:48:57 +00:00
commit 7d514a5401
2 files changed
+33 -5

No files matched your search

+16 -5
View File
@@ -7,6 +7,7 @@ alert references for new products and price changes.
"""
import logging
import math
from dataclasses import asdict
from datetime import datetime, timezone
from functools import cache
@@ -318,10 +319,13 @@ def calculate_priority(document: dict) -> int:
Always recalculated from current and original price so the priority
reflects the prices at alert time rather than any stale stored
percentage. Missing prices, zero original prices, and price increases
resolve to priority 0. A product with no MSRP has no percentage to rank
on and takes NO_MSRP_PRIORITY instead, since a real 0 would leave it
permanently behind every other alert in the claim query's sort. A new
percentage. Missing prices, zero original prices, non-finite prices, a
discount too large to represent, and price increases resolve to priority
0, so one product's bad pricing can never raise out of the whole cycle (a
retailer field like "Infinity" survives float() and used to crash the
monitor with an OverflowError). A product with no MSRP has no percentage
to rank on and takes NO_MSRP_PRIORITY instead, since a real 0 would leave
it permanently behind every other alert in the claim query's sort. A new
listing is floored at NEW_LISTING_PRIORITY for the same reason: it may
carry any discount at all, and its percentage rank still wins when higher.
@@ -337,10 +341,17 @@ def calculate_priority(document: dict) -> int:
if current_price is None or not original_price:
return 0
if not (math.isfinite(current_price) and math.isfinite(original_price)):
return 0
if not document.get("hasMsrp", True):
return NO_MSRP_PRIORITY
percentage = int(((original_price - current_price) / original_price) * 100)
discount = ((original_price - current_price) / original_price) * 100
if not math.isfinite(discount):
return 0
percentage = int(discount)
priority = min(max(percentage // 10, 0), 10)
if document.get("newListing"):
return max(priority, NEW_LISTING_PRIORITY)
+17
View File
@@ -50,6 +50,23 @@ def test_broken_prices_still_outrank_nothing():
assert calculate_priority(document(None, 100.0, hasMsrp=False)) == 0
def test_non_finite_prices_resolve_to_zero_instead_of_raising():
"""float("Infinity") from a retailer field once crashed the whole monitor."""
inf, nan = float("inf"), float("nan")
assert calculate_priority(document(50.0, inf)) == 0
assert calculate_priority(document(inf, 100.0)) == 0
assert calculate_priority(document(-inf, 100.0)) == 0
assert calculate_priority(document(nan, 100.0)) == 0
assert calculate_priority(document(50.0, nan)) == 0
assert calculate_priority(document(50.0, inf, newListing=True)) == 0
def test_a_discount_too_large_to_represent_resolves_to_zero():
"""Finite prices can still overflow the ratio (a subnormal original)."""
assert calculate_priority(document(-1e308, 5e-324)) == 0
assert calculate_priority(document(1e308, 5e-324)) == 0
def test_new_listing_is_floored_not_buried():
"""A low-discount new listing sends regardless, so it must not sort last."""
assert (