Celery countdown sets eta in the past - celery

I have a celery task which I call using the countdown keyword.
def plan_my_task():
countdown = some_computation_function() #result is a positive integer
res = my_task.apply_async(args=[some_arg], countdown=countdown)
#task
def my_task(some_arg):
do_something()
In my logs in see something like
[2013-11-14 01:22:31,516: INFO/MainProcess] Received task: my_module.my_task[d5d36a59-b88a-43cb-b7ac-bf0737cdab2c] eta:[2013-11-14 01:16:17.513310+01:00]
As you can see, the eta is set before the current time!
I use celery 3.1.

I don't actually use celery, but from the API, it looks like countdown is a keyword parameter to both Task.apply_async, or Task.retry. It's not a keyword for a function just decorated with #task
EDIT: According to this answer, it may be that the log time is in local time, and the ETA time is in UTC time. This might be possible if countdown was in the thousands (to give us a few hours off instead of the few minutes it looks like its off comparing the times directly)

Related

In Celery tasks, do retry_backoff and retry_backoff_max affect the manual self.retry() calls?

So according to the docs, default_retry_delayspecifies the time in seconds before a retry of the task should be executed. I just want to be sure that this only affects the manually called self.retry()calls and not the autoretries triggered by Celery when the task encounters predefined exceptions.
Likewise, I want to know if retry_backoff and retry_backoff_maxonly affect the autoretries and not the manual self.retry().
Finally, what happens when all of these are set?
That answer may change depending on the version of Celery that is used. However, as far as I have checked with the source code of versions v4.3.1, v4.4.7 and v5.0.0, retry_backoff and retry_backoff_max only affect the auto-retry. If autoretry_for is not set as True (or a True value such as positive integers), then the backoff parameters is not used.
As it can be seen from the implementation, when a True value is set to autoretry_for, Celery uses retry_backoff, retry_backoff_max, and retry_jitter arguments in order to compute the countdown of the next retry, before calling .retry method. Thus, these retry_xx arguments are not directly used by the .retry method; however, they affect the value of countdown. Thus, they are only used in the auto_retry.
When the countdown is explicity defined or computed via autoretry, then the value of default_retry_delay is ignored, as it can be seen in the implementation of v5.0.0. The same is valid when eta is set. Thus, to be able to use default_retry_delay, countdown, and eta should not be set. Additionally, autoretry_for should not be set or it should be set with a False value.
Another approach to use default_retry_delay and autoretry at the same time would be to define autoretry and retry variables; but for manual retry calls, set the eta and countdown to None explicitly. One example:
#app.task(bind=True, default_retry_delay=360, autoretry_for=[ExternalApiError], max_retries=5, retry_backoff=1800, retry_backoff_max=8 * 3600, retry_jitter=False)
def my_task(self, data):
try:
... # some code here that may raise ExternalApiError
except SomeOtherError:
try:
self.retry(countdown=None, eta=None)
except self.MaxRetriesExceededError:
... # when maximum number of retries has been exceeded.
If you want to use backoff parameters with manual retry calls, it can be implemented by using the method get_exponential_backoff_interval of Celery. One example could be this:
from celery.utils.time import get_exponential_backoff_interval
#app.task(bind=True, max_retries=5)
def my_task(self, data):
try:
... # some code here that may raise ExternalApiError
except SomeOtherError:
try:
retry_backoff = True
retry_backoff_max = 5
retry_jitter = True
countdown = get_exponential_backoff_interval(
factor=retry_backoff,
retries=self.request.retries,
maximum=retry_backoff_max,
full_jitter=retry_jitter)
)
self.retry(countdown=countdown)
except self.MaxRetriesExceededError:
... # when maximum number of retries has been exceeded.

Sahi scripting wait or time delay

I was wondering if someone could help me. I want to introduce a 10 minute wait or time delay within my sahi script.
Can someone confirm the correct command to use?
Thanks in advance
Just have a look at the docs, the command you are looking for is _wait
https://sahipro.com/docs/sahi-apis/action-apis.html#Waits
Write _wait(parameter); where parameter is your the time in milli-seconds you want to introduce the delay for.
In your case try _wait(600000);
You can also use the setSpeed(parameter); API , in this case Sahi will wait for the time specified in milli-seconds as a parameter , after each task in the script. But I guess waiting 10 mins after each task is not your requirement.
You can use this method:
_wait($timeout, [$condition])
here $timeout is the duration you want to wait for. And $Condition is something that you can customize based on what condition you want to wait for.
Or you can just use the overloaded method _wait($timeout) if you want to wait for a specific duration.
You can also apply a conditional wait:
_wait(timeOut, _isVisible($element));
This will either wait till "timeOut" milliseconds, or till $element is visible. (whichever condition is satisfied earlier)

