
io.cloudslang.engine.queue.services.ExecutionQueueServiceImpl Maven / Gradle / Ivy
The newest version!
/*
* Copyright © 2014-2017 EntIT Software LLC, a Micro Focus company (L.P.)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudslang.engine.queue.services;
import io.cloudslang.engine.queue.entities.ExecStatus;
import io.cloudslang.engine.queue.entities.ExecutionMessage;
import io.cloudslang.engine.queue.entities.Payload;
import io.cloudslang.engine.queue.repositories.ExecutionQueueRepository;
import io.cloudslang.engine.queue.services.assigner.ExecutionAssignerService;
import io.cloudslang.engine.versioning.services.VersionService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.time.StopWatch;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static java.util.stream.Collectors.toList;
/**
* User:
* Date: 20/09/12
* Time: 18:09
*/
final public class ExecutionQueueServiceImpl implements ExecutionQueueService {
private final Logger logger = LogManager.getLogger(this.getClass());
@Autowired
private ExecutionQueueRepository executionQueueRepository;
@Autowired
private ExecutionAssignerService executionAssignerService;
@Autowired
private BusyWorkersService busyWorkersService;
@Autowired(required = false)
private List listeners = Collections.emptyList();
@Autowired
private VersionService versionService;
@Override
@Transactional
public void enqueue(List messages) {
if (CollectionUtils.isEmpty(messages))
return;
if (logger.isDebugEnabled()) logger.debug("Enqueue " + messages.size() + " messages");
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// assign worker for messages with pending status
messages = executionAssignerService.assignWorkers(messages);
if (logger.isDebugEnabled()) logger.debug("Messages were assigned successfully");
final List stateMessages = new ArrayList<>(messages.size());
// first fill the execution state id for new insert
for (ExecutionMessage msg : messages) {
if (msg.getExecStateId() == ExecutionMessage.EMPTY_EXEC_STATE_ID) {
long execStateId = executionQueueRepository.generateExecStateId();
msg.setExecStateId(execStateId);
stateMessages.add(msg);
} else if (msg.getPayload() != null && msg.getStatus() == ExecStatus.IN_PROGRESS) {
stateMessages.add(msg);
}
}
if (CollectionUtils.isNotEmpty(listeners)) {
stopWatch.split();
for (QueueListener listener : listeners) {
listener.prePersist(messages);
}
if (logger.isDebugEnabled()) logger.debug("Listeners done in " + (stopWatch.getSplitTime()) + " ms");
}
stopWatch.split();
if (stateMessages.size() > 0) {
executionQueueRepository.insertNotActiveExecutionsQueues(stateMessages.stream()
.filter(executionMessage -> !executionMessage.isActive())
.collect(toList()));
executionQueueRepository.insertExecutionStates(stateMessages);
}
long msgVersion = versionService.getCurrentVersion(VersionService.MSG_RECOVERY_VERSION_COUNTER_NAME);
executionQueueRepository.insertExecutionQueue(messages, msgVersion);
if (logger.isDebugEnabled()) logger.debug("Persistency done in " + (stopWatch.getSplitTime()) + " ms");
if (CollectionUtils.isNotEmpty(listeners)) {
stopWatch.split();
List failedMessages = filter(messages, ExecStatus.FAILED);
List terminatedMessages = filter(messages, ExecStatus.TERMINATED);
List toPersistMessages = filterToPersistMessages(messages);
for (QueueListener listener : listeners) {
listener.onEnqueue(messages, messages.size());
if (!failedMessages.isEmpty()){
listener.onFailed(failedMessages);
}
if (!terminatedMessages.isEmpty()){
listener.onTerminated(terminatedMessages);
}
if (!toPersistMessages.isEmpty()){
listener.onPersistMessage(toPersistMessages);
}
}
if (logger.isDebugEnabled()) logger.debug("Listeners done in " + (stopWatch.getSplitTime()) + " ms");
}
if (logger.isDebugEnabled()) logger.debug("Enqueue done in " + (stopWatch.getTime()) + " ms");
}
private List filter(List messages, ExecStatus status) {
List result = new ArrayList<>();
for (ExecutionMessage msg : messages) {
if (msg.getStatus() == status) {
result.add(msg);
}
}
return result;
}
private List filterToPersistMessages(List messages) {
List result = new ArrayList<>();
for (ExecutionMessage msg : messages) {
if (msg.isStepPersist()) {
result.add(msg);
}
}
return result;
}
@Override
@Transactional(readOnly = true)
public List poll(String workerId, int maxSize, long workerPollingMemory, ExecStatus... statuses) {
List result = new ArrayList<>();
//check if the worker has work before actually polling for work
if(busyWorkersService.isWorkerBusy(workerId))
result = executionQueueRepository.poll(workerId, maxSize, workerPollingMemory, statuses);
for (QueueListener listener : listeners) {
listener.onPoll(result, result.size());
}
return result;
}
@Override
@Transactional(readOnly = true)
public List pollRecovery(String workerId, int maxSize, ExecStatus... statuses) {
return executionQueueRepository.pollRecovery(workerId, maxSize, statuses);
}
@Override
@Transactional(readOnly = true)
public List pollMessagesWithoutAck(int maxSize, long minVersionAllowed) {
List result = executionQueueRepository.pollMessagesWithoutAck(maxSize, minVersionAllowed);
if (listeners != null && result != null) {
for (QueueListener listener : listeners) {
listener.onPoll(result, result.size());
}
}
return result;
}
@Override
@Transactional(readOnly = true)
public Map readPayloadByExecutionIds(Long... ids) {
if (ArrayUtils.isEmpty(ids)) throw new IllegalArgumentException("List of IDs is null or empty");
return executionQueueRepository.findPayloadByExecutionIds(ids);
}
@Override
@Transactional(readOnly = true)
public List readMessagesByStatus(int maxSize, ExecStatus... statuses) {
return executionQueueRepository.findByStatuses(maxSize, statuses);
}
@Override
@Transactional(readOnly = true)
public int countMessagesWithoutAckForWorker(int maxSize, long minVersionAllowed, String workerUuid) {
return executionQueueRepository.countMessagesWithoutAckForWorker(maxSize, minVersionAllowed, workerUuid);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy