procrastinate icon indicating copy to clipboard operation
procrastinate copied to clipboard

Wait asynchronously for a deferred job to complete and get its return value

Open Korijn opened this issue 5 years ago • 9 comments

Question is in the title. With this library, can you (asynchronously) wait for a deferred job to complete and get its return value? I couldn't find it in the docs.

Something like:

result = await sum.defer_async(a=3, b=5)
output = await result.get()

Korijn avatar Dec 15 '20 15:12 Korijn

No, there's no such thing. The return values of tasks are ignored by Procrastinate. They are actually logged, but that's it. In particular they're not stored in the procrastinate_jobs table. So it is your task's responsibility to save its results somewhere, in an application-specific Postgres table for example.

Note that Task.defer returns a the deferred job id, that is the id of the job in the procrastinate_jobs table. Procrastinate doesn't currently provide a Python function for checking the status of a job given its id, but this is something we could consider adding in the future. In the mean time, you can use that job id to yourself read the job status from the procrastinate_jobs table.

elemoine avatar Dec 16 '20 09:12 elemoine

So, let me see if I understand correctly:

  • I can get a job's status from the table procrastinate_jobs, but I would need to write the query myself
  • Waiting for a job to complete is also something I would need to write myself? (I thought I read something about postgres' LISTEN being used...)
  • Writing results and retrieving them should be implemented in application code

Korijn avatar Dec 16 '20 09:12 Korijn

* I can get a job's  status from the table `procrastinate_jobs`, but I would need to write the query myself

Yep. Contrary to what I said in my previous comment, Procrastinate does have a function for retrieving a job by its id, but it's not part of the official API yet.

jobs = app.manager.list_jobs(id=your_job_id)
job = jobs[0]
print(f"{job.status}")

But this is an area of Procrastinate that is still in flux I'd say.

Waiting for a job to complete is also something I would need to write myself?

Yes.

I thought I read something about postgres' LISTEN being used...

Yes, it's used internally to wake up the Procrastinate workers when a new job is inserted into the queue.

Writing results and retrieving them should be implemented in application code

Yep, you got that right.

elemoine avatar Dec 16 '20 09:12 elemoine

Alright, thanks for confirming! I'm contemplating a move from Celery to procrastinate because it fits our setup so well (the locking features in particular), but having to implement something similar to a result backend ourselves might be too risky.

Final question: do you support anything similar to Celery's task chains, where one task's output is fed to the input of the next task in a sequence?

Korijn avatar Dec 16 '20 09:12 Korijn

Alright, thanks for confirming! I'm contemplating a move from Celery to procrastinate because it fits our setup so well (the locking features in particular), but having to implement something similar to a result backend ourselves might be too risky.

In our applications, we use a Postgres table for storing results. We have a Postgres database which contains both the Procrastinate and application-specific objects.

elemoine avatar Dec 16 '20 09:12 elemoine

Final question: do you support anything similar to Celery's task chains, where one task's output is fed to the input of the next task in a sequence?

Well, given that we do not store the return value of a job (...yet), that's not something we have. But using the lock, you can make the equivalent of a sequence and ensure that a group of tasks will run in order (defer the tasks with the same lock value in order, and they will run in order).

I think we could imagine a lot of things from what you're mentionning:

  • Storing the results of a task (would probably limit to JSON, same as the task args)
  • Adding a function to fetch a task in the official public API
  • Have each task emit a postgres NOTIFY that we could listen for
  • Have a method for awaiting a task completion (maybe with a timeout, or leave that to the caller)
  • Provide primitives such as chains and chords (I don't know if we could make chords today) to ease migration from Celery

This all requires some time to setup, so if we agree, we could make scoped tickets. Would you be interested to participate in the development of some of those, @Korijn ?

ewjoachim avatar Dec 16 '20 17:12 ewjoachim

I would enjoy working on something like that, however I am currently plowing through a list of personal projects already so it will take some time before I would be able to get to it. Is that a problem?

Korijn avatar Dec 24 '20 23:12 Korijn

From my point of view, it's fine if it's not done soon, and I'll be glad to provide some help or guidance :) But if people want to tackle some steps before, it's first come first serve :) (as long as we create tickets and, ideally, assign ourselves to them on ping in them)

ewjoachim avatar Jan 11 '21 13:01 ewjoachim

Hm, a few months apart, I realize I gave a different answer regarding storing tasks. https://github.com/peopledoc/procrastinate/issues/419

@elemoine What's your opinion on that ?

ewjoachim avatar Jul 16 '21 20:07 ewjoachim