2017-05-05 3 views
1

Ich arbeite derzeit an einem Django 1.11-Projekt, wo ich zwei Modelle Profil und Kampagne, die erste inline die zweite. Ich möchte eine asynchrone Funktion anwenden, wenn ich mein Profil speichere. Also mache ich eine Sellerieaufgabe.Django MySQL nicht den letzten Stand meiner db bekommen

# in admin.py 
class ProfileAdmin(admin.ModelAdmin): 
    # some stuff 

def save_related(self, request, form, formsets, change): 
     print(“before save: ” + str(len(campaigns))) 
     super(type(self), self).save_related(request, form, fomsets, change) 
     campaigns = Campaign.objects.filter(is_enabled=True) 
     print(“after save: ” + str(len(campaigns))) 
     tasks.foo.delay() 

# in tasks.py 
@shared_task 
def foo(): 
    campaigns = Campaign.objects.filter(is_enabled=True) 
    print(“Foo: ” + str(len(campaigns))) 

Mein Problem ist, dass die Länge der Kampagnen in Foo die Länge vor dem Speichern und nicht nach dem Drucken ist. Dieses Problem verschwindet, wenn ich am Anfang von foo einen Schlaf hinzufüge.

Beispiel Ausgabe:

before save: 5 
after save: 3 
Foo: 5 

Dieses Problem gibt es nur auf meiner Google-Instanz mit MySQL 5.7.

Ich verstehe nicht, warum die Kampagne in foo nicht immer korrekt ist. Ich finde keinen Grund, dieses Verhalten zu erklären.

Antwort

2

Der Code in save_related() wird innerhalb einer Transaktion aufgerufen. Das bedeutet, dass foo() innerhalb eines Worker-Prozesses ausgeführt werden kann, bevor die Transaktion im Hauptprozess abgeschlossen ist. Dies führt zu dem Verhalten, das Sie beobachtet haben, wenn die Aufgabe (die außerhalb der Transaktion liegt) die Änderungen an der Datenbank nicht sehen.

Es ist eine Race-Bedingung und kann nicht immer passieren. Es kann auf einigen Maschinen wahrscheinlicher als andere sein.

Eine einfache Lösung wäre, einen Countdown für die Aufgabe hinzuzufügen:

tasks.foo.delay(countdown=1) 
Verwandte Themen