Search code examples
pythonpostgresqlweb2py

Can web2py tasks(scheduler) have a race condition with web2py actions?


I am running a web2py application which has a function that is called by a webhook from an external source. That function schedules a task and puts data from the webhook into my db. The task it schedules also updates the db. I noticed that none of my tasks are failing, but the db does not appear to be updated properly by the task.

From the docs:

Remember to call db.commit() at the end of every task if it involves inserts/updates to the database. web2py commits by default at the end of a successful action but the scheduler tasks are not actions.

My code has roughly the following form, and I am wondering if this can generate a race condition or if the first insert happens right away:

def receive_webhook():
  def POST(*args, **vars):
    inserted_id = db.webhook_table.insert(webhook_data=data, status=0)
    #I have tested with putting a db.commit() here and problem still persists
    scheduler.queue_task(process_update,pvars={'inserted_id': inserted_id})
    #....some other code happens after this

The code in my Scheduler.py:

 def process_update(inserted_id):
        import json
        record = db(db.webhook_table.id == inserted_id).select().as_list()
        # CAN THIS SELECT FINISH BEFORE THE INSERT FROM receive_webhook IS RECORDED IN THE DB OR IS THE INSERT FINISHED IMMEDIATEDLY
        state = json.loads(record[0]['webhook_data'])['status']
        if not state == 'Updated':
            db(db.webhook_table.id == inserted_id).update(status=2)
        db.commit()
    from gluon.scheduler import Scheduler
    scheduler = Scheduler(db)

Can this create a race condition? If so what is the best way to fix it so that it can't?


Solution

  • scheduler.queue_task does an insert, but it is part of the same transaction as the insert in the previous line, so both inserts will be committed at the same time. So, it should not be possible for the task to be processed before the initial insert has been committed.