fix: avoid division by zero when logging watch load rate (#4289)

Co-authored-by: snowyukitty <270071858+snowyukitty@users.noreply.github.com>
This commit is contained in:
snowyukitty
2026-08-16 14:26:39 +02:00
committed by GitHub
co-authored by snowyukitty
parent 3e3300896f
commit 21f19b239a
2 changed files with 30 additions and 6 deletions
@@ -285,7 +285,7 @@ def load_all_watches(datastore_path, rehydrate_entity_func):
Returns:
Dictionary of uuid -> Watch object
"""
start_time = time.time()
start_time = time.perf_counter()
logger.info("Loading watches from individual watch.json files...")
watching = {}
@@ -294,9 +294,9 @@ def load_all_watches(datastore_path, rehydrate_entity_func):
return watching
# Find all watch.json files using glob (faster than manual directory traversal)
glob_start = time.time()
glob_start = time.perf_counter()
watch_files = glob.glob(os.path.join(datastore_path, "*", "watch.json"))
glob_time = time.time() - glob_start
glob_time = time.perf_counter() - glob_start
total = len(watch_files)
logger.debug(f"Found {total} watch.json files in {glob_time:.3f}s")
@@ -318,16 +318,17 @@ def load_all_watches(datastore_path, rehydrate_entity_func):
# load_watch_from_file already logged the specific error
failed += 1
elapsed = time.time() - start_time
elapsed = time.perf_counter() - start_time
load_rate = loaded / elapsed if elapsed > 0 else 0
if failed > 0:
logger.critical(
f"LOAD COMPLETE: {loaded} watches loaded successfully, "
f"{failed} watches FAILED to load (corrupted or invalid) "
f"in {elapsed:.2f}s ({loaded/elapsed:.0f} watches/sec)"
f"in {elapsed:.2f}s ({load_rate:.0f} watches/sec)"
)
else:
logger.info(f"Loaded {loaded} watches from disk in {elapsed:.2f}s ({loaded/elapsed:.0f} watches/sec)")
logger.info(f"Loaded {loaded} watches from disk in {elapsed:.2f}s ({load_rate:.0f} watches/sec)")
return watching
@@ -0,0 +1,23 @@
import tempfile
from types import SimpleNamespace
from unittest.mock import Mock, patch
from changedetectionio.store import file_saving_datastore
def test_load_all_watches_handles_zero_elapsed_time():
frozen_clock = SimpleNamespace(
perf_counter=lambda: 1.0,
time=lambda: 1.0,
)
rehydrate_entity = Mock()
with tempfile.TemporaryDirectory() as datastore_path:
with patch.object(file_saving_datastore, 'time', frozen_clock):
watches = file_saving_datastore.load_all_watches(
datastore_path,
rehydrate_entity_func=rehydrate_entity,
)
assert watches == {}
rehydrate_entity.assert_not_called()