package ee.telekom.workflow.core.lock;
import java.lang.invoke.MethodHandles;
import java.util.Date;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import ee.telekom.workflow.core.common.WorkflowEngineConfiguration;
/**
* Manages an exclusive distributed lock per cluster to avoid multiple master.
*/
@Service
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class LockServiceImpl implements LockService{
private static final Logger log = LoggerFactory.getLogger( MethodHandles.lookup().lookupClass() );
@Autowired
private LockDao dao;
@Autowired
private WorkflowEngineConfiguration config;
@Override
public boolean eagerAcquire(){
releaseExpiredLock();
return refreshOwnLock() || acquireLock();
}
@Override
public boolean acquireLock(){
String clusterName = config.getClusterName();
String nodeName = config.getNodeName();
Date expireTime = DateUtils.addSeconds( new Date(), config.getHeartbeatMaximumPauseSeconds() );
boolean isAcquired = dao.create( clusterName, nodeName, expireTime );
return isAcquired;
}
@Override
public boolean isOwnLock(){
String nodeName = config.getNodeName();
return nodeName.equals( getLockOwner() );
}
@Override
public boolean refreshOwnLock(){
String clusterName = config.getClusterName();
String nodeName = config.getNodeName();
Date expireTime = DateUtils.addSeconds( new Date(), config.getHeartbeatMaximumPauseSeconds() );
boolean isRefreshed = dao.updateExpireTime( clusterName, nodeName, expireTime );
return isRefreshed;
}
@Override
public boolean releaseOwnLock(){
String clusterName = config.getClusterName();
String nodeName = config.getNodeName();
boolean isReleased = dao.deleteByOwner( clusterName, nodeName );
if( isReleased ){
log.info( "Released own lock" );
}
else{
log.error( "Could not release own lock since lock was not owned" );
}
return isReleased;
}
@Override
public boolean releaseExpiredLock(){
String clusterName = config.getClusterName();
Date now = new Date();
boolean isReleased = dao.deleteByExpireTime( clusterName, now );
if( isReleased ){
log.warn( "Released exprired lock" );
}
return isReleased;
}
@Override
public String getLockOwner(){
return dao.findOwner( config.getClusterName() );
}
@Override
public Date getLockExpireDate(){
return dao.findExpireTime( config.getClusterName() );
}
}