package ee.telekom.workflow.core.workunit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ee.telekom.workflow.core.common.WorkflowEngineConfiguration;
import ee.telekom.workflow.core.workflowinstance.WorkflowInstanceService;
@Service
@Transactional
public class WorkUnitServiceImpl implements WorkUnitService{
@Autowired
private WorkUnitDao dao;
@Autowired
private WorkflowInstanceService workflowInstanceService;
@Autowired
private WorkflowEngineConfiguration config;
@Override
public List<WorkUnit> findNewWorkUnits( Date now ){
String clusterName = config.getClusterName();
List<WorkUnit> newWorkUnits = dao.findNewWorkUnits( now, clusterName );
// The DAO returns a list of new work units that may contain more than one item per workflow instance.
// However, our concurrency strategy only supports one work unit per workflow instance at a time.
// If there is more than one work unit, we need to select one of them. When doing this selection, we
// make use of the fact that the list is ordered such that the first work unit for each workflow instance
// reflects the action with highest priority.
// (1) ABORT_PROCESS work units are of highest priority. If there is a ABORT_PROCESS work unit, we select this one.
// (2) First come, first serve. We take the work unit with the earliest "waiting since date". If two such work units have
// an identical "waiting since date", then we choose the one earlier inserted into the database (i.e. the one with
// lower work_item.ref_num.
int initialSize = newWorkUnits.size();
List<WorkUnit> workUnits = new ArrayList<>( initialSize );
Long previousWoinRefNum = null;
for( WorkUnit wu : newWorkUnits ){
Long woinRefNum = wu.getWoinRefNum();
if( !woinRefNum.equals( previousWoinRefNum ) ){
workUnits.add( wu );
previousWoinRefNum = woinRefNum;
}
}
return workUnits;
}
@Override
public void lock( List<WorkUnit> workUnits ){
List<Long> woinRefNums = new ArrayList<Long>( workUnits.size() );
for( WorkUnit wu : workUnits ){
woinRefNums.add( wu.getWoinRefNum() );
}
workflowInstanceService.lock( woinRefNums );
}
}