django-celery PeriodicTask and eta field

I have a django project in combination with celery and my need is to be able to schedule tasks dynamically, at some point in the future, with recurrence or not. I need the ability to delete/edit already scheduled tasks
So to achieve this at the beginning I started using django-celery with DatabaseScheduler to store some PeriodicTasks (with expiration) to the database as it is described more or less here
In this way if I close my app and start it again my schedules are still there
My problem though still remains since I cannot utilize the eta and schedule a task at some point in the future. Is it possible somehow to dynamically schedule a task with eta?
A second question of mine is whether I can schedule a once off task, like schedule it to run e.g. at 2015-05-15 15:50:00 (that is why I'm trying to use eta)
Finally, I will be scheduling some thousants of notifications, is celery beat capable to handle this number of scheduled tasks? some of them once-off while others being periodic? Or do I have to go with a more advanced solution such as APScheduler
Thank you
I've faced the same problem yesterday. My ugly temporary solution is:
# tasks.py
from djcelery.models import PeriodicTask, IntervalSchedule
from datetime import timedelta, datetime
from django.utils.timezone import now
...
#app.task
def schedule_periodic_task(task='app.tasks.task', task_args=[], task_kwargs={},
interval=(1, 'minute'), expires=now()+timedelta(days=365*100)):
PeriodicTask.objects.filter(name=task+str(task_args)+str(task_kwargs)).delete()
task = PeriodicTask.objects.create(
name=task+str(task_args)+str(task_kwargs), task=task,
args=str(task_args),
kwargs=str(task_kwargs),
interval=IntervalSchedule.objects.get_or_create(
every=interval[0],
period=interval[1])[0],
expires=expires,
)
task.save()
So, if you want to schedule periodic task with eta, you shoud
# anywhere.py
schedule_periodic_task.apply_async(
kwargs={'task': 'grabber.tasks.grab_events',
'task_args': [instance.xbet_id], 'task_kwargs': {},
'interval': (10, 'seconds'),
'expires': instance.start + timedelta(hours=3)},
eta=instance.start,
)
schedule task with eta, which creates periodic task. Ugly:
deal with raw.task.name
strange period (n, 'interval')
Please, let me know, if you designed some pretty solution.

Setting Time Limit on specific task with celery

I have a task in Celery that could potentially run for 10,000 seconds while operating normally. However all the rest of my tasks should be done in less than one second. How can I set a time limit for the intentionally long running task without changing the time limit on the short running tasks?
You can set task time limits (hard and/or soft) either while defining a task or while calling.
from celery.exceptions import SoftTimeLimitExceeded
#celery.task(time_limit=20)
def mytask():
try:
return do_work()
except SoftTimeLimitExceeded:
cleanup_in_a_hurry()
or
mytask.apply_async(args=[], kwargs={}, time_limit=30, soft_time_limit=10)
This is an example with decorator for an specific Task and Celery 3.1.23 using soft_time_limit=10000
#task(bind=True, default_retry_delay=30, max_retries=3, soft_time_limit=10000)
def process_task(self, task_instance):
"""Task processing."""
pass

How is delay of the akka scheduler?

I wrote an actor, using a scheduler each 5 milliseconds to assign a time stamp to a field.
And in test, I found that the result of (System.currentTimeMillis() - timeField) is at least 35
And if I use a scheduleAtFixedRate() method from the Executors.scheduledThreadPool, the result is right.
So is the scheduler delay has a min value ?
Answer: the default tick duration is 100 milliseconds.
ScheduledThreadPoolExecutor uses System.nanoTime():
http://fuseyism.com/classpath/doc/java/util/concurrent/ScheduledThreadPoolExecutor-source.html
See comparison here:
System.currentTimeMillis vs System.nanoTime
Akka has a fairly extensive documentation.
Here's an excerpt:
"The default implementation of Scheduler used by Akka is based on the Netty HashedWheelTimer. It does not execute tasks at the exact time, but on every tick, it will run everything that is overdue. The accuracy of the default Scheduler can be modified by the “ticks-per-wheel” and “tick-duration” configuration properties. For more information, see: HashedWheelTimers."