I have sidekiq jobs running Selenium. If the job crashes, I need to
catch the exception to shut down the selenium driver (otherwise all coming jobs will crash as well),
notify error handler (Sentry)
Have sidekiq try again
Today I can catch and notify, but by catching the exception Sidekiq will not retry the job.
My question is similar to this one but a) it got no answer and b) that user did not want to notify its error handling service.
How do I get Sidekiq to retry the job even though I catch the exception?
How about re-raising exception? It would be something like this:
def perform
# perform_code
rescue ErrorClass => error
# handle error
raise error
end
This way, sidekiq is gonna repeat this task (because it raises an error), but the handling code will also be executed.
Is it possible to catch the following exception?
"Failed to get matching snapshots"
Most of the stability issues with XCUITest is due to not having a proper method to wait for element to exist. Tried exists(), waitforexistence(),xctwaiter waits etc. In all cases it fails randomly with above error. Is there a way we have handle this exception do a retry in our tests itself.
You should stick to combination of two methods
Use it for every flaky element
button.waitForExistence()
button.tap()
I'm developing a Java EE 7 application on wildfly 8.2 and need to run a periodic background task. I inject an executor service and schedule a task, this part is working fine:
#Resource
private ManagedScheduledExecutorService executorService;
...
executorService.scheduleWithFixedDelay(() -> {
try {
// do some stuff
} catch (Throwable t) {
log.error("Error", t);
}
}, 0, 1, TimeUnit.MINUTES);
Now the (actually nice) feature is that upon redeploy the scheduled task is saved and therefore is still scheduled in the new deployment.
But how can I detect if the task is already scheduled to avoid scheduling it multiple times?
I tried to use a ScheduledFutureand cancel the task on #PreDestroy
and #PrePassivate
reloadTreeFuture = executorService.scheduleWithFixedDelay(() -> {
...
#PreDestroy
#PrePassivate
protected void shutdown() {
reloadTreeFuture.cancel(true);
}
This is working fine as long as the corresponding task is not executing at the very moment the cancel is fired. Since the task is long running and running frequently the chance of hitting it in the middle of an execution is somewhat high.
If the cancel is fired while the task is still executing the cancel seems to do nothing. It immediatly returns and the method ScheduledFuture.isDone() also returns true but from the logs I can see the task is still executing in the background until it hits a point where it needs an injected Bean which is not available due to the undeployment process. The process then ends with org.jboss.msc.service.ServiceNotFoundException - but is still scheduled.
reloadTreeFuture.cancel(true);
while (!reloadTreeFuture.isDone()) {
Thread.sleep(200); // I know this is bad - it's just for testing
}
So basic question: how can I make sure the task is not scheduled twice (or even more)?
You could write down the id of each task and check them before executing. Of course this may be not a best solution, but it works.
When using Quartz.net to schedule jobs, I occasionally receive an exception when instantiating a job. This, in turn causes Quartz to set the trigger for the job to an error state. When this occurs, the trigger will cease firing until some manual intervention occurs (restarting the service since I'm using in-memory job scheduling).
How can I prevent the error state from being set, or at the very least, tell Quartz to retry triggers that are in the error state?
The reason for the exception is due to flaky network calls that are required to get configuration data that is passed in to the job's constructor. I'm using a custom IJobFactory to do this.
I've seen other references to this without resolutions:
https://groups.google.com/forum/#!topic/quartznet/8qaT70jfJPw
http://forums.terracotta.org/forums/posts/list/2881.page
For the record, I consider this a design flaw of Quartz. If a job can't be constructed once, that doesn't mean it can't always be constructed. This is a transient error and should be treated as such. Stopping all future scheduled jobs violates the principle of least astonishment.
Anyway, my hack solution is to catch any errors that are the result of my job construction and instead of throwing an error or returning null to return a custom IJob instead that simply logs an error. This isn't perfect, but at least it doesn't prevent future triggering of the job.
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
var job = this.container.Resolve(bundle.JobDetail.JobType) as IJob;
return job;
}
catch (Exception ex)
{
this.logger.Error(ex, "Exception creating job. Giving up and returning a do-nothing logging job.");
return new LoggingJob(this.logger);
}
}
When exception occurs on trigger instatiating IJob class, then trigger change it TRIGGER_STATE to ERROR, and then trigger in this state will no longer fire.To reenable trigger your need to change it state to WAITING, and then it could to fire again.
Here the example how your can reenable yours misfired trigger.
var trigerKey = new TriggerKey("trigerKey", "trigerGroup");
if (scheduler.GetTriggerState(trigerKey) == TriggerState.Error)
{
scheduler.ResumeTrigger(trigerKey);
}
Actually the best way to reset Trigger from ERROR state is:
private final SchedulerFactoryBean schedulerFactoryBean;
Scheduler scheduler = schedulerFactoryBean.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
if (scheduler.getTriggerState(triggerKey).equals(Trigger.TriggerState.ERROR)) {
scheduler.resetTriggerFromErrorState(triggerKey);
}
Note:
You should never modify the records in a table from a third-party library or software manually. All changes should be made through the API to that library if there is any functionality.
JobStoreSupport.resetTriggerFromErrorState
How can I prevent the error state from being set, or at the very least, tell Quartz to retry triggers that are in the error state?
Unfortunately, in current version, you cannot retry those triggers. As per the documentation of Quartz,
It should be extremely rare for this method to throw an exception -
basically only the case where there is no way at all to instantiate
and prepare the Job for execution. When the exception is thrown, the
Scheduler will move all triggers associated with the Job into the state, which will require human
intervention (e.g. an application restart after fixing whatever
configuration problem led to the issue with instantiating the Job).
Simply put, you should follow good object oriented practices: constructors should not throw exceptions. Try to move pulling of configuration data to job's execution phase (Execute method) where retries will be handled correctly. This might mean providing a service/func via constructor that allows pulling the data.
To change the trigger state to WAITING the author also suggests that a way could be to manually update the database.
[...] You might need to update database manually, but yeah - if jobs cannot be instantiated it's considered quite bad thing and Quartz will flag them as broken.
I created another job scheduled at app startup that updates the triggers in error state to recover them.
UPDATE QRTZ_TRIGGERS SET [TRIGGER_STATE] = 'WAITING' WHERE [TRIGGER_STATE] = 'ERROR'
More information in this github discussion.
When my test runs into a critical failure such as tapping an invalid element the Automation Instrument attempts to restart the test from the beginning which results in a lot of errors and can even lag my system, making it difficult to stop the test. I don't have the repeat option enabled. Is there a way of preventing this behavior?
I reckon what you can do is: try capturing when your test runs into a failure by means of a try/catch block.
When your test fails, it will jump inside the catch block and you can stop it there.
Maybe something like this.
try {
// Run your tests
} catch (exception){
UIALogger.logFail("Test failed with error message: " + exception.message);
}
I think that the logFail() method should be enough to keep your tests from running indefinately.