Skip to content

Commit 2f48c5d

Browse files
committed
Fixed bug in EntityTrackerSubscriber when there are more than one bulk requests
1 parent 033ee1a commit 2f48c5d

File tree

3 files changed

+61
-11
lines changed

3 files changed

+61
-11
lines changed

src/Manager/ConnectionManager.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -216,16 +216,16 @@ public function commit(bool $forceRefresh = true)
216216

217217
$this->bulkQueries = [];
218218

219+
if ($this->eventDispatcher) {
220+
$this->eventDispatcher->dispatch(new PostCommitEvent($response, $this), Events::POST_COMMIT);
221+
}
222+
219223
if ($response['errors']) {
220224
$errorCount = $this->logBulkRequestErrors($response['items']);
221225
$e = new BulkRequestException(\sprintf('Bulk request failed with %s error(s)', $errorCount));
222226
$e->setBulkResponseItems($response['items'], $bulkRequest);
223227
throw $e;
224228
}
225-
226-
if ($this->eventDispatcher) {
227-
$this->eventDispatcher->dispatch(new PostCommitEvent($response, $this), Events::POST_COMMIT);
228-
}
229229
}
230230

231231
/**

src/Subscriber/EntityTrackerSubscriber.php

+12-7
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,18 @@ public function onPostCommit(PostCommitEvent $postCommitEvent)
6767

6868
// Update the ids of persisted entity objects
6969
foreach ($this->entitiesData[$postCommitEvent->getConnectionName()] as $bulkOperationIndex => $entityData) {
70-
$idValue = \current($postCommitEvent->getBulkResponse()['items'][$bulkOperationIndex])['_id'];
71-
$idPropertyMetadata = $entityData['metadata']['_id'];
72-
$entity = $entityData['entity'];
73-
if (DocumentMetadata::PROPERTY_ACCESS_PRIVATE === $idPropertyMetadata['propertyAccess']) {
74-
$entity->{$idPropertyMetadata['methods']['setter']}($idValue);
75-
} else {
76-
$entity->{$idPropertyMetadata['propertyName']} = $idValue;
70+
$bulkResponseItem = $postCommitEvent->getBulkResponse()['items'][$bulkOperationIndex];
71+
$operation = \key($bulkResponseItem);
72+
$bulkResponseItemValue = \current($bulkResponseItem);
73+
if (in_array($operation, ['create', 'index']) && !isset($bulkResponseItemValue['error'])) {
74+
$idValue = $bulkResponseItemValue['_id'];
75+
$idPropertyMetadata = $entityData['metadata']['_id'];
76+
$entity = $entityData['entity'];
77+
if (DocumentMetadata::PROPERTY_ACCESS_PRIVATE === $idPropertyMetadata['propertyAccess']) {
78+
$entity->{$idPropertyMetadata['methods']['setter']}($idValue);
79+
} else {
80+
$entity->{$idPropertyMetadata['propertyName']} = $idValue;
81+
}
7782
}
7883
}
7984

tests/Functional/Subscriber/EntityTrackerSubscriberTest.php

+45
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Sineflow\ElasticsearchBundle\Tests\Functional\Subscriber;
44

5+
use Sineflow\ElasticsearchBundle\Exception\BulkRequestException;
56
use Sineflow\ElasticsearchBundle\Finder\Finder;
67
use Sineflow\ElasticsearchBundle\Result\DocumentConverter;
78
use Sineflow\ElasticsearchBundle\Tests\AbstractElasticsearchTestCase;
@@ -13,6 +14,50 @@
1314
*/
1415
class EntityTrackerSubscriberTest extends AbstractElasticsearchTestCase
1516
{
17+
/**
18+
* Test executing 2 separate bulk requests, where there's an error in the first one,
19+
* to make sure the subscriber properly keeps track of bulk request items.
20+
*/
21+
public function testTwoBulkRequestWithErrorInFirstOne()
22+
{
23+
$imWithAliases = $this->getIndexManager('customer');
24+
$customer1 = new Customer();
25+
$customer1->name = 'batman';
26+
$customer1->setActive('invalid value');
27+
$customer2 = new Customer();
28+
$customer2->name = 'robin';
29+
$imWithAliases->persist($customer1);
30+
$imWithAliases->persist($customer2);
31+
try {
32+
$imWithAliases->getConnection()->commit();
33+
} catch (BulkRequestException $e) {
34+
// ignore the exception
35+
}
36+
37+
$customer3 = new Customer();
38+
$customer3->name = 'superman';
39+
$imWithAliases->persist($customer3);
40+
$imWithAliases->getConnection()->commit();
41+
42+
$this->assertNull($customer1->id, 'id should not have been set');
43+
$this->assertNotNull($customer2->id, 'id should have been set');
44+
$this->assertNotNull($customer3->id, 'id should have been set');
45+
46+
// Make sure that the correct id was assigned to the object, not the id of another customer
47+
// Get the customer from ES by name
48+
$finder = $this->getContainer()->get(Finder::class);
49+
50+
$docs = $finder->find(['AcmeFooBundle:Customer'], ['query' => ['match' => ['name' => 'robin']]]);
51+
$this->assertCount(1, $docs);
52+
$retrievedCustomer2 = $docs->current();
53+
$this->assertEquals($customer2->id, $retrievedCustomer2->id);
54+
55+
$docs = $finder->find(['AcmeFooBundle:Customer'], ['query' => ['match' => ['name' => 'superman']]]);
56+
$this->assertCount(1, $docs);
57+
$retrievedCustomer3 = $docs->current();
58+
$this->assertEquals($customer3->id, $retrievedCustomer3->id);
59+
}
60+
1661
/**
1762
* Test populating persisted entity ids after a bulk operation with several operations
1863
*/

0 commit comments

Comments
 (0)