Fix issue when multiple locks are in DB

This commit is contained in:
George Kalampokis 2020-02-14 10:35:19 +02:00
parent 2b41ca582f
commit a8fa0312d1
1 changed files with 29 additions and 10 deletions

View File

@ -9,11 +9,14 @@ import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Component @Component
public class LockManager { public class LockManager {
private final Comparator<eu.eudat.data.entities.Lock> compareByTouchedAt = Comparator.comparing(o -> o.getTouchedAt().getTime());
private ApiContext apiContext; private ApiContext apiContext;
private Environment environment; private Environment environment;
@ -34,7 +37,7 @@ public class LockManager {
} }
} }
}catch(NoResultException e) { }catch(NoResultException e) {
return new eu.eudat.data.entities.Lock(); lock.setId(null);
} }
} }
eu.eudat.data.entities.Lock newLock = lock.toDataModel(); eu.eudat.data.entities.Lock newLock = lock.toDataModel();
@ -47,31 +50,47 @@ public class LockManager {
LockCriteria criteria = new LockCriteria(); LockCriteria criteria = new LockCriteria();
criteria.setTarget(UUID.fromString(targetId)); criteria.setTarget(UUID.fromString(targetId));
Long availableLocks = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).count(); Long availableLocks = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).count();
if (availableLocks > 0) { if (availableLocks == 1) {
eu.eudat.data.entities.Lock lock = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).getSingle(); eu.eudat.data.entities.Lock lock = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).getSingle();
if (lock.getLockedBy().getId().equals(principal.getId())) { if (lock.getLockedBy().getId().equals(principal.getId())) {
lock.setTouchedAt(new Date()); lock.setTouchedAt(new Date());
this.createOrUpdate(new Lock().fromDataModel(lock), principal); this.createOrUpdate(new Lock().fromDataModel(lock), principal);
return false; return false;
} }
if (new Date().getTime() - lock.getTouchedAt().getTime() > environment.getProperty("database.lock-fail-interval", Integer.class)) { if (this.forceUnlock(targetId) > 0){
this.forceUnlock(targetId); return true;
return false;
} }
return true; } else if (availableLocks > 1) {
this.forceUnlock(targetId);
return this.isLocked(targetId, principal);
} }
return false; return false;
} }
private Long forceUnlock(String targetId) {
private void forceUnlock(String targetId) throws Exception {
LockCriteria criteria = new LockCriteria(); LockCriteria criteria = new LockCriteria();
criteria.setTarget(UUID.fromString(targetId)); criteria.setTarget(UUID.fromString(targetId));
Long availableLocks = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).count(); Long availableLocks = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).count();
Long deletedLocks = 0L;
if (availableLocks > 0) { if (availableLocks > 0) {
eu.eudat.data.entities.Lock lock = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).getSingle(); List<eu.eudat.data.entities.Lock> locks = this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().getWithCriteria(criteria).toList();
this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().delete(lock); for (eu.eudat.data.entities.Lock lock : locks) {
if (new Date().getTime() - lock.getTouchedAt().getTime() > environment.getProperty("database.lock-fail-interval", Integer.class)) {
this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().delete(lock);
deletedLocks++;
}
}
if (deletedLocks == 0) {
eu.eudat.data.entities.Lock recentlock = locks.stream().max(compareByTouchedAt).get();
for (eu.eudat.data.entities.Lock lock : locks) {
if (lock != recentlock) {
this.apiContext.getOperationsContext().getDatabaseRepository().getLockDao().delete(lock);
deletedLocks++;
}
}
}
} }
return availableLocks - deletedLocks;
} }
public void unlock(String targetId, Principal principal) throws Exception { public void unlock(String targetId, Principal principal) throws Exception {