Sellerie - call-Funktion auf die Aufgabe
Ich bin mit Sellerie mit django und rabbitmq zum erstellen einer message queue. Ich habe auch ein Arbeiter, der ursprünglich aus einer anderen Maschine. In einem django, das ich beginne einem Prozess wie diesem:
def processtask(request, name):
args = ["ls", "-l"]
MyTask.delay(args)
return HttpResponse("Task set to execute.")
Meine Aufgabe ist so konfiguriert:
class MyTask(Task):
def run(self, args):
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = p.communicate()
return out
Meine Frage ist nun, wie kann ein broker (meine django-Projekt) erhalten nun die Ausgabe von "ls -l" - Befehl, der den Arbeitnehmer ausgeführt, auf seinem computer. Ich denke die beste Sache wäre, für die Arbeiter, eine Funktion aufzurufen broker wenn Sie bereit zum senden der Ausgabe vom ausgeführten Befehl.
Ich würde gerne die Ausgabe vom Arbeiter asynchron, dann aktualisieren Sie die Webseite mit dem Ausgang, aber das ein anderes mal. Für jetzt würde ich nur gerne die Ausgabe vom Arbeiter.
Update
Jetzt habe ich eine HTTP-GET-request ausgelöst wird, die am Ende der Aufgabe, Benachrichtigung von der web-Anwendung, die Aufgabe ist getan - ich bin auch der Versand der task_id in der http-GET. Die http-Methode GET ruft django Ansicht, die erstellt AsyncResult und bekommt das Ergebnis, aber das problem ist, dass beim Aufruf Ergebnis.get() bekomme ich die folgende Fehlermeldung:
/usr/lib64/python2.6/site-packages/django_celery-2.5.1-py2.6.egg/djcelery/managers.py:178: TxIsolationWarning: Polling results with transaction isolation level repeatable-read within the same transaction may give outdated results. Be sure to commit the transaction for each poll iteration.
"Polling results with transaction isolation level"
Irgendwelche Ideen, warum? Ich bin nicht mit der Datenbank, denn ich bin mit rabbitmq mit AMQP.
Update.
Ich würde sehr gerne verwenden Dritte option, das scheint die beste option - für kleine und große Werte zurückgeben. Meine ganze Aufgabe sieht wie folgt aus:
class MyTask(Task):
def __call__(self, *args, **kwargs):
return self.run(*args, **kwargs)
def after_return(self, status, retval, task_id, args, kwargs, einfo):
if self.webhost is not None:
conn = httplib.HTTPConnection(self.webhost, self.webport)
conn.request("HEAD", "/vuln/task/output/"+task_id)
def run(self, args, webhost=None, webport=None):
self.webhost = webhost
self.webport = webport
r = "This is a basic result string used for code clarity"
return r
So, ich habe überschrieben, die after_return-Funktion, die sollte auch die Sperre auf meine Aufgabe, da die Aufgabe der Funktion run() bereits einen Wert zurückgegeben. In den HEAD-request, ich bin grundsätzlich Aufruf einer django-Funktion, die Anrufe AsyncResult auf task_id, die sollten mit dem Ergebnis der Aufgabe. Ich habe willkürliche Ergebnis für Testzwecke in meinem Fall, da es nur zum testen.
Ich würde gerne wissen, warum der obige code funktioniert nicht. Ich kann verwenden on_success, aber ich glaube nicht, dass es einen Unterschied machen wird - oder wird es?
- Könnte Sie speichern die Ausgabe des Befehls in die Datenbank ?
- Hi, Nein, weil die Arbeiter nicht haben, Zugang zu den Makler-Datenbank und noch tun, ich will, dass Sie Zugriff haben. Ich muss unbedingt zurück zu senden, ein Ergebnis und dann verarbeiten Sie in den broker.
- Vielleicht könnten Sie eine HTTP-API zurück zu senden, das Ergebnis ? Es gibt einige sehr einfache Möglichkeiten, das zu tun, Django.
- Ja, ich habe einen HTTP GET-Aufruf, sendet wieder eine ID. Dann die web-Anwendung sollte nur Lesen der Ausgabe der Aufgabe, aber es funktioniert nicht - ich habe aktualisiert mein Frage mit den Ergebnissen eines Ausfalls.
- Ich verstehe nicht, was Sie tun - Sie wusste nicht, poste deinen code. Aber wenn eine URL verwendet wird, zu speichern, dann sollte es definitiv nicht auf BEKOMMEN, das wäre gegen RFC2616. Betrachten POST.
- Können Sie erläutern, wie es nicht funktioniert?
- Sorry. Das problem ist das gleiche wie es vorher war, also kann es nicht das Ergebnis der Aufgabe " erste "Ergebnisse mit transaction isolation level" - Fehler.
- Ich habe ein sehr ähnliches problem, warum man dies nicht getan werden, mit dem Sellerie-Signal
task_postrun(task_id, task, args, kwargs, retval)
? Was bin ich über Signale (bitte)? Sind die Empfänger auch auf einen unbekannten Vorgang eher als Django?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn man sich hier finden Sie die folgenden:
Django-Sellerie verwendet MySQL den überblick zu behalten, Aufgaben/Ergebnisse, rabbit-mq ist als Kommunikations-bus im Grunde.
Was wirklich geschieht, ist, dass Sie versuchen zu Holen die
ASyncResult
des Arbeitnehmers, während der Vorgang noch ausgeführt wird (der task aufgerufen wird, eine HTTP-Anforderung an den server, und da er nicht zurückkehren, doch die db-locking-Sitzung vom Arbeiter ist immer noch aktiv und das Ergebnis der Zeile ist immer noch gesperrt). Wenn Django zu Lesen versucht den task-Ergebnis (seinen Zustand und den tatsächlichen Rückgabewert der ausführen-Funktion), findet er die Zeile gesperrt und die Probleme, die Sie eine Warnung.Gibt es ein paar Möglichkeiten zum beheben dieses:
Weiteren Sellerie Aufgabe zu ernten, das Ergebnis und die Kette die Sie um Ihre Bearbeitungsaufgabe. So original-Aufgabe fertig wird, die Sperre auf db und das neue wird es erworben haben, Lesen Sie das Resultat in django und tun, was immer Sie brauchen, es zu tun. Look-up-Sellerie-docs auf dieser.
Nicht stören, einfach einen POST zu Django full-Verarbeitung Ergebnis anbei als Nutzlast, anstatt zu versuchen, um es zu Holen über die db.
Überschreiben on_success in Ihrem task-Klasse und die POST-notification-Anfrage an Django dann, an welchem Punkt die Sperre aufgehoben werden soll, auf die db-Tabelle.
Beachten Sie, dass Sie benötigen, zu speichern, die ganze Verarbeitung, Ergebnis (egal wie groß es ist) in die Rückkehr der run-Methode (eventuell gebeizt). Sie hat nicht erwähnt, wie groß das Ergebnis sein kann, so mag es Sinn machen, eigentlich nur Szenario #2 oben (was ich auch tun würde). Alternativ würde ich mit #3. Vergessen Sie auch nicht behandeln on_failure-Methode als auch in Ihre Aufgabe.