run celery tasks in random times
<p>i need to run few celery tasks in random times - every run should be at a new random time - the random number should generated every run. <br>
what I did in the past is:<br></p>

<pre><code> "my_task": {
     "task": "path.to.my_task",
     "schedule": crontab(minute='*/%s' % rand),
 },
rand = random(1,12)
</code></pre>

<p>but this code is not good for my needs anu more:<br>
1. I need different (as possible with random0 number for each tenant <br>
2. different number will generated every time and not only on settings.py load (once) <br></p>

<p>I tried to overwrite Schedule as explained in <a href="http://stackoverflow.com/questions/7172584/django-celery-how-to-set-task-to-run-at-specific-interval-programmatically">THIS</a> answer but it did not work, is there better way? am I missing something?</p>

<p>(for example in tenant A the task will run at 23 and the day after at 8, and in tenant B the task will run at 4 and the day after at 20 etc)</p>

<p>Thanks! </p>

<p>======== update ====</p>

<p>after the great answer I got, I added option to my task and process it in apply_asynch method as suggested- <br>.</p>

<pre><code>"my-task": {  # deprecated task
               "task": "mdm_sync.tasks.test_task",
               # "schedule": new_sc(),
               "schedule": crontab(minute=39, hour=11),
                "options": {
                    "eta": datetime.utcnow()
                }
},
</code></pre>

<p><br></p>

<pre><code>entry.options["eta"] = datetime.datetime.utcnow() + datetime.timedelta(seconds=random(3600,12*3600)
</code></pre>

<p>works great!</p>

<p>I faced a similar problem in which i had to generate <strong>facebook</strong> like notifications between <strong>random users</strong> at <strong>random interval of time</strong></p>

<p>Initially i was also doing the same as you, using the <code>random</code> function to give the <code>minute</code> value to <code>crontab</code>. But, as <code>settings.py</code> and <code>celery.py</code> are loaded only once when you hit <code>python manage.py runserver</code>, that random function runs only once and hence that random value is selected only once, say <strong>5 minutes</strong> or <strong>7 minutes</strong>, but then this random value is used for repeating the task at every 5 or 7 minutes, hence making the tasks <strong>repeat periodically</strong>.</p>

<p>So, what you need to do is that instead of defining the timing of task in <code>settings.py</code> or <code>celery.py</code> you need to <strong>recursively</strong> call the function/ method in your <code>tasks.py</code>. But the key here is that you need to call the same function <strong>recursively and asynchronously</strong>, and while calling it asynchronously, you need to pass a parameter <strong>delay</strong> whose value will be calculated by using the <strong>random function</strong></p>

<p>See my <code>tasks.py</code> -> <a href="https://github.com/ankushrgv/notification/blob/master/apps/notifications/tasks.py" rel="nofollow">https://github.com/ankushrgv/notification/blob/master/apps/notifications/tasks.py</a></p>

<p>And</p>

<p><code>celery.py</code> -> <a href="https://github.com/ankushrgv/notification/blob/master/config/celery.py" rel="nofollow">https://github.com/ankushrgv/notification/blob/master/config/celery.py</a></p>

<p>You'll have to <code>python manage.py shell</code> and then call the function / method from there only once to start the recursion.</p>

<p>something like</p>

<pre><code>`myFunction().apply_async()`
</code></pre>

<p>In my case it used to be</p>

<pre><code>`CreateNotifications().apply_async()`
</code></pre>

python django celery celerybeat