Closed aanair08 closed 5 months ago
The logic you were relying on was broken to begin with and fixed in 2.7.0. Before 2.7.0, the UnitOfWork unscheduled workloads (e.g. document insertions) before the write was actually completed. This led to situations where UnitOfWork thought that documents were successfully inserted when they weren't. So after that first flush that causes the duplicate key error, ODM thought that the customer was inserted successfully and on the subsequent call to flush
that inserts the DuplicateCustomer
document didn't handle $customer
at all.
In 2.7.0, this changed and the pending workload in the UnitOfWork is only marked as completed when it was actually completed in the database. Since the $customer
couldn't be saved to the database, it is still marked as a pending insertion and left for you to figure out. On the next flush
, it will once again attempt to save the document to the database, which of course will fail again.
The reason for making this change is twofold: for one, it is required to support transactions. In MongoDB, transactions can be retried after certain errors, so we have to remember pending writes until each write has completed. The other issue is that before the change the UnitOfWork state was broken: the document was marked as fully persisted when it wasn't - this could lead to further issues down the line.
Since you are handling the error yourself, the correct course of action here is to detach
the $customer
document so that it will no longer be managed by the UnitOfWork:
try {
$customer = new Customer();
$customer->setCustomerCode($customerCode);
$customer->setCustomerName($customerName);
$dm->persist($customer);
$dm->flush();
} catch (\Exception $e) {
if ($e->getCode() === self::MONGO_DUPLICATE_KEY_ERR_CODE) {
// detach original customer from document manager
$dm->detach($customer);
// duplicate customer code insert into tracking
$duplicateCustomer = new DuplicateCustomer();
$duplicateCustomer->setCustomerCode($customerCode);
$duplicateCustomer->setCustomerName($customerName);
$dm->persist($duplicateCustomer);
$dm->flush();
}
}
FWIW, situations like this one are why ORM closes the entity manager after any exception that occurs during a write. We have chosen not to go that route and instead leave the DocumentManager in the (broken) dirty state for the user to clean up. So, if you decide to handle errors during flushing, make sure to clean up before attempting to flush again.
I have a document called Customer, Which have a field named CustomerCode and added unique index. I have been trying to create Customer
This above code was working fine before. After the version changed 2.7.0 data not inserted into Duplicate Customer and show error in log saying that duplicate error in CustomerCode in Cutomer. I can not figure out the issue in there, since the code was working fine.