mirror of
https://github.com/kuhyx/diet-guard.git
synced 2026-11-10 20:27:11 +01:00
Refresh the phone weight from run_sync, where the PC's event-driven sync actually passes
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2ea5dcac52
commit
8e0a4bddab
@ -2,7 +2,7 @@ name: diet_guard_app
|
||||
description: "Companion phone app for diet_guard: log meals on the go."
|
||||
publish_to: 'none'
|
||||
|
||||
version: 1.0.84+1
|
||||
version: 1.0.85+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.12.2
|
||||
|
||||
@ -27,10 +27,6 @@ _LAZY_ATTRS = {
|
||||
"run_sync": ("diet_guard._sync", "run_sync"),
|
||||
"SyncError": ("diet_guard._sync", "SyncError"),
|
||||
"RemoteSyncError": ("crdt_sync", "RemoteSyncError"),
|
||||
"refresh_weight_from_phone": (
|
||||
"diet_guard._phone_weight",
|
||||
"refresh_weight_from_phone",
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +78,4 @@ def cmd_sync(emit: Callable[[str], None]) -> int:
|
||||
return 1
|
||||
total_entries = sum(len(entries) for entries in merged.values())
|
||||
emit(f"synced: {total_entries} entries across {len(merged)} day(s).")
|
||||
# After the merge, never before: the local record is then already the
|
||||
# merged winner, so refreshing its ``t`` re-asserts nothing stale.
|
||||
module.refresh_weight_from_phone(emit)
|
||||
return 0
|
||||
|
||||
@ -37,6 +37,7 @@ from diet_guard._constants import (
|
||||
)
|
||||
from diet_guard._device import device_identity
|
||||
from diet_guard._foodbank_rebuild import rebuild_food_bank
|
||||
from diet_guard._phone_weight import refresh_weight_from_phone
|
||||
from diet_guard._state_sync import (
|
||||
read_raw_log,
|
||||
resign_entry,
|
||||
@ -202,6 +203,11 @@ def run_sync() -> DayLog:
|
||||
message="diet_guard sync: revision",
|
||||
)
|
||||
state_store.save(SyncState(pushed_rev=revision, peer_revs=seen_revs))
|
||||
# Last, after the budget merge above: the local record is then already
|
||||
# the merged winner, so the refreshed ``t`` re-asserts nothing stale.
|
||||
# Here rather than in the ``sync`` subcommand because on the PC a full
|
||||
# tick runs from ``publish_after_log``, never from that command.
|
||||
refresh_weight_from_phone(lambda line: _logger.info("%s", line))
|
||||
return resigned
|
||||
|
||||
|
||||
|
||||
@ -162,6 +162,11 @@ def _isolate_state(tmp_path: Path) -> Iterator[None]:
|
||||
"diet_guard._sync_client.CONFIG_FILE",
|
||||
tmp_path / "nonexistent-firebase.json",
|
||||
),
|
||||
# Every full tick ends by reading the phone's weigh-in through
|
||||
# `wake_alarm._weight`, which is installed here and reads the live
|
||||
# Firebase database. `test_sync_budget` asserts the call; nothing
|
||||
# else may pay for it.
|
||||
patch("diet_guard._sync.refresh_weight_from_phone", return_value=None),
|
||||
# Logging a meal now publishes immediately (`_sync_events`), so every
|
||||
# test that logs one would otherwise open a real connection through a
|
||||
# path that has nothing to do with what it is asserting. Patched at the
|
||||
|
||||
@ -19,23 +19,9 @@ class TestCmdSync:
|
||||
"2026-06-21": [{"id": "c"}],
|
||||
}
|
||||
lines: list[str] = []
|
||||
with (
|
||||
patch.object(_cli_sync, "run_sync", return_value=merged),
|
||||
patch.object(_cli_sync, "refresh_weight_from_phone") as refresh,
|
||||
):
|
||||
with patch.object(_cli_sync, "run_sync", return_value=merged):
|
||||
assert _cli_sync.cmd_sync(lines.append) == 0
|
||||
assert lines == ["synced: 3 entries across 2 day(s)."]
|
||||
# The phone's weigh-in is applied after the merge, through the same
|
||||
# sink, so its one line lands under the sync summary.
|
||||
refresh.assert_called_once_with(lines.append)
|
||||
|
||||
def test_a_failed_sync_does_not_touch_the_weight(self) -> None:
|
||||
with (
|
||||
patch.object(_cli_sync, "run_sync", side_effect=SyncError("no token")),
|
||||
patch.object(_cli_sync, "refresh_weight_from_phone") as refresh,
|
||||
):
|
||||
assert _cli_sync.cmd_sync(lambda _line: None) == 1
|
||||
refresh.assert_not_called()
|
||||
|
||||
def test_reports_sync_error_as_not_configured(self) -> None:
|
||||
lines: list[str] = []
|
||||
|
||||
@ -38,6 +38,24 @@ class TestSyncBudget:
|
||||
pushed_paths = {call.args[0] for call in client.put_file_text.call_args_list}
|
||||
assert f"diet-guard-sync/devices/{device_id()}/budget.json" in pushed_paths
|
||||
|
||||
def test_refreshes_the_weight_from_the_phone_after_the_merge(self) -> None:
|
||||
"""The hook runs last, on every successful tick, into the sync log."""
|
||||
_write_token()
|
||||
write_budget(2000)
|
||||
client = _mock_client(devices=())
|
||||
with (
|
||||
patch.object(_sync_client, "GitHubSyncClient", return_value=client),
|
||||
patch.object(_sync, "refresh_weight_from_phone") as refresh,
|
||||
):
|
||||
_sync.run_sync()
|
||||
refresh.assert_called_once()
|
||||
(sink,) = refresh.call_args.args
|
||||
with patch.object(_sync._logger, "info") as info:
|
||||
sink("weight: 72.4 kg from the phone (2026-09-17).")
|
||||
info.assert_called_once_with(
|
||||
"%s", "weight: 72.4 kg from the phone (2026-09-17)."
|
||||
)
|
||||
|
||||
def test_nothing_pushed_when_no_budget_ever_set(self) -> None:
|
||||
"""An uninitialized device contributes nothing -- no push, no crash."""
|
||||
_write_token()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user