perf: reuse sample dimensions and catalog digest
This commit is contained in:
parent
7142f10cfe
commit
1064e356de
2 changed files with 78 additions and 17 deletions
|
|
@ -273,6 +273,10 @@ class RecognitionEngine:
|
|||
self.settings.image_store_max_bytes,
|
||||
)
|
||||
self._catalog_cache: Optional[Tuple[str, List[Dict[str, Any]]]] = None
|
||||
# (version, csv mtime_ns, csv size, sorted image name:size). Version is
|
||||
# the content digest; the rest is the cheap fingerprint that invalidates it.
|
||||
self._catalog_version_cache: Optional[Tuple[str, int, int, Tuple[Tuple[str, int], ...]]] = None
|
||||
self._catalog_version_lock = threading.Lock()
|
||||
self._started_at = time.time()
|
||||
|
||||
# ------------------------------------------------------------------ lifecycle
|
||||
|
|
@ -477,6 +481,8 @@ class RecognitionEngine:
|
|||
len(gallery.sku_ids),
|
||||
gallery.device,
|
||||
)
|
||||
if gallery.head_reason != "ok":
|
||||
LOGGER.warning("identity head: %s (%s)", gallery.head_reason, gallery._head_path)
|
||||
else:
|
||||
LOGGER.warning("identity gallery unavailable; gallery requests stay unrecognized")
|
||||
return gallery if loaded else None
|
||||
|
|
@ -606,24 +612,53 @@ class RecognitionEngine:
|
|||
|
||||
# ------------------------------------------------------------------ catalog
|
||||
def catalog_version(self) -> str:
|
||||
digest = hashlib.sha256()
|
||||
"""12-hex digest of stock.csv bytes plus template image names and sizes.
|
||||
|
||||
Unchanged files reuse the digest. A stock update that has not been written
|
||||
back to the CSV still changes the digest, because the in-memory fingerprint
|
||||
is dropped. Same-size content rewritten without a new mtime is not detected
|
||||
until the next stock update or a real stat change.
|
||||
"""
|
||||
csv_path = os.path.join(self.settings.stock_dir, self.settings.stock_csv)
|
||||
try:
|
||||
with open(csv_path, "rb") as handle:
|
||||
digest.update(handle.read())
|
||||
stat = os.stat(csv_path)
|
||||
csv_key = (stat.st_mtime_ns, stat.st_size)
|
||||
except OSError:
|
||||
digest.update(b"missing-csv")
|
||||
csv_key = None
|
||||
try:
|
||||
entries = sorted(
|
||||
entries = tuple(sorted(
|
||||
(name, os.path.getsize(os.path.join(self.settings.stock_dir, name)))
|
||||
for name in os.listdir(self.settings.stock_dir)
|
||||
if name.lower().endswith((".jpeg", ".jpg", ".png"))
|
||||
)
|
||||
))
|
||||
except OSError:
|
||||
entries = []
|
||||
entries = ()
|
||||
fingerprint = (
|
||||
csv_key[0] if csv_key else -1,
|
||||
csv_key[1] if csv_key else -1,
|
||||
entries,
|
||||
)
|
||||
with self._catalog_version_lock:
|
||||
cached = self._catalog_version_cache
|
||||
if cached is not None and csv_key is not None and cached[1:] == fingerprint:
|
||||
return cached[0]
|
||||
digest = hashlib.sha256()
|
||||
if csv_key is None:
|
||||
digest.update(b"missing-csv")
|
||||
else:
|
||||
try:
|
||||
with open(csv_path, "rb") as handle:
|
||||
digest.update(handle.read())
|
||||
except OSError:
|
||||
digest.update(b"missing-csv")
|
||||
csv_key = None
|
||||
for name, size in entries:
|
||||
digest.update(f"{name}:{size}".encode("utf-8"))
|
||||
return digest.hexdigest()[:12]
|
||||
version = digest.hexdigest()[:12]
|
||||
if csv_key is not None:
|
||||
with self._catalog_version_lock:
|
||||
self._catalog_version_cache = (version, csv_key[0], csv_key[1], entries)
|
||||
return version
|
||||
|
||||
def model_version(self) -> str:
|
||||
try:
|
||||
|
|
@ -689,6 +724,8 @@ class RecognitionEngine:
|
|||
product = self.inventory.get_product(sku_id) or {}
|
||||
payload = self._product_payload(sku_id, product)
|
||||
self._catalog_cache = None
|
||||
with self._catalog_version_lock:
|
||||
self._catalog_version_cache = None
|
||||
return payload
|
||||
|
||||
def sku_count(self) -> int:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue