Skip to content

fix: Reuse an in-flight big segment status poll instead of querying twice - #460

Merged
jsonbailey merged 1 commit into
mainfrom
jb/fix/bigsegments-double-startup-poll
Oct 6, 2026
Merged

jsonbailey merged 1 commit into
mainfrom
jb/fix/bigsegments-double-startup-poll

Conversation

@jsonbailey

@jsonbailey jsonbailey commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

BEGIN_COMMIT_OVERRIDE
fix: Reuse an in-flight big segment status poll instead of always querying twice
END_COMMIT_OVERRIDE

The status getter polled the store whenever no status was cached yet, so a request arriving while the startup poll was still in flight started a second metadata query of its own. get_context_membership had the same inline poll, and now routes through get_status so the cache check lives in one place.

Status requests now wait on the same Mutex the poll task holds and re-check the cached status after acquiring it, so a poll that is already running satisfies them instead of being duplicated. Observers are notified outside the lock — a listener calling back into the manager would otherwise deadlock on Ruby's non-reentrant mutex.

The poll schedule is unchanged — the first poll still fires immediately, and the RepeatingTask timing arguments are untouched.

Matching change in Python: launchdarkly/python-server-sdk#535

Test evidence

Two regression specs added in spec/impl/big_segments_spec.rb, one per entry point (the status getter and get_context_membership). The store signals when it has entered a metadata query and then stays there, so the request is forced to overlap an in-flight poll rather than relying on timing; each asserts exactly one metadata query. Both fail with expected: 1, got: 2 against the code on main.

Unit suite: 1108 examples, 0 failures. RuboCop: 188 files, no offenses. v2 contract tests: 4703 total, 15 skipped, all passed — including all seven big segments/status polling tests.

Tracked Internally: SDK-3212


Note

Overview
Fixes duplicate big segment store metadata queries when a status or membership read happens while the startup (or in-flight) poll has not finished yet.

BigSegmentStoreManager now serializes status fetches with a Mutex: callers double-check @last_status after acquiring the lock and only run one store query if still empty. get_context_membership no longer triggers its own inline poll and always goes through get_status. Store querying is split into query_store_status (cache only, under the lock); update_status / observer notification runs outside the lock to avoid deadlock if a listener re-enters the manager.

Regression specs force overlap between the background poll and a status or membership request and assert exactly one get_metadata call.

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

@jsonbailey
jsonbailey marked this pull request as ready for review October 5, 2026 14:51
@jsonbailey
jsonbailey requested a review from a team as a code owner October 5, 2026 14:51
@jsonbailey
jsonbailey marked this pull request as draft October 5, 2026 15:05
…wice

The status getter polled the store whenever no status was cached yet, so
a request arriving while the startup poll was still in flight started a
second metadata query of its own.

Status requests now wait on the same lock the poll task holds and
re-check the cached status after acquiring it, so a poll that is already
running satisfies them. The poll schedule is unchanged: the first poll
still fires immediately. Observers are notified outside the lock,
because a listener that calls back into the manager would otherwise
deadlock on a non-reentrant mutex.
@jsonbailey
jsonbailey force-pushed the jb/fix/bigsegments-double-startup-poll branch from f2ab464 to 012431d Compare October 5, 2026 22:34
@jsonbailey jsonbailey changed the title fix: Delay the first big segment status poll by one interval fix: Reuse an in-flight big segment status poll instead of querying twice Oct 5, 2026
@jsonbailey
jsonbailey marked this pull request as ready for review October 6, 2026 12:23
Comment thread lib/ldclient-rb/impl/big_segments.rb
@jsonbailey
jsonbailey merged commit 96cca28 into main Oct 6, 2026
13 checks passed
@jsonbailey
jsonbailey deleted the jb/fix/bigsegments-double-startup-poll branch October 6, 2026 14:36
jsonbailey pushed a commit that referenced this pull request Oct 6, 2026
🤖 I have created a release *beep* *boop*
---


##
[8.18.1](8.18.0...8.18.1)
(2026-10-06)


### Bug Fixes

* Pass connect_timeout to the streaming SSE client
([#458](#458))
([f4a07af](f4a07af))
* Prevent close from hanging after a persistent store read fails
([91b7c9c](91b7c9c))
* Prevent flags from falling back to defaults when a deleted item has no
key
([afb9f3d](afb9f3d))
* Prevent flags from falling back to defaults when Consul holds one item
([8891226](8891226))
* Prevent the store availability poller from outliving the client
([91b7c9c](91b7c9c))
* Publish the data source status before releasing ready waiters
([#431](#431))
([0e224b9](0e224b9))
* Reuse an in-flight big segment status poll instead of querying twice
([#460](#460))
([96cca28](96cca28))

---
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 **Release Please** PR cuts **8.18.1** by bumping
`LaunchDarkly::VERSION`, `.release-please-manifest.json`, and the
provenance example in `PROVENANCE.md`.
> 
> It adds a **8.18.1** section to `CHANGELOG.md` documenting bug fixes
already landed on main: streaming **connect_timeout** wiring,
persistent-store **close** and availability-poller lifecycle,
flag-evaluation fallbacks with deleted/Consul store edge cases, **data
source status** ordering before ready waiters, and deduplicating **big
segment** status polls. No SDK implementation files change in this
diff—only release bookkeeping.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
46d0611. 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>
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