Skip to content

fix: Log the cached-data evaluation warning only once per client - #520

Merged
kinyoklion merged 1 commit into
mainfrom
rlamb/log-cached-data-warning-once
Sep 15, 2026
Merged

kinyoklion merged 1 commit into
mainfrom
rlamb/log-cached-data-warning-once

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Sep 11, 2026 •

Copy link
Copy Markdown
Member

Summary

When data availability is CACHED, every evaluation and every all_flags_state() call logs a warning that the client is using last known values from the feature store. While the client stays in that state, this floods the log with one line per evaluation.

Each of these messages now logs once per client instance. LDClient and AsyncLDClient each hold two flags, one for the evaluation message and one for the all_flags_state() message. The messages say that they are logged once.

In LDClient, a threading.Lock guards the set of each flag. The lock is reached only inside the CACHED branch and only until the flag is set, so the normal evaluation path never touches it. Python has no lock-free atomic flag in the standard library. In AsyncLDClient, a plain boolean is enough because one event loop runs the client and no await separates the check and the set.

The sibling messages for the DEFAULTS case and the availability check itself are unchanged.


Note

Overview
Stops log flooding when the SDK serves flags from cached store data before the data source has reached REFRESHED. Warnings for variation / evaluation and for all_flags_state() now emit once per client instead of on every call, with copy noting "This message is logged once."

LDClient adds per-message boolean flags guarded by a threading.Lock (double-checked) so concurrent evaluations only log once. AsyncLDClient uses the same two flags without a lock, relying on single-threaded event-loop semantics between check and set.

Behavior when data is unavailable (non-CACHED) is unchanged. Tests simulate cached-but-uninitialized clients and assert a single warning per message type after repeated calls.

Reviewed by Cursor Bugbot for commit 08b2230. Bugbot is set up for automated code reviews on this repo. Configure here.

@kinyoklion
kinyoklion marked this pull request as ready for review September 15, 2026 17:48
@kinyoklion
kinyoklion requested a review from a team as a code owner September 15, 2026 17:48
@kinyoklion
kinyoklion merged commit 59ce998 into main Sep 15, 2026
25 of 27 checks passed
@kinyoklion
kinyoklion deleted the rlamb/log-cached-data-warning-once branch September 15, 2026 22:21
jsonbailey added a commit that referenced this pull request Sep 25, 2026
🤖 I have created a release *beep* *boop*
---


##
[9.18.0](9.17.0...9.18.0)
(2026-09-25)


### Features

* Add retry state for RETRY-spec backoff
([#522](#522))
([e734558](e734558))
* Drive repeating tasks from a delay source
([9abe8cb](9abe8cb))
* Retry indefinitely after a data source failure instead of stopping
permanently in FDv1
([e17e173](e17e173))
* warn that payload filtering has no effect with FDv2
([#518](#518))
([296311f](296311f))
* Warn when the SDK is used in a forked process without postfork
([#512](#512))
([75402e9](75402e9))


### Bug Fixes

* Add async modules to the readthedocs API reference
([#513](#513))
([f40d3b2](f40d3b2))
* Log the cached-data evaluation warning only once per client
([#520](#520))
([59ce998](59ce998))
* Read all items when a collection is empty
([#524](#524))
([1087147](1087147))
* Repeating task wait duration is no longer reduced by a slow callback
duration.
([9abe8cb](9abe8cb))
* Report a distinct User-Agent for the async client
([#516](#516))
([514c467](514c467))
* Warn and use the documented default for an invalid poll interval or
initial reconnect delay
([e17e173](e17e173))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> This PR **cuts release 9.18.0** by bumping the package version in
`pyproject.toml`, `ldclient/version.py`,
`.release-please-manifest.json`, and the provenance docs example, and by
adding the **9.18.0** section to `CHANGELOG.md`.
> 
> There is **no application code in the diff**—Release Please is
packaging work that was already merged. The new changelog highlights
**FDv1 data-source resilience** (indefinite retry after failures,
RETRY-spec backoff state, repeating tasks driven by a delay source, and
sane defaults/warnings for invalid poll/reconnect settings),
**operational warnings** (forked process without `postfork`, FDv2
payload filtering), and **fixes** (empty-collection reads,
repeating-task timing, one-time cached-data warnings, distinct async
`User-Agent`, ReadTheDocs async API docs).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
eef08a1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jason Bailey <jbailey@launchdarkly.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants