Currently, we have an orderId for which we give the benefit(posting) to the user.
There are multiple events that can trigger benefit/posting. But the condition is that only 1 event should be triggered. Hence for handling current requests, we created a boolean field POSTING_EVENT_SENT, initially set to false, and later whoever was able to mark it as true can proceed further.
public boolean isOrderLockedAndUpdatedToTriggerPosting(String orderId, OrderStatus orderStatus) {
Query query = new Query();
query.addCriteria(Criteria.where(OrderConstants.ORDER_ID).is(orderId));
query.addCriteria(Criteria.where(OrderConstants.POSTING_EVENT_SENT).is(false));
Update update = new Update();
update.set(OrderConstants.ORDER_STATUS, orderStatus);
update.set(OrderConstants.UPDATED_AT, new Date());
update.set(OrderConstants.UPDATED_IP_BY, deploymentProperties.getServerIp());
update.set(OrderConstants.POSTING_EVENT_SENT, true);
update.set(OrderConstants.UPDATED_BY, OrderConstants.UPDATED_BY_WORKER);
UpdateResult result = mongoTemplate.updateFirst(query, update, OrderDetails.class);
return result.getModifiedCount() > 0;
}
this is the mongodb query that code is trying to execute
db.order.update({orderId : 123, paymentEventSent: false},{$set : {paymentEventSent: true}})
So we're checking if the field is false, then mark it to true. So theoretically only 1 request will be able to do the same, because the mongo queries are atomic.
But in our scenario, both the concurrent queries were updating the records successfully.
What else we're missing here?
question from:
https://stackoverflow.com/questions/65915366/mongodb-concurrent-update-to-same-document-is-not-behaving-atomic 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…