Conversation
Phase 5, the last of forward-porting concurrent multi-key support from v8 (#817). EnvironmentStatusRep gains sdkKeys and mobileKeys arrays of { key, value, expiry? }. Both are always present rather than omitted, so a consumer can iterate without a nil check: sdkKeys always holds at least the anchor, and mobileKeys is empty for a server-side-only environment. The scalar sdkKey and mobileKey fields stay, and designate which array entry owns the connection to LaunchDarkly and which mobile key is used where only one can be. They are deliberately not replaced by a flag on an entry: sdkKey predates concurrent keys and is what consumers read to identify an environment, v8 reports the same pair, and encoding the designation twice would let the two drift. Removes the singular expiringSdkKey. One field cannot describe an environment that accepts several keys with different expiries, and the soonest-expiring rule phase 3 carried was only there to keep the field and the metrics reading it deterministic while the rest of the port landed. Per-key expiry is in the arrays. The two metrics derived from that field move onto the arrays. The per-environment gauge becomes a count of the environment's expiring keys rather than a bit, because a bit cannot say how many, and it no longer means "a rotation is in progress": a key set can carry an expiring key as a steady state. The relay-wide gauge still counts environments, now those serving at least one key with an expiry. Descriptions reworded in the code and in docs/metrics.md. The expect query API needed no grammar change. Its array selectors were added for this, and the test asserting they were not yet evaluable is replaced with coverage of them resolving against real data.
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.
Summary
Phase 5, the last of forward-porting concurrent multi-key support from v8 (#817) to v9. Stacked on #897; GitHub retargets it to
feat/concurrent-keys-v9as the stack merges.EnvironmentStatusRepgainssdkKeysandmobileKeysarrays of{ key, value, expiry? }. Both are always present rather than omitted, so a consumer can iterate without a nil check:sdkKeysalways holds at least the anchor, andmobileKeysis empty for a server-side-only environment.The scalar fields stay
sdkKeyandmobileKeyremain, designating which array entry owns the connection to LaunchDarkly and which mobile key is used where only one can be. Asked and decided during review: they are deliberately not replaced by ananchor: trueflag on an entry.sdkKeypredates concurrent keys and is what consumers read to identify an environment, v8 reports the same pair of fields so one consumer can read both versions, and encoding the designation in two places would let them drift. The rationale is recorded on the field.expiringSdkKeyis removedOne field cannot describe an environment that accepts several keys with different expiries. The soonest-expiring-non-anchor rule phase 3 carried was only there to keep that field, and the metrics reading it, deterministic while the rest of the port landed. Per-key expiry now lives in the arrays.
Metrics re-based
The two instruments #876 derived from
ExpiringSDKKey != ""move onto the arrays:launchdarkly.relay.environment.expiring_keys, a count of that environment's SDK keys carrying an expiry. A bit cannot say how many, and it no longer means "a rotation is in progress" — a key set can hold an expiring key as a steady state.launchdarkly.relay.environment.expiring_key.count, still counting environments, now those serving at least one key with an expiry.Descriptions reworded in
status_measures.goanddocs/metrics.md. The existing metrics tests caught a name collision when the per-environment gauge was first renamed to.expiring_key.count, which is why the two now have clearly distinct names.The
expectAPI was already readyNo grammar change was needed.
internal/api/status_query_test.gocarried a test named "array fields the schema does not have yet", whose comment said the path grammar supports array selectors specifically so they would survive the concurrent-keys change. That test now describes the past, so it is split: addressingsdkKeysat the wrong level still returns 422, and there is new positive coverage forsdkKeys[key=...]andsdkKeys[0]resolving against real data, with a selector that matches nothing returning 412 rather than 422.Documentation
docs/endpoints.mddocumentedexpiringSdkKey=...as a 412 example, which would now be a 422, and its three status-document examples showed only the scalar fields. All updated, plus a short paragraph on why an environment reports several keys and what the scalar fields designate.Part of SDK-3203, under epic SDK-3188.
Note
Overview
The
/statushealth JSON now reports each environment’s full accepted credential set via always-presentsdkKeysandmobileKeysarrays (key, obscuredvalue, optionalexpiry). ScalarsdkKey/mobileKeystay as the anchor and primary mobile key designators.expiringSdkKeyis removed; rotation and overlap are expressed per entry insdkKeys. Status building dropssoonestExpiringSDKKeyin favor of populating those arrays from the accepted key set.Metrics: per-environment
launchdarkly.relay.environment.expiring_keysis a count of SDK keys with an expiry (replacing the booleanexpiring_keygauge); relay-wideexpiring_key.countstill counts environments with any expiring SDK key.expectprobes can assert onsdkKeys[...](412 when a selector matches no key); docs and tests are updated. Integration tests useexpiringSDKKeyIn()overSDKKeysinstead of the old field.Reviewed by Cursor Bugbot for commit 0dadeb2. Bugbot is set up for automated code reviews on this repo. Configure here.