perf: Deduplicate concurrent polling requests with a flight group - #798
Draft
keelerm84 wants to merge 3 commits into
Draft
perf: Deduplicate concurrent polling requests with a flight group#798keelerm84 wants to merge 3 commits into
keelerm84 wants to merge 3 commits into
Conversation
The streaming endpoints have always collapsed concurrent replay builds through a singleflight group, but every polling request snapshotted and serialized the store on its own. The two server-side full-payload polling endpoints (GET /sdk/poll and GET /sdk/flags) now share one payload build per environment through a flight group exposed by the EnvContext, keyed by the FDv2 basis where the payload depends on it. The per-context evaluation endpoints and the per-key PHP endpoints are unchanged: their results rarely collide, so there is little duplicate work to share. The store and serialize spans belong to the one request that executes the build; every request records relay.singleflight.shared on its request span so a trace without those child spans is explainable.
…time A request that received its payload from a flight another request was executing now records how long it waited as relay.singleflight.wait_ms on its request span. The executing request carries no wait attribute -- it did not wait, and its time is visible as the store and serialize child spans -- so the attribute's presence alone identifies a request that waited, and slow waits are queryable. Both polling handlers now resolve their flights through a shared runPollingFlight helper that owns the Do call and both span annotations. That indirection also breaks the taint chain behind the gosec G705 false positive on writeCacheableJSONResponse, so its nolint directive is removed.
The streaming repositories' replay flight groups now record the same information the polling endpoints do: relay.singleflight.shared on the subscribing request's span, plus relay.singleflight.wait_ms when a replay waited on a flight another subscriber was already executing. The annotation logic moves into tracing.SingleflightDo so both sides record identical information by construction. The flags-only repository never implemented ReplayWithContext, so it had no request context to annotate; it now advertises context support the same way the main server-side repository does.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The streaming endpoints have always collapsed concurrent replay builds
through a singleflight group, but every polling request snapshotted and
serialized the store on its own. The two server-side full-payload
polling endpoints (GET /sdk/poll and GET /sdk/flags) now share one
payload build per environment through a flight group exposed by the
EnvContext, keyed by the FDv2 basis where the payload depends on it.
The per-context evaluation endpoints and the per-key PHP endpoints are
unchanged: their results rarely collide, so there is little duplicate
work to share.
The store and serialize spans belong to the one request that executes
the build; every request records relay.singleflight.shared on its
request span so a trace without those child spans is explainable.