dev #21
@@ -5,6 +5,7 @@ from datetime import datetime
|
|||||||
from math import ceil
|
from math import ceil
|
||||||
from queue import Empty, Queue
|
from queue import Empty, Queue
|
||||||
from typing import List, Optional, Set, Union
|
from typing import List, Optional, Set, Union
|
||||||
|
from time import monotonic # <-- NEW
|
||||||
|
|
||||||
import loguru
|
import loguru
|
||||||
from PySide6.QtCore import QThread, Signal
|
from PySide6.QtCore import QThread, Signal
|
||||||
@@ -49,13 +50,10 @@ def _same_book(a: BookData, b: BookData) -> bool:
|
|||||||
|
|
||||||
# strong title match required; then author if available; then year if available
|
# strong title match required; then author if available; then year if available
|
||||||
if ta and tb and ta == tb:
|
if ta and tb and ta == tb:
|
||||||
# if both have authors, require match
|
|
||||||
if aa and ab and aa == ab:
|
if aa and ab and aa == ab:
|
||||||
# if both have year, require match
|
|
||||||
if ya and yb:
|
if ya and yb:
|
||||||
return ya == yb
|
return ya == yb
|
||||||
return True
|
return True
|
||||||
# if one/both authors missing, allow title (+year if both present)
|
|
||||||
if ya and yb:
|
if ya and yb:
|
||||||
return ya == yb
|
return ya == yb
|
||||||
return True
|
return True
|
||||||
@@ -116,6 +114,10 @@ class NewEditionCheckerThread(QThread):
|
|||||||
total_entries_signal = Signal(int)
|
total_entries_signal = Signal(int)
|
||||||
resultsSignal = Signal(list) # list[tuple[BookData, list[BookData]]]
|
resultsSignal = Signal(list) # list[tuple[BookData, list[BookData]]]
|
||||||
|
|
||||||
|
# NEW: metrics signals
|
||||||
|
rateSignal = Signal(float) # items per second ("it/s")
|
||||||
|
etaSignal = Signal(int) # seconds remaining (-1 when unknown)
|
||||||
|
|
||||||
def __init__(self, entries: Optional[list["BookData"]] = None, parent=None):
|
def __init__(self, entries: Optional[list["BookData"]] = None, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.entries: list["BookData"] = entries if entries is not None else []
|
self.entries: list["BookData"] = entries if entries is not None else []
|
||||||
@@ -194,6 +196,11 @@ class NewEditionCheckerThread(QThread):
|
|||||||
for entry in response
|
for entry in response
|
||||||
if not (_norm_isbns(entry.isbn) & _norm_isbns(book.isbn))
|
if not (_norm_isbns(entry.isbn) & _norm_isbns(book.isbn))
|
||||||
]
|
]
|
||||||
|
response = [
|
||||||
|
entry
|
||||||
|
for entry in response
|
||||||
|
if book.publisher in entry.publisher
|
||||||
|
]
|
||||||
|
|
||||||
if not response:
|
if not response:
|
||||||
return None
|
return None
|
||||||
@@ -221,8 +228,14 @@ class NewEditionCheckerThread(QThread):
|
|||||||
total = len(self.entries)
|
total = len(self.entries)
|
||||||
self.total_entries_signal.emit(total)
|
self.total_entries_signal.emit(total)
|
||||||
|
|
||||||
|
# start timer for metrics
|
||||||
|
t0 = monotonic()
|
||||||
|
|
||||||
if total == 0:
|
if total == 0:
|
||||||
log.debug("No entries to process.")
|
log.debug("No entries to process.")
|
||||||
|
# emit metrics (zero work)
|
||||||
|
self.rateSignal.emit(0.0)
|
||||||
|
self.etaSignal.emit(0)
|
||||||
self.resultsSignal.emit([])
|
self.resultsSignal.emit([])
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -255,9 +268,27 @@ class NewEditionCheckerThread(QThread):
|
|||||||
processed += int(payload)
|
processed += int(payload)
|
||||||
self.updateSignal.emit(processed, total)
|
self.updateSignal.emit(processed, total)
|
||||||
self.updateProgress.emit(processed, total)
|
self.updateProgress.emit(processed, total)
|
||||||
|
|
||||||
|
# ---- NEW: compute & emit metrics ----
|
||||||
|
elapsed = max(1e-9, monotonic() - t0)
|
||||||
|
rate = processed / elapsed # items per second
|
||||||
|
remaining = max(0, total - processed)
|
||||||
|
eta_sec = int(round(remaining / rate)) if rate > 0 else -1
|
||||||
|
|
||||||
|
self.rateSignal.emit(rate)
|
||||||
|
# clamp negative just in case
|
||||||
|
self.etaSignal.emit(max(0, eta_sec) if eta_sec >= 0 else -1)
|
||||||
|
# -------------------------------------
|
||||||
|
|
||||||
elif kind == "result":
|
elif kind == "result":
|
||||||
self.results.append(payload)
|
self.results.append(payload)
|
||||||
elif kind == "done":
|
elif kind == "done":
|
||||||
finished_workers += 1
|
finished_workers += 1
|
||||||
|
|
||||||
|
# Final metrics on completion
|
||||||
|
elapsed_total = max(1e-9, monotonic() - t0)
|
||||||
|
final_rate = total / elapsed_total
|
||||||
|
self.rateSignal.emit(final_rate)
|
||||||
|
self.etaSignal.emit(0)
|
||||||
|
|
||||||
self.resultsSignal.emit(self.results)
|
self.resultsSignal.emit(self.results)
|
||||||
|
|||||||
Reference in New Issue
Block a user