mirror of
https://github.com/rommapp/romm.git
synced 2026-04-23 06:54:40 +00:00
74 lines
2.4 KiB
Python
74 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Literal, NamedTuple
|
|
|
|
from utils.datetime import to_utc
|
|
|
|
SyncAction = Literal["upload", "download", "conflict", "no_op"]
|
|
|
|
|
|
class SyncComparisonResult(NamedTuple):
|
|
action: SyncAction
|
|
reason: str
|
|
|
|
|
|
def compare_save_state(
|
|
*,
|
|
client_hash: str | None,
|
|
client_updated_at: datetime,
|
|
server_hash: str | None,
|
|
server_updated_at: datetime,
|
|
device_last_synced_at: datetime | None,
|
|
) -> SyncComparisonResult:
|
|
"""Compare client and server save state to determine the sync action.
|
|
|
|
Returns a (action, reason) tuple where action is one of:
|
|
- upload: client save should be uploaded to server
|
|
- download: server save should be downloaded to client
|
|
- conflict: both sides changed, needs resolution
|
|
- no_op: saves are in sync
|
|
"""
|
|
client_ts = to_utc(client_updated_at)
|
|
server_ts = to_utc(server_updated_at)
|
|
|
|
# If hashes match, saves are identical
|
|
if client_hash and server_hash and client_hash == server_hash:
|
|
return SyncComparisonResult("no_op", "Content is identical")
|
|
|
|
# If we have a last sync timestamp, use it to determine which side changed
|
|
if device_last_synced_at:
|
|
synced_ts = to_utc(device_last_synced_at)
|
|
client_changed = client_ts > synced_ts
|
|
server_changed = server_ts > synced_ts
|
|
|
|
if client_changed and server_changed:
|
|
return SyncComparisonResult(
|
|
"conflict", "Both sides changed since last sync"
|
|
)
|
|
|
|
if client_changed:
|
|
return SyncComparisonResult("upload", "Client save is newer than last sync")
|
|
|
|
if server_changed:
|
|
return SyncComparisonResult(
|
|
"download", "Server save is newer than last sync"
|
|
)
|
|
|
|
return SyncComparisonResult("no_op", "No changes since last sync")
|
|
|
|
# No sync history: fall back to timestamp comparison
|
|
if client_ts > server_ts:
|
|
return SyncComparisonResult("upload", "Client save is newer (no sync history)")
|
|
|
|
if server_ts > client_ts:
|
|
return SyncComparisonResult(
|
|
"download", "Server save is newer (no sync history)"
|
|
)
|
|
|
|
# Same timestamp, different hashes (or missing hashes)
|
|
if client_hash != server_hash:
|
|
return SyncComparisonResult("conflict", "Same timestamp but different content")
|
|
|
|
return SyncComparisonResult("no_op", "Saves appear identical")
|