feat: improve key alignment efficiency

This commit is contained in:
Mike A.
2025-09-24 22:57:13 +02:00
parent 054fe9f78e
commit 3cc33f6bb0
2 changed files with 16 additions and 11 deletions

View File

@@ -61,9 +61,11 @@ class RollingKeyPairSource(ABC):
@abstractmethod @abstractmethod
def update_alignment(self, dt: datetime, index: int) -> None: def update_alignment(self, dt: datetime, index: int) -> None:
""" """
Update alignment of the accessory. Update alignment of the accessory based on a key index that was observed at a specific time.
Alignment can be updated based on a LocationReport that was observed at a specific index. Implementations of this method should consider that this method may be called
multiple times, sometimes with seemingly conflicting data: the same index may be
observed at different times, or multiple indices may be observed at the same time.
""" """
raise NotImplementedError raise NotImplementedError
@@ -222,8 +224,13 @@ class FindMyAccessory(RollingKeyPairSource, util.abc.Serializable[FindMyAccessor
@override @override
def update_alignment(self, dt: datetime, index: int) -> None: def update_alignment(self, dt: datetime, index: int) -> None:
if dt < self._alignment_date: if dt < self._alignment_date or index < self._alignment_index:
# we only care about the most recent report # We only care about the most recent report and index.
# Multiple calls to this method may be made with
# possibly conflicting data, so we just ignore
# anything that seems to go backwards in time or index.
# Saving the newest data is at least likely to be stable
# over multiple fetches.
return return
logger.info("Updating alignment based on report observed at index %i", index) logger.info("Updating alignment based on report observed at index %i", index)

View File

@@ -431,7 +431,7 @@ class LocationReportsFetcher:
# state variables # state variables
cur_keys_primary: set[str] = set() cur_keys_primary: set[str] = set()
cur_keys_secondary: set[str] = set() cur_keys_secondary: set[str] = set()
cur_index = accessory.get_min_index(start_date) cur_index = accessory.get_max_index(start_date)
ret: set[LocationReport] = set() ret: set[LocationReport] = set()
async def _fetch() -> set[LocationReport]: async def _fetch() -> set[LocationReport]:
@@ -446,17 +446,15 @@ class LocationReportsFetcher:
report.decrypt(key) report.decrypt(key)
# update alignment data on every report # update alignment data on every report
# if a key maps to multiple indices, only feed it the maximum index, for i in key_to_ind[key]:
# since apple only returns the latest reports per request. accessory.update_alignment(report.timestamp, i)
# This makes the value more likely to be stable.
accessory.update_alignment(report.timestamp, max(key_to_ind[key]))
cur_keys_primary.clear() cur_keys_primary.clear()
cur_keys_secondary.clear() cur_keys_secondary.clear()
return set(new_reports) return set(new_reports)
while cur_index <= accessory.get_max_index(end_date): while cur_index >= accessory.get_min_index(end_date):
key_batch = accessory.keys_at(cur_index) key_batch = accessory.keys_at(cur_index)
# split into primary and secondary keys # split into primary and secondary keys
@@ -483,7 +481,7 @@ class LocationReportsFetcher:
cur_keys_primary |= new_keys_primary cur_keys_primary |= new_keys_primary
cur_keys_secondary |= new_keys_secondary cur_keys_secondary |= new_keys_secondary
cur_index += 1 cur_index -= 1
if cur_keys_primary or cur_keys_secondary: if cur_keys_primary or cur_keys_secondary:
# fetch remaining keys # fetch remaining keys