SimpleMongoLock extends AbstractSimpleLock { @Override protected String acquire(final String key, final String storeId, final String token, final long expiration) { final var query = Query.query(Criteria.where("_id").is(key)); final var update = new Update() .setOnInsert("_id", key) .setOnInsert("expireAt", LocalDateTime.now().plus(expiration, ChronoUnit.MILLIS)) .setOnInsert("token", token); final var options = new FindAndModifyOptions().upsert(true).returnNew(true); final var doc = mongoTemplate.findAndModify(query, update, options, LockDocument.class, storeId); final var locked = doc.getToken().equals(token); log.debug("Tried to acquire lock for key {} with token {} in store {}. Locked: {}", key, token, storeId, locked); return locked ? token : null; } SimpleMongoLock(final Supplier<String> tokenSupplier, final MongoTemplate mongoTemplate);   }
@Test public void shouldLock() { final var expectedExpiration = LocalDateTime.now().plus(1000, ChronoUnit.MILLIS); final var token = lock.acquire(Collections.singletonList("1"), "locks", 1000); assertThat(token).isEqualTo("abc"); final var document = mongoTemplate.findById("1", LockDocument.class, "locks"); assertThat(document.getToken()).isEqualTo("abc"); assertThat(document.getExpireAt()).isCloseTo(expectedExpiration, new TemporalUnitWithinOffset(100, ChronoUnit.MILLIS)); }
@Test public void shouldNotLock() { mongoTemplate.insert(new LockDocument("1", LocalDateTime.now().plusMinutes(1), "def"), "locks"); final var token = lock.acquire(Collections.singletonList("1"), "locks", 1000); assertThat(token).isNull(); assertThat(mongoTemplate.findById("1", LockDocument.class, "locks").getToken()).isEqualTo("def"); }