0

The examples provided in the Python-RQ documentation consistently show functions being enqueued, using queue.enqueue(). For example:

job = q.enqueue(count_words_at_url, 'http://nvie.com')

Is it possible to enqueue a method of a particular object instance? And if so, is this considered reasonable practise?

For example:

member = Member.objects.get(id=142)
job = q.enqueue(member.send_email())

If the answer to either of the above questions is no, what is the reccommended pattern to approach this situation?

One possiblity I had considered was to create a helper function, that is independent of the Member model. For example:

def send_member_email_bg_task(member_id):
    Member.objects.get(id=member_id).send_email()

and enqueue it as follows:

job = q.enqueue(send_member_email_bg_task, member.id)

I would be grateful for suggestions on the best way to approach this. Thanks

Scratcha
  • 1,359
  • 1
  • 14
  • 22
  • 1
    The bound method is `member.send_email`, not `member.send_email()`, just as the function is `count_words_at_url`, not `count_words_at_url()`. – chepner Feb 12 '23 at 21:36

1 Answers1

1

You can enqueue any queueable object. In this case, that object is the bound method member.send_mail, not the object that results from the call member.send_email().

member = Member.objects.get(id=142)
job = q.enqueue(member.send_email)

The bound method produced by member.send_email wraps both member and type(member).send_email, and when called calls the wrapped function with member as its first argument.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • In your example, when the worker picks up and executes the work, will it call send_email() on the same instance of member? ie where member.id=142 ? – Scratcha Feb 12 '23 at 21:53
  • Yes; `member.send_email.__self__ is member`, so when when the bound method is finally called, it will do so using `member`. – chepner Feb 12 '23 at 22:53