Skip to content

Commit 327b2f3

Browse files
committed
Restore end-to-end probe in shard routing readiness gates
The suite refactor (f571e4a) rewrote the standalone TestShardExactRouting_FullPipeline_Integration into a testify suite but dropped the end-to-end probe search from both readiness gates. The original fix (7b43d50) replaced structural-only checks with a probe that issues a routed search and verifies ShardExactMatch=true through the observer, catching cases where the shard map looks complete but shardExactCandidates still returns nil (connection Names not converged, needsCatUpdate still set, etc.). Both SetupSuite and TestFullPipelineRouting gates now check all three layers: structural completeness, needsCatUpdate flags, and an actual probe search confirming the full pipeline works. Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
1 parent 5316f54 commit 327b2f3

1 file changed

Lines changed: 56 additions & 10 deletions

File tree

opensearchtransport/shard_routing_integration_test.go

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,14 @@ func (s *ShardRoutingSuite) SetupSuite() {
181181
require.NoError(t, err)
182182
warmResp.Body.Close()
183183

184-
// --- Discover shard mappings for the new index ---
184+
// --- Discover shard mappings and verify end-to-end shard-exact routing ---
185185
// DiscoverNodes fetches /_cat/shards and populates the router's shard
186-
// catalog. Poll until:
186+
// catalog. Poll until all three conditions hold:
187187
// 1. The shard map for the test index has all shards populated
188-
// 2. No connections have lcNeedsCatUpdate set (which would cause
188+
// 2. No connections have needsCatUpdate set (which would cause
189189
// shardExactCandidates to filter them out)
190+
// 3. An actual probe search gets ShardExactMatch=true through the
191+
// observer, proving the full pipeline has converged
190192
routerPolicy, ok := s.transport.router.(Policy)
191193
require.True(t, ok, "router does not implement Policy")
192194
s.cache = findRouterCache(routerPolicy)
@@ -218,9 +220,26 @@ func (s *ShardRoutingSuite) SetupSuite() {
218220
}
219221
}
220222
}
221-
return true
223+
224+
// End-to-end probe: issue a routed search and verify ShardExactMatch.
225+
// Structural checks above can pass while shardExactCandidates still
226+
// returns nil (e.g. connection Names haven't converged into sorted
227+
// snapshots). The probe tests the full pipeline in a single assertion.
228+
s.obs.reset()
229+
probeURL := apiURL([]string{"/", s.index, "_search"}, map[string]string{"routing": "probe-canary"})
230+
probeReq, _ := http.NewRequestWithContext(s.ctx, http.MethodPost,
231+
probeURL,
232+
bytes.NewReader([]byte(`{"query":{"match_all":{}},"size":0}`)))
233+
probeReq.Header.Set("Content-Type", "application/json")
234+
probeResp, probeErr := s.transport.Perform(probeReq)
235+
if probeErr != nil {
236+
return false
237+
}
238+
probeResp.Body.Close()
239+
probeEvent := s.obs.lastEvent()
240+
return probeEvent != nil && probeEvent.ShardExactMatch
222241
}, 30*time.Second, 500*time.Millisecond,
223-
"shard catalog for index %q not ready after repeated DiscoverNodes", s.index)
242+
"shard-exact routing for index %q not working after repeated DiscoverNodes", s.index)
224243
s.obs.reset()
225244
}
226245

@@ -310,13 +329,26 @@ func (s *ShardRoutingSuite) TestDocIDAsDefaultRouting() {
310329
func (s *ShardRoutingSuite) TestFullPipelineRouting() {
311330
t := s.T()
312331

313-
// Refresh the shard catalog and clear any needsCatUpdate flags that
314-
// previous test methods (e.g., TestDocIDAsDefaultRouting) may have set
315-
// via transport errors.
332+
// Refresh the shard catalog and verify end-to-end shard-exact routing
333+
// works before running assertions. Previous test methods (e.g.,
334+
// TestDocIDAsDefaultRouting) may have set needsCatUpdate flags via
335+
// transport errors, and the resulting DiscoverNodes can replace the
336+
// shard map with incomplete data if shards are still settling. Poll
337+
// until an actual probe search gets ShardExactMatch=true through the
338+
// observer — this tests the full pipeline (shard map populated,
339+
// routing_num_shards fetched, connection names converged, no
340+
// connections filtered by needsCatUpdate) in a single assertion.
316341
require.Eventually(t, func() bool {
317342
if err := s.transport.DiscoverNodes(s.ctx); err != nil {
318343
return false
319344
}
345+
// Quick structural check: shard map must have all shards populated.
346+
slot := s.cache.getOrCreate(s.index)
347+
sm := slot.shardMap.Load()
348+
if sm == nil || sm.RoutingNumShards == 0 || len(sm.Shards) < s.numShards {
349+
return false
350+
}
351+
// Check no connections have needsCatUpdate set.
320352
s.transport.mu.RLock()
321353
pool := s.transport.mu.connectionPool
322354
s.transport.mu.RUnlock()
@@ -327,8 +359,22 @@ func (s *ShardRoutingSuite) TestFullPipelineRouting() {
327359
}
328360
}
329361
}
330-
return true
331-
}, 30*time.Second, 500*time.Millisecond, "connections still have needsCatUpdate after DiscoverNodes")
362+
// End-to-end probe: issue a routed search and verify ShardExactMatch.
363+
s.obs.reset()
364+
probeURL := apiURL([]string{"/", s.index, "_search"}, map[string]string{"routing": "probe-canary"})
365+
probeReq, _ := http.NewRequestWithContext(s.ctx, http.MethodPost,
366+
probeURL,
367+
bytes.NewReader([]byte(`{"query":{"match_all":{}},"size":0}`)))
368+
probeReq.Header.Set("Content-Type", "application/json")
369+
probeResp, probeErr := s.transport.Perform(probeReq)
370+
if probeErr != nil {
371+
return false
372+
}
373+
probeResp.Body.Close()
374+
probeEvent := s.obs.lastEvent()
375+
return probeEvent != nil && probeEvent.ShardExactMatch
376+
}, 30*time.Second, 500*time.Millisecond,
377+
"shard-exact routing for index %q not working after repeated DiscoverNodes", s.index)
332378
s.obs.reset()
333379

334380
type groundTruth struct {

0 commit comments

Comments
 (0)