on 11-11-2014 10:19 AM
I am using hybris 5.1.0 and accelerator.When there is a email is sent as part of user registration, order creation, etc , if the email sending fails, I want to retry email sending (few times ,for next 2hr- which should be configurable in local.properties) .
I can see accelerator uses *process.xml for most of the work flows
e.g For customer registration , accelerator uses the customerRegistrationEmailProcess.xml , which
uses SendEmailAction to send emails.
Any idea how this retry can be implemented with its attributes such as retry count, how long to retry -are dynamic for each flow ?
I solved myself, For the benefit of many, the steps involved are described below.
1) Where ever the email sending is done using getEmailService().send() , RetryLaterException has to be thrown in case of failure
e.g SendEmailAction.java ->Extend this class and create a new class and override
@Override
public void executeAction(final de.hybris.platform.processengine.model.BusinessProcessModel businessProcessModel)
throws RetryLaterException
{
for (final EmailMessageModel email : businessProcessModel.getEmails())
{
getCustomerServiceEmails(email);
getEmailService().send(email);
if (!email.isSent())
{
int emailRetryDelay =5 ;//in minutes , //TODO read it from local.properties
LOG.info("Email sending failed - for " + businessProcessModel + " and its code " + businessProcessModel.getCode());
final RetryLaterException retryLaterException = new RetryLaterException();
retryLaterException.setDelay(1000L * 60L * emailRetryDelay); // in milliseconds
retryLaterException.setMethod(Method.LINEAR);
throw retryLaterException;
}
}
}
2) DefaultTaskExecutionStrategy is not handling the retry fully with predictable delay etc. So Extend DefaultTaskExecutionStrategy and create a new class and over ride handleRetry() as below
@Override
public Date handleRetry(final TaskService taskService, final TaskRunner<TaskModel> runner, final TaskModel model,
final RetryLaterException retry, final int currentRetries)
{
final int emailRetryCount = 5;// TODO read it from local.properties
log.info("Before evaluating retrying of Process " + ((ProcessTaskModel) model).getProcess() + " and action "
+ ((ProcessTaskModel) model).getAction());
Date next = null;
if (model instanceof ProcessTaskModel
&& (((ProcessTaskModel) model).getAction().equalsIgnoreCase("sendEmails"))) //TODO match whatever actions which sends email
{
if (model.getRetry() < emailRetryCount - 1)
{
next = retry.getMethod().nextInvocation(new Date(), currentRetries, retry.getDelay());
log.info("Before retrying of`process " + ((ProcessTaskModel) model).getProcess() + " with action "
+ ((ProcessTaskModel) model).getAction() + " next at: " + next + " retry count:" + (model.getRetry() + 1));
}
}
return next;
}
3). Register the above two classes in the *spring.xml and deploy.
4). To simulate the testing , go to HAC->platform->config. Search for smtp. change the ip address to a invalid one. Now try Forgot pwd functionality (or any flow which send emails)
5). Watch the server console, you should see the retries every minute for 5 (first+4 retries) times.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You can look into the workflow retry policy, assuming you want to retry failed jobs;
https://wiki.hybris.com/display/release5/Workflow+Retry+Policy
However I don't think that would work ideally in a cluster env.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Just to add you could go with a quick custom service if you can't use the task service; define retry status and counter attributes in the model, flag the failed events, build a search query dao of failed events, and publish/send them again until count of retry < retry_size_limit (and increment counter of course).
I would suggest to use the task engine for this, have a look at the technical guide:
https://wiki.hybris.com/display/release5/task+-+Technical+Guide
Example:
@Override
public void run(final TaskService paramTaskService, final TaskModel task) throws RetryLaterException {
if (!getEmailService().send((EmailMessageModel) task.getContext())) {
if (task.getRetry().intValue() <= 10) {
LOG.warn("email not sent successfully, trying to re-send email");
final RetryLaterException e = new RetryLaterException("unable to send email");
e.setDelay(60 * 60 * 1000);
throw e;
}
else {
throw new IllegalStateException("unable to send email after " + task.getRetry() + " retries");
}
}
else {
LOG.info("email sent successfully");
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
if (!getEmailService().send(email)) { throw new RetryLaterException(); }
Well this would retry. You don't control the count, how long to try etc. It exponentially waits longer each try. This is bad.
I would avoid this approach. Make a CronJob and run it regularly to "clean up" failures.You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
7 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.