Trataţi o cerere ca o tranzacţie, nu o apăsare buton
O interfaţă zilnică-recompensă pare simplă: arată un calendar, evidenţiază astăzi şi lasă jucătorul să revendice. Partea dificilă este totul în spatele acelui buton. Un client poate trimite aceeaşi cerere în mod repetat. Două servere pot observa aceeaşi stare stocată. O cerere de magazin de date poate eşua după ce o parte din logica recompensei a rulat. Un jucător se poate deconecta între persistenţă şi prezentare. În cazul în care implementarea tratează fiecare cerere ca permisiunea de a acorda, valută duplicat şi elemente sunt un rezultat aşteptat mai degrabă decât un caz de margine.
Modelul mai sigur este o tranzacție deținută de server. Clientul cere să solicite, dar nu decide niciodată dacă o recompensă este datorată, ceea ce conține recompensa, sau dacă grantul a reușit. Serverul derivă perioada curentă de recompensă, încarcă starea de profil autoritar, validează recompensa configurată, încearcă o tranziție de stat atomic, și numai atunci returnează un rezultat pe care clientul îl poate afișa.
Această separare este regula centrală: interfața de utilizator comunică intenția; serverul deține eligibilitatea și mutația.
Defineşte cea mai mică stare de autoritate
Recompensele zilnice nu au nevoie de o istorie a fiecărei interacţiuni de interfaţă. Au nevoie de o stare suficient de durabilă pentru a răspunde la trei întrebări: care perioadă de recompensare a fost ultima comisă, ce poziţie dungă urmează de la acest stat, şi dacă cererea actuală poate muta statul înainte.
Un profil practic are nevoie, de obicei, de o cheie de perioadă stabilă, o cheie de ultimă instanță, și o valoare dungă. Cheia perioadei ar trebui să vină din timpul serverului și o politică documentată de resetare. Fie că produsul se resetează la miezul nopții UTC, la o limită regională configurată, sau după o durată de rulare este o decizie de produs, dar decizia trebuie să fie deterministă pe server. Ceasuri client nu ar trebui să determine eligibilitatea.
Menține configurația separată de starea jucătorului. Calendarul configurat poate defini identificatorii recompensei, cantitățile, numele monedei, comportamentul stream și datele active. Starea jucătorului ar trebui să se refere la o versiune validată de configurare sau la un identificator de recompensă stabil, în loc să copieze încărcăturile utile arbitrare ale clientului în depozit.
Validarea telecomenzii înainte de a atinge depozitul
Ghidul de securitate Roblox tratează fiecare valoare care traversează limita de client-server ca neîncredere. Pentru o cerere de zi cu zi, cererea ar trebui să fie în mod deliberat plictisitor. În multe modele serverul nu are nevoie de suma de recompensă, numărul streak, sau indicele de zi de la client, la toate; se poate obține aceste valori în sine.
Înainte de începerea lucrărilor magazinului de date, serverul ar trebui să aplice un mic lanț de respingere:
- confirma cererea ajunsa pe serverul destinat RemoteEveniment sau RemoteFunction;
- să respingă tipurile neașteptate, identificatorii suplimentari sau încărcăturile utile malformate;
- încercări de cerere cu limită de rată per jucător de pe server;
- verifică dacă profilul jucătorului și configurația caracteristicilor relevante sunt disponibile;
- refuza cererile în timp ce o cerere pentru acel jucător este deja procesată la nivel local.
Limitarea ratei nu este garanţia dublă-grant. Protejează capacitatea serverului şi reduce abuzul. Garanţia durabilă trebuie să supravieţuiască în continuare două servere, retries, reconectează, şi proces reporneşte.
Asigură eligibilitatea și angajamentul unei actualizări atomice
Un GETAsync () urmat mai târziu deSetAsync () părăsește o fereastră de cursă. Două servere pot citi același stat nerevendicat, ambele decid că jucătorul este eligibil, și ambele scriu un grant. Roblox documente
Pune decizia de eligibilitate în interiorul acestei actualizări atomice. Callback primește cea mai recentă valoare stocată, verifică dacă perioada curentă a fost deja angajată, și returnează fie un nou stat sau
Statul angajat ar trebui să includă un marker de grant durabil: perioada de recompensă și identificatorul de recompensă stabil sau cheia de tranzacție care a câștigat actualizarea. În cazul în care apelback descoperă că markerul există deja, rezultatul corect este deja revendicat, nu un alt grant.
Acest model transformă cererile repetate în lecturi repetate ale aceluiaşi rezultat. Primul câştig de tranziţie valid. Mai târziu, încercările de observare a markerului comis şi să devină no-op.
Apropierea decalajului dintre persistenţă şi livrarea recompensei
Starea profilului atomic previne două tranziții de cerere, dar design-ul încă mai are nevoie de un ordin de livrare clar. Dacă moneda este adăugată înainte ca markerul de cerere să fie durabil, o eroare a magazinului de date poate lăsa valoarea acordată fără înregistrare. În cazul în care markerul este stocat în primul rând și serverul se blochează înainte de livrare, jucătorul poate avea o cerere angajată fără elementul.
Răspunsul solid este un record de grant idempotent. Comite un identificator de tranzacție și un stat de livrare, apoi face recompensa livrare în condiții de siguranță pentru a repeta împotriva acestui identificator. Moneda, inventar, insigna, sau servicii de drepturi ar trebui să recunoască faptul că o anumită tranzacție a fost deja aplicată. O cale de recuperare poate inspecta înregistrările comise-dar-nelivrate și retrie-le fără a crea o a doua recompensă.
Nu orice experienţă are nevoie de un registru complex, dar fiecare experienţă are nevoie de un răspuns explicit la întrebarea parţial eşuată.
Păstrați ordinea de operare în timpul retries
Apelurile de la Datastore pot eșua, iar fundația LiveOps Goblin runtime folosește un ambalaj sigur de datestore cu retry and backoff comportamente. Retezarea nu este același lucru cu trimiterea aceleiași operații din nou din mai multe sarcini independente. Roblox avertizează că retările naive pot reordona operațiuni de stat.
Utilizați o cale de cerere serializată pe jucător, păstrați ordinea de modificări de profil, și păstrați identificatorul de tranzacție stabil peste retries. Retrie numai operațiunea eșuată cu backoff delimitată. Nu recalculați o nouă perioadă de recompensă sau tasta de tranzacție pe fiecare încercare. Dacă jucătorul pleacă, recuperarea durabilă ar trebui să poată continua de la starea stocată, mai degrabă decât de la un steag în memorie.
Diagnosticul ar trebui să facă distincţia între cererile respinse, limitele ratei, avertismentele de la magazinul de date, rezultatele deja revendicate, cererile angajate şi recuperarea livrării. Aceste evenimente sunt dovezi operaţionale; acestea nu ar trebui să expună secrete sau să fabrice activităţi atunci când nu este configurat nici un furnizor de analiză.
Păstrați configurația în siguranță înainte de a ajunge la joc
Protecţia duplicată este slăbită atunci când calendarul de recompensă exportat în sine este ambiguu. LiveOps Goblin validează cantităţi imposibile, lipsesc tastele magazinului de date, nume de monede ambigue, coduri duplicate şi orare expirate înainte de a produce o versiune Roblox.
O definiţie a recompensei ar trebui să utilizeze identificatori stabili, cantităţi limitate, ţinte cunoscute în valută sau inventar, reguli explicite ale programului şi o versiune care poate fi urmărită în diagnostice. Calendarele goale ar trebui să rămână goale până când un creator adaugă recompense reale. Valorile demo în configuraţia de producţie sunt mai periculoase decât o stare goală sinceră, deoarece acestea pot deveni mutaţii ale economiei reale.
Atunci când un calendar se schimbă, decide ce se întâmplă cu jucătorii mijlocul-streak. identificatori de recompensă stabilă și configurația modificată face această politică testabilă. Ipotezele doar poziția face mai ușor pentru trei zile de a face referire la diferite recompense înainte și după o actualizare.
Testaţi eşecurile, nu numai calea fericită.
O matrice utilă de testare zilnică a recompensei ar trebui să includă mai mult decât revendicare o dată și să primească monede.
- două cereri rapide din partea aceluiași client;
- cereri din două contexte de servere contra aceluiași profil stocat;
- o cerere pentru o perioadă deja angajată;
- sarcini utile la distanță și comportamente cu limită de rată malformate;
- Conflictul magazinului de date, eșecul tranzitoriu și căile de rejudecare epuizate;
- se deconectează după angajament, dar înainte de confirmarea clientului;
- reincercarea de livrare folosind acelasi identificator de tranzactie;
- o modificare a versiunii calendarului în timpul unei dungi active;
- o configurație a recompensei lipsă sau invalidă;
- Analytics dezactivate cu diagnostice încă funcţionează.
Rezultatul aşteptat nu este doar "niciun accident." bază Fiecare test trebuie să afirme starea finală durabilă, numărul de subvenţii aplicate, rezultatul vizibil al clientului şi evenimentul diagnostic.
O listă concisă de punere în aplicare
Design-ul final poate fi revizuit cu zece întrebări. Este eligibilitatea derivată pe server? Este timpul de resetare determinist? Are clientul trimite doar intenția? Sunt cererile la distanță validate și-rata de server-limitată? Este cererea de tranziție atomică? Starea stocată include un marker de tranzacție stabil? Poate recompensa livrarea să fie repetată fără suprapunere? Retările păstrează ordinea? Configurațiile sunt modificate și validate? Testele de convailitate și de eșec parțial se dovedesc a fi exact un grant durabil?
Când toate cele zece răspunsuri sunt concrete, o recompensă zilnică încetează să mai fie un handler fragil și devine o tranzacție LiveOps mică, ușor de înțeles.








