You can find in the documentation of Shedlock that in order to extend the maximum locked time, lockAtMostUntil
, you have to create both SimpleLock
and extend()
method manually. Remember that, you also have to invoke the extend()
method manually, or by implementing a check()
method that checks if your process is finished and invokes the extend()
method if needed, otherwise, the lock will be automatically unlocked when it reaches the lockAtMostUntil
time, no matter if your process is still running.
Here I am explaining how you can create the SimpleLock
manually from LockProvider
.
For questions about how to set the database, I recommend you read this part of the documentation of Shedlock.
I have used spring boot
for my application, so the annotations that you see come from spring boot
.
Dependencies:
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>4.23.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>4.23.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
Configuration of LockProvider
:
@EnableAsync
@Profile("!unit_test")
@Configuration
public class LockConfiguration {
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(
JdbcTemplateLockProvider.Configuration.builder()
.withTimeZone(TimeZone.getTimeZone("Europe/Rome"))
.withJdbcTemplate(new JdbcTemplate(dataSource))
.withTableName("shared_lock")
.usingDbTime()
.build());
}
}
DistributedLock here is where we implement SimpleLock
and all the needed related methods:
@Component
@Slf4j
public class DistributedLockWithExtend {
@Autowired
private LockProvider lockProvider;
private final Map<String, SimpleLock> locks = new HashMap<>();
public boolean tryLock(String lockname, Duration lockDuration){
Duration minDuration = Duration.ZERO;
Instant now = ClockProvider.now();
LockConfiguration config = new LockConfiguration(now, lockname, lockDuration, minDuration);
Optional<SimpleLock> lockLocal = lockProvider.lock(config);
if(lockLocal.isPresent()) {
locks.put(lockname, lockLocal.get());
log.debug("lock is created!");
return true;
}else {
log.debug("lock is locked!");
return false;
}
}
public boolean extendLock(String lockname, Duration duration){
Duration minDuration = Duration.ZERO;
SimpleLock lock = locks.get(lockname);
if(lock != null) {
Optional<SimpleLock> localLock = lock.extend(duration, duration);
locks.put(lockname, localLock.get());
log.debug("Lock is extended");
return true;
}else {
log.debug("There is no lock or the lock is already unlocked! Create a lock with tryLock() if you need!");
return false;
}
}
public String unLock(String lockname){
SimpleLock lock = locks.get(lockname);
if(lock != null) {
locks.remove(lockname);
lock.unlock();
log.debug("Lock is unLocked!");
return "Lock is unLocked!";
}else {
log.debug("There is no lock or the lock is already unlocked! Create a lock if you need!");
return "There is no lock or the lock is already unlocked! Create a lock if you need!";
}
}
}
And here is a test RestController that I created to demonstrate the usage of the DistributedLockWithExtend
methods:
@Profile("!unit_test")
@RestController
@RequestMapping(TestLockController.PATH)
public class TestLockController {
public static final String PATH = BaseController.PATH + "/test-lock";
@Autowired
ApplyPolicyScheduler applyPolicySchedular;
@Autowired
DistributedLockWithExtend distributedLockWithExtend;
@GetMapping("/up")
public String testService(){
return "Service is up!";
}
@GetMapping("/invoke")
public String invokeTest(){
return distributedLockWithExtend.tryLock("testLockUtil", Duration.ofMinutes(1)) + "";
}
@GetMapping("/extend")
public String extendTest(){
return distributedLockWithExtend.extendLock("testLockUtil", Duration.ofMinutes(3)) + "";
}
@GetMapping("/unlock")
public String unlockTest(){
distributedLockWithExtend.unLock("testLockUtil");
return "Unlock called!";
}
}