package com.softwaremill.common.sqs.task;
import com.google.common.base.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.softwaremill.common.sqs.Queue;
import com.softwaremill.common.sqs.ReceivedMessage;
import com.softwaremill.common.sqs.SQS;
import com.softwaremill.common.sqs.timer.TimerManager;
import com.softwaremill.common.task.ExecuteWithRequestContext;
import com.softwaremill.common.task.OneTimeTask;
import javax.ejb.Timeout;
import javax.inject.Inject;
import static com.softwaremill.common.sqs.SQSConfiguration.TASK_SQS_QUEUE;
/**
* Receiver polling Amazon's SQS queue and executing tasks.
*
* Configured via sqs.conf in jboss/server/profile/conf or classpath
* smtpHost= mailing host
* smtpPort= mailing host's port
* queue= SQS queue, where the email data is coming from
* from= from address put into the eamil
*
* To use this bean write a @Stateless bean that extends SQSTaskTimer
*
* @author Jaroslaw Kijanowski - jarek@softwaremill.pl
* Date: Aug 24, 2010
* @author Adam Warski
*/
public abstract class SQSTaskTimerBean extends TimerManager implements SQSTaskTimer {
private static final Logger LOG = LoggerFactory.getLogger(SQSTaskTimerBean.class);
public void startTimer(int interval){
startTimer(TASK_SQS_QUEUE, interval);
}
public void destroyTimer(){
destroyTimer(TASK_SQS_QUEUE);
}
@Inject
private SQS sqs;
/* That's just for legacy code, in case SQS doesn't get injected */
protected SQS getSQS() {
if (sqs ==null) {
sqs = new SQS();
}
return sqs;
}
@Timeout
public void timeout(javax.ejb.Timer timer) {
Queue queue = getSQS().getQueueByName(TASK_SQS_QUEUE);
Optional<ReceivedMessage> sqsAnswer = queue.receiveSingleMessage();
if (sqsAnswer.isPresent()) {
Object message = sqsAnswer.get().getMessage();
if (message instanceof OneTimeTask) {
LOG.debug("Deserialized message: " + message);
OneTimeTask task = (OneTimeTask) message;
try {
if (task.getTaskTimeout() != null) {
queue.setMessageVisibilityTimeout(sqsAnswer.get(), task.getTaskTimeout());
}
new ExecuteWithRequestContext(task).execute();
queue.deleteMessage(sqsAnswer.get());
} catch (RuntimeException e) {
LOG.warn("Something went wrong and the task has not been executed. Redelivery will occur.", e);
}
} else {
LOG.warn("Trash in SQS: " + TASK_SQS_QUEUE);
LOG.warn("Deserialized message: " + message + " -- removing message from queue!");
queue.deleteMessage(sqsAnswer.get());
}
}
LOG.debug("SQS task queue checked " + TASK_SQS_QUEUE);
}
/**
* Asynchronously executes the given task.
* @param task Task to execute.
*/
@SuppressWarnings("UnusedDeclaration")
public static void scheduleTask(OneTimeTask<?> task) {
scheduleTask(task, new SQS().getQueueByName(TASK_SQS_QUEUE));
}
public static void scheduleTask(OneTimeTask<?> task, Queue queue) {
queue.sendSerializable(task);
}
}