2

I am trying to run a periodic task with django celery, and it is dynamically added by users using custom arguments. I have the following code to start the task. I only want it to run once as it takes a while for it to set up, and I have an infinite while loop that constantly checks for changes on a website.

schedule, created = IntervalSchedule.objects.get_or_create(every=100,period=IntervalSchedule.DAYS,)
PeriodicTask.objects.create(interval=schedule, enabled=True, name=name,task='scanner.tasks.texting', args=json.dumps([phone_number, carrier_address]),)

The problem is that when I create the task, it is not started and needs to wait for the interval before starting. Is it possible to start the tasks when the object is created?

Otherwise, I could change the interval to just a second to start immediately. The problem with this implementation is that it will start the thread every second, even though I just want to run it once, and let it keep running in the background.

Does anyone have a solution to this?

rishubk
  • 441
  • 2
  • 8
  • 19

1 Answers1

0

You can just run the function in the background immediately:

scanner.tasks.texting.delay([phone_number, carrier_address])

and then add periodic task:

schedule, created = IntervalSchedule.objects.get_or_create(every=100,period=IntervalSchedule.DAYS,)
PeriodicTask.objects.create(interval=schedule, enabled=True, name=name,task='scanner.tasks.texting', args=json.dumps([phone_number, carrier_address]),)

The other solution might be to dynamically update periodic task. For example start periodic task with small interval and after the execution update the task, ideally task can be updated at the end of the first execution:

# you need additional object to keep reference to PeriodicTask

class ModelWithTask(models.Model):
    task = models.OneToOneField(
        PeriodicTask, null=True, blank=True, on_delete=models.SET_NULL
    )

# start with SECONDS interval

some_object = ModelWithTask.objects.get_or_create()

schedule, created = IntervalSchedule.objects.get_or_create(every=100,period=IntervalSchedule.SECONDS,)
task = PeriodicTask.objects.create(interval=schedule, enabled=True, name=name,task='scanner.tasks.texting', args=json.dumps([phone_number, carrier_address, some_object.id]),)

some_object.task = task
some_object.save()

Update task

# in scanner.tasks.texting

new_schedule, created = IntervalSchedule.objects.get_or_create(every=100,period=IntervalSchedule.DAYS,)

some_object.task.interval = new_schedule
some_object.task.save()


pplonski
  • 5,023
  • 1
  • 30
  • 34