Batalkan tugas yang sudah dijalankan dengan Celery?

96

Saya telah membaca dokumen dan mencari tetapi tidak dapat menemukan jawaban langsung:

Bisakah Anda membatalkan tugas yang sudah dijalankan? (seperti dalam tugas telah dimulai, membutuhkan beberapa saat, dan setengah jalan perlu dibatalkan)

Saya menemukan ini dari dokumen di FAQ Celery

>>> result = add.apply_async(args=[2, 2], countdown=120)
>>> result.revoke()

Tapi saya tidak jelas apakah ini akan membatalkan tugas antrian atau jika itu akan mematikan proses yang sedang berjalan pada seorang pekerja. Terima kasih atas cahaya apa pun yang bisa Anda tumpahkan!

dcoffey3296.dll
sumber

Jawaban:

185

mencabut membatalkan eksekusi tugas. Jika tugas dicabut, pekerja mengabaikan tugas tersebut dan tidak menjalankannya. Jika Anda tidak menggunakan pencabutan persisten, tugas Anda dapat dijalankan setelah pekerja dimulai ulang.

http://docs.celeryproject.org/en/latest/userguide/workers.html#worker-persistent-revokes

revoke memiliki opsi menghentikan yang False secara default. Jika Anda perlu menghentikan tugas yang sedang dijalankan, Anda perlu mengatur terminate ke True .

>>> from celery.task.control import revoke
>>> revoke(task_id, terminate=True)

http://docs.celeryproject.org/en/latest/userguide/workers.html#revoke-revoking-tasks

mher
sumber
3
Ini persis penjelasan yang saya cari, terima kasih!
dcoffey3296
1
Apakah ini berfungsi di lingkungan terdistribusi? Maksud saya jika saya memiliki pekerja di beberapa mesin yang menjalankan tugas. Apakah seledri melacak mesin mana yang menjalankan tugas?
ksrini
1
Memang. Komunikasi dengan pekerja dilakukan melalui perantara.
mher
5
result.revoke (terminate = True) harus melakukan hal yang sama seperti revoke (task_id, terminate = True)
CamHart
10
Selain itu, menggunakan opsi menghentikan adalah "pilihan terakhir untuk administrator", sesuai dengan dokumen Celery terbaru. Anda menjalankan risiko menghentikan tugas lain yang baru-baru ini dimulai pada pekerja itu.
kouk
38

Di Celery 3.1, API tugas pencabutan diubah.

Menurut FAQ Seledri , Anda harus menggunakan result.revoke:

>>> result = add.apply_async(args=[2, 2], countdown=120)
>>> result.revoke()

atau jika Anda hanya memiliki id tugas:

>>> from proj.celery import app
>>> app.control.revoke(task_id)
Rockallite
sumber
25

Jawaban @ 0x00mh benar, namun dokumen seledri baru-baru ini mengatakan bahwa menggunakan terminateopsi ini adalah " pilihan terakhir untuk administrator " karena Anda mungkin secara tidak sengaja menghentikan tugas lain yang mulai dijalankan sementara itu. Mungkin solusi yang lebih baik adalah menggabungkan terminate=Truedengan signal='SIGUSR1'(yang menyebabkan pengecualian SoftTimeLimitExceeded dimunculkan dalam tugas).

kouk
sumber
2
Solusi ini bekerja dengan sangat baik untuk saya. Saat SoftTimeLimitExceededdimunculkan dalam tugas saya, logika pembersihan kustom saya (diimplementasikan melalui try/ except/ finally) dipanggil. Ini jauh lebih baik, menurut saya, daripada apa yang AbortableTaskditawarkan ( docs.celeryproject.org/en/latest/reference/… ). Dengan yang terakhir, Anda memerlukan backend hasil database dan Anda harus secara manual dan berulang kali memeriksa status tugas yang sedang berjalan untuk melihat apakah itu telah dibatalkan.
David Schneider
2
Bagaimana ini lebih baik, sejauh yang saya mengerti jika ada tugas lain yang diambil oleh proses tersebut, itu akan dihentikan, hanya pengecualian yang berbeda akan dilemparkan.
marxin
Jika saya menggunakan worker_prefetch_multiplier = 1karena saya hanya memiliki beberapa tugas yang berjalan lama, penghentian seharusnya baik-baik saja - karena tidak ada tugas lain yang akan dilakukan dengan penghentian - apakah saya mendapatkan ini dengan benar? @spicyramen
maffe
1

Lihat opsi berikut untuk tugas: time_limit , soft_time_limit (atau Anda dapat mengaturnya untuk pekerja). Jika Anda ingin mengontrol tidak hanya waktu eksekusi, lihat argumen kedaluwarsa metode apply_async.

Simplylizz
sumber