From 5d642e6211a0711ad014ce640e5a172c06831f7d Mon Sep 17 00:00:00 2001 From: moe-berri Date: Wed, 30 Sep 2026 13:12:49 -0700 Subject: [PATCH] perf(roi): skip writes for unchanged cached identities --- litellm/proxy/roi_calculator/sync.py | 13 +++++++++++-- tests/unit/proxy/roi_calculator/test_sync.py | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/litellm/proxy/roi_calculator/sync.py b/litellm/proxy/roi_calculator/sync.py index 6f00bf770ae..65a2cb38a17 100644 --- a/litellm/proxy/roi_calculator/sync.py +++ b/litellm/proxy/roi_calculator/sync.py @@ -313,9 +313,16 @@ def _processed_records(processed: tuple[_ProcessedPull, ...]) -> Mapping[int, RO return MappingProxyType({item.position: item.record for item in processed}) -async def _cache_estimated_pull(repository: _ReportRepository, key: str | None, record: ROIPullRecord) -> None: +async def _cache_estimated_pull( + repository: _ReportRepository, key: str | None, record: ROIPullRecord, previous: ROIPullRecord | None = None +) -> None: if key is None or record["estimate"]["status"] != "estimated": return + if previous is not None and (record.get("profile_email"), record["emails"]) == ( + previous.get("profile_email"), + previous["emails"], + ): + return await repository.set_param( "roi_calculator_pull_" + key, _JSON_OBJECT_ADAPTER.validate_python(TypeAdapter(ROIPullRecord).dump_python(record, mode="json")), @@ -506,7 +513,9 @@ class SyncManager: } ) ) - await _cache_estimated_pull(repository, key, cached_record) + await _cache_estimated_pull( + repository, key, cached_record, cached_pull if saved is not None else None + ) self._update_estimate_progress(cached_record["estimate"]) return _ProcessedPull(index, cached_record) try: diff --git a/tests/unit/proxy/roi_calculator/test_sync.py b/tests/unit/proxy/roi_calculator/test_sync.py index 9cbcaca4338..f58bc396d94 100644 --- a/tests/unit/proxy/roi_calculator/test_sync.py +++ b/tests/unit/proxy/roi_calculator/test_sync.py @@ -75,12 +75,15 @@ class _Parameter: class _ReportRepository: def __init__(self) -> None: self.values: Mapping[str, object] = MappingProxyType({}) + self.pull_writes: int = 0 async def get_param(self, param_name: str) -> _Parameter | None: value: Final = self.values.get(param_name) return _Parameter(value) if value is not None else None async def set_param(self, param_name: str, param_value: object) -> object: + if param_name.startswith("roi_calculator_pull_"): + self.pull_writes += 1 _assert_json_round_trip(param_value) self.values = MappingProxyType({**self.values, param_name: param_value}) return self.values[param_name] @@ -589,6 +592,7 @@ async def test_reused_profile_preserves_email_only_when_lookup_fails(profile_sta subsequent: Final = TypeAdapter(ROIReport).validate_python(repository.values["roi_calculator_report"]) assert subsequent["pulls"][0]["profile_email"] == expected assert subsequent["pulls"][0]["emails"] == ((expected,) if expected else ()) + assert repository.pull_writes == (2 if profile_status == 200 else 1) @pytest.mark.asyncio