fix(chainlink): deterministic ordering for /nodes pagination#22459
Open
ozpool wants to merge 2 commits into
Open
fix(chainlink): deterministic ordering for /nodes pagination#22459ozpool wants to merge 2 commits into
ozpool wants to merge 2 commits into
Conversation
Fixes smartcontractkit#18263. The Nodes tab reorders on every render because the aggregated NodeStatuses() slice inherits whatever per-relayer order the underlying chain returned, which is map-iteration order for several implementations. With more than 100 nodes (now the case for CCIP) the same chain's nodes flip across pages between refreshes, making the page unusable for finding a specific node. The outer relayer keys are already sorted by (Network, ChainID), so the missing layer is a stable sort of the aggregated NodeStatus slice by (ChainID, Name). slices.SortStableFunc preserves input order on equal keys so dev-fixture duplicates or multi-relayer dummy chains stay reproducible too. Extract the sort to a small `sortNodeStatuses` helper and add unit coverage that asserts both the ordering (shuffled within a chain, grouped across chains, lexicographic chain ids) and the stability property. The helper is package-private and the test lives in a new internal `_test.go` file so the full loop.Relayer interface does not need to be stubbed just to verify the sort.
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.
Problem
The Nodes tab in the operator UI reorders on every render. With more than 100 nodes configured (now routine for CCIP), the same chain's nodes flip across pages between refreshes, making the page unusable for locating a specific node by sight.
The root cause is in
(*CoreRelayerChainInteroperators).NodeStatuses: per-relayer node ordering is whatever the underlying chain implementation returns, and several relayer implementations build the list from map iteration. The outer relayer keys are already sorted by(Network, ChainID), but the aggregated[]types.NodeStatusslice has no stable order, so pagination is non-deterministic.Fix
Extract a package-private
sortNodeStatuseshelper and apply it inNodeStatusesright after aggregation, before the offset/size slicing happens. The sort key is(ChainID, Name)usingslices.SortStableFuncso equal keys (e.g. dev fixtures or multi-relayer dummy chains) keep their input order and the result is fully reproducible.Test
relayer_chain_interoperators_internal_test.gocovers:Name.The test lives in an internal
_test.goso it can exercise the helper without standing up the fullloop.Relayerinterface.Fixes #18263