目前,我们有一个orderId,我们给用户带来好处(张贴)。有多个事件可以触发利益/公告。但是条件是只有一个事件应该被触发。因此,为了处理当前的请求,我们创建了一个布尔字段 POSTING_EVENT_SENT ,最初设置为false,之后,能够将其标记为true的人可以继续进行。
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; }
这是代码试图执行的mongodb查询。
db.order.update({orderId : 123, paymentEventSent: false},{$set : {paymentEventSent: true}})
我们正在检查字段是否为假,然后将其标记为true。因此,理论上只有一个请求能够完成同样的任务,因为mongo查询是原子的。但是在我们的场景中,两个并发查询都成功地更新了记录。我们还缺什么?
发布于 2021-01-27 09:01:24
使用条件更新并检查更新文档的数量,以确定更新是否发生。
require 'mongo' client = Mongo::Client.new(['localhost:14400']) coll = client['coll'] coll.delete_many coll.insert_one(foo: 1) rv = coll.update_one({foo: 1}, '$set' => {foo: 2}) if rv.modified_count == 1 puts 'Updated'