@@ -181,12 +181,14 @@ private function doTestCase(stdClass $test, string $schemaVersion, ?array $runOn
181181 $ this ->checkRunOnRequirements ($ test ->runOnRequirements );
182182 }
183183
184- if (isset ($ initialData )) {
185- $ this ->prepareInitialData ($ initialData );
186- }
184+ assertIsArray ($ test ->operations );
187185
188186 $ context = $ this ->createContext ();
189187
188+ if (isset ($ initialData )) {
189+ $ this ->prepareInitialData ($ initialData , $ context , $ this ->isAdvanceClusterTimeNeeded ($ test ->operations ));
190+ }
191+
190192 /* If an EntityMap observer has been configured, assign the Context's
191193 * EntityMap to a class property so it can later be accessed from run(),
192194 * irrespective of whether this test succeeds or fails. */
@@ -198,7 +200,6 @@ private function doTestCase(stdClass $test, string $schemaVersion, ?array $runOn
198200 $ context ->createEntities ($ createEntities );
199201 }
200202
201- assertIsArray ($ test ->operations );
202203 $ this ->preventStaleDbVersionError ($ test ->operations , $ context );
203204
204205 $ context ->startEventObservers ();
@@ -421,17 +422,48 @@ private function assertOutcome(array $outcome): void
421422 }
422423 }
423424
424- private function prepareInitialData (array $ initialData ): void
425+ private function prepareInitialData (array $ initialData, Context $ context , bool $ isAdvanceClusterTimeNeeded ): void
425426 {
426427 assertNotEmpty ($ initialData );
427428 assertContainsOnly ('object ' , $ initialData );
428429
430+ /* In order to avoid MigrationConflict errors on sharded clusters, use the cluster time obtained from creating
431+ * collections to advance session entities. This is necessary because initialData uses an internal MongoClient,
432+ * which will not share/gossip its cluster time via the test entities. */
433+ if ($ isAdvanceClusterTimeNeeded ) {
434+ $ session = $ this ->internalClient ->startSession ();
435+ }
436+
429437 foreach ($ initialData as $ data ) {
430438 $ collectionData = new CollectionData ($ data );
431- $ collectionData ->prepareInitialData ($ this ->internalClient );
439+ $ collectionData ->prepareInitialData ($ this ->internalClient , $ session ?? null );
440+ }
441+
442+ if (isset ($ session )) {
443+ $ context ->setAdvanceClusterTime ($ session ->getClusterTime ());
432444 }
433445 }
434446
447+ /**
448+ * Work around potential MigrationConflict errors on sharded clusters.
449+ */
450+ private function isAdvanceClusterTimeNeeded (array $ operations ): bool
451+ {
452+ if (! in_array ($ this ->getPrimaryServer ()->getType (), [Server::TYPE_MONGOS , Server::TYPE_LOAD_BALANCER ], true )) {
453+ return false ;
454+ }
455+
456+ foreach ($ operations as $ operation ) {
457+ switch ($ operation ->name ) {
458+ case 'startTransaction ' :
459+ case 'withTransaction ' :
460+ return true ;
461+ }
462+ }
463+
464+ return false ;
465+ }
466+
435467 /**
436468 * Work around potential error executing distinct on sharded clusters.
437469 *
0 commit comments