-
Type:
Task
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Change streams
-
None
-
DB Integration & Observability
-
Fully Compatible
-
v9.0
-
QE 2026-09-28
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Fix flaky test `jstests/sharding/query/change_streams/change_stream_read_preference.js`.
The test was previously flaky and could non-deterministically fail with an error message such as follows ([example failed patch run](https://parsley.corp.mongodb.com/test/mongodb_mongo_master_enterprise_rhel_8_64_bit_dynamic_classic_engine_burn_in:sharding_gen_enterprise_rhel_8_64_bit_dynamic_classic_engine_0_patch_94c253e337508c29d836607582fdac497aada7ec_6ab5014f17a7e50007bab825_26_09_24_10_54_24/0/b77c70d25cc9fe87f6f3bb85c47c0ac1?bookmarks=0%2C32806&selectedLineRange=L32750&shareLine=32750)):
```
[js_test:change_stream_read_preference] [jsTest] ✘ change stream and update lookup read preference > targets a secondary with readPreference 'secondary'
[js_test:change_stream_read_preference] [jsTest] expected 2 to equal 1
[js_test:change_stream_read_preference] [jsTest] + expected - actual
[js_test:change_stream_read_preference] [jsTest]
[js_test:change_stream_read_preference] [jsTest] -2
[js_test:change_stream_read_preference] [jsTest] +1
[js_test:change_stream_read_preference] [jsTest] : ip-10-128-182-147.ec2.internal:22146 should read locally. indexOpsDelta:
[js_test:change_stream_read_preference] [jsTest] _getErrorWithCode@src/mongo/shell/utils.js:32:13
[js_test:change_stream_read_preference] [jsTest] doassert@src/mongo/shell/assert.js:48:14
[js_test:change_stream_read_preference] [jsTest] _doassert@src/mongo/shell/assert.js:182:13
[js_test:change_stream_read_preference] [jsTest] assert.eq@src/mongo/shell/assert.js:310:14
[js_test:change_stream_read_preference] [jsTest] runReadPreferenceTest/<@jstests/sharding/query/change_streams/change_stream_read_preference.js:81:32
[js_test:change_stream_read_preference] [jsTest] withChangeStreamTest@/data/mci/37ad89971eaf39fbffca8d47d9d3cf6c/src/jstests/libs/query/change_stream_util.js:946:11
[js_test:change_stream_read_preference] [jsTest] runReadPreferenceTest@jstests/sharding/query/change_streams/change_stream_read_preference.js:33:29
[js_test:change_stream_read_preference] [jsTest] @jstests/sharding/query/change_streams/change_stream_read_preference.js:174:30
[js_test:change_stream_read_preference] [jsTest] run@/data/mci/37ad89971eaf39fbffca8d47d9d3cf6c/src/jstests/libs/mochalite.js:375:31
```
The failing assertion is [this](https://github.com/10gen/mongo/blob/fc72883d242187c1bbbfdf135b973ba2efa37b3e/jstests/sharding/query/change_streams/change_stream_read_preference.js#L81-L85):
```
assert.eq(
observation.indexOpsDelta["_id_"],
1,
`${node.host} should read locally. indexOpsDelta: ${toJsonForLog(observation.indexOpsDelta)}`,
);
```
The optimized update-lookup does exactly one lookup. however the `$indexStats` `id` access counter on a secondary can be incremented twice during the measurement window.
`indexAccessOpsByName()` (in [jstests/libs/index_stats_utils.js](https://github.com/10gen/mongo/blob/fc72883d242187c1bbbfdf135b973ba2efa37b3e/jstests/libs/index_stats_utils.js#L86)) reads `$indexStats.accesses.ops`. That counter is global to the node and counts every operation that uses the `id` index, including but not limited to the change stream's lookup.
The change stream's optimized update-lookup records exactly one `id` access. But there are additional counter increases on the secondary:
The test itself writes `coll.update({id:...});` (lines 40, 41) and `coll.deleteMany({});` (line 158). When those oplog entries are applied on the secondary, they are simple `_id` equality writes and go through the Express/idhack path, which does an `_id` index seek and records `id` usage.
Those writes use the default write concern (`
`). Only the inserts use `
{w: "majority"}` (lines 152–153). So the secondary can apply these operations after the test establishes its `$indexStats` baseline.
This change fixes the test to wait for these operations to be fully applied on the secondaries before establishing the index stats baseline.