> 18. 9. 2016 v 12:19, Vladimír Macek <
ma...@sandbox.cz>:
>
> On 18.9.2016 00:04, Tomáš Ehrlich wrote:
>>> 17. 9. 2016 v 23:55, Vladimír Macek <
ma...@sandbox.cz>:
>>>
>>> Zdar,
>>>
>>> jak řešíte nepříjemné dvojité POSTy, kdy uživatel poklepe na submit?
>> Jestli je problém, je uživatel double clickne na submit, tak řešit přes JS? OnClick -> Disable?
>
> Ano, to bude první fáze řešení a určitě to zlepší UX, jak píšeš níže. Ale
> nejde na to spoléhat.
Spoléhat na to nejde, ale pokud to vyřeší 99,9% případů, tak bych to tak nechal. Museli by
se sejít dvě události zároveň, aby to nefungovalo:
1) Javascript nepojede (stránka ještě není načtená nebo javascript vypnutý globálně),
2) Uživatel double clickne
>
>
>>> V logu je něco takového:
>>>
>>> 2016-09-17T18:34:35+02:00 "POST /accounts/signup/ HTTP/1.1" 499 ...
>>> 2016-09-17T18:34:36+02:00 "POST /accounts/signup/ HTTP/1.1" 500 ...
>>>
>>> Tj. na první POST Django stihne uživatele zaregistrovat, ale nginx zjistí,
>>> že browser mezitím zavřel spojení (499) a čeká na spojení dalším. Tam ovšem
>>> zařve postgres, že uživatel s tímto e-mailem už existuje.
>>>
>>> Pořádné webové aplikaci by se podle mě tohle nemělo stát a druhému POSTu by
>>> měla vrátit to samé, co BY vrátila tomu prvnímu.
>> To se mi moc nezdá. Musel bys nějak identifikovat, že oba requesty přišly od stejného uživatele.
>
> Ano, řešitelné. Zatím uvažuju o middleware, který po každém commitu POSTu
> uloží do cache HttpResponse klíčovanou hashem request.POST dat + IP adresy
> + csrfcookie s timeoutem 2 sec. Na začátku POSTu by se do cache mrklo a
> kdyžtak response hned vrátí.
To mi právě vrtá hlavou. Pokud je to takový do očí bijící problém, proč ještě není vyřešený?
Django žije víc jak 10 let, to už si někdo musel všimnou…
>
>
>> Dokončí Django první request, když nginx vrátí 499? Nebo ho nginx “utne”?
>
> No to zatím jsem nevyřešil, proč druhý request skončí s IntegrityError a
> nikoli se reg. formem s chybou "Uživatel už existuje”.
Aha! Tak to je určitě podezřelé. Pamatuju si, že nám občas registrace taky vracela
IntegrityError. Bylo to spojení s přihlašováním přes facebook a stávalo se to
náhodně a jen občas. Nenašli jsme příčinu :(
>
> Díval jsem se do logu postgresu a celý signup skrz django-allauth proběhne
> v transakci. To je druhá záhada, když `ATOMIC_REQUESTS=False` a neobjevil
> jsem v té cestě `transaction.atomic`. Django nějak samo začne transakci
> před `SELECT` zjišťujícím, jestli už e-mail existuje a skončí jí až s
> vytvořením po vytvoření všech objektů vázaných na uživatele, jak to máme v
> aplikaci. Přitom normálně requesty do transakce nebalí.
To záleží na verzi. Dřív django balilo do transakce celé requesty, pak se to změnilo,
všechny operace jsou atomické a pokud chceš transakci, musíš si ji vynutit.
Nebo použiješ middleware, který celý request obalí do transakce a vrátíš tak
původní chování Djanga. Verzi si bohužel nepamatuju.
Co se stane, když nginx vrátí 499 a 500? Je uživatel v DB? Nebo tam není vůbec?
>
> Třeba někdo víte z hlavy.
>
> Dík,
>
> V.
>
> Chcete-li zobrazit tuto diskusi na webu, navštivte
https://groups.google.com/d/msgid/django-cs/6bfbd599-50ae-7540-6aef-c0e7e194902b%40sandbox.cz.