Wenn Sie in meiner App auf eine Schaltfläche klicken, wird eine XHR-Anfrage an meinen Server gesendet, um ein Konto zu aktualisieren und den Benutzer zu belasten.

def upgradeView(request):
    if request.user.upgraded == False:
         billAccount(request.user.id)
    else: 
         return HttpRequests('Already billed')
    request.user.upgraded = True
    request.user.save()
    return HttpResponse('OK!')

Ich kann die Schaltfläche mit Javascript so ändern, dass sie deaktiviert wird, nachdem der Benutzer einmal darauf geklickt hat. Wie kann ich auf der Serverseite bestätigen, dass der Benutzer nicht 5 XHR-Anforderungen gleichzeitig senden kann und am Ende fünfmal in Rechnung gestellt wird? Ich überprüfe manuell, ob sie bereits in Rechnung gestellt wurden. Was ist jedoch, wenn die Funktion billAccount einige Sekunden dauert und mehrere Anforderungen den Aufruf billAccount auslösen können, bevor der Benutzer als aktualisiert festgelegt werden kann?

Je mehr ich darüber nachdenke, desto mehr scheint es unmöglich zu sein, das Einrutschen mehrerer Anforderungen zu verhindern. Selbst wenn der billAccount -Aufruf eine Millisekunde dauert, ist immer noch genug Zeit, um mehrere Anforderungen zu erhalten.

0
bones225 29 Aug. 2020 im 07:36

2 Antworten

Beste Antwort

Die Antwort verwendet select_for_update und transaction.atomic() für die pessimistische Sperrung und das Argument "no_wait". Dadurch wird verhindert, dass ein anderer Prozess dieses Objekt auswählt, wenn es gesperrt ist. Hier ist eine großartige Ressource, die weiter geht.

Ich glaube, Sie können die Zeile folgendermaßen sperren, damit nicht mehrere Transaktionen gleichzeitig ausgeführt werden können:

def upgradeView(request):
    with transaction.atomic():
        u = Users.objects.select_for_update(nowait=True).filter(pk=request.user.pk)
        if u.upgraded == False:
             billAccount(u.id)
        else: 
             return HttpRequests('Already billed')
        u.upgraded = True
        u.save()
        return HttpResponse('OK!')
0
bones225 2 Sept. 2020 im 02:07

Sie können ein weiteres Attribut hinzufügen, das beim Senden einer Anforderung auf True und vor dem Senden der Antwort auf False zurückgesetzt wird.
Abhängig vom Wert dieses Attributs entscheiden Sie, ob Sie eine Rechnungsanfrage stellen möchten oder nicht.

def upgradeView(request):
   if request.user.bill_state == 'open':
      # So there is a biliing request is running and we
   else:
      # set bill state to true to prevent any further requests
      request.user.bill_state = 'open'
      request.user.save()

   # make normal process of billing here an before end the request
   request.user.bill_state = 'close'
   request.user.save()

Ich denke, das Ändern einer Variablen von "Öffnen" in "Schließen" ist schneller als die Abrechnung und Sie können mehrere Anforderungen verhindern.

0
Ahmed Munir 29 Aug. 2020 im 04:59