Trattare un reclamo come una transazione, non un pulsante premere
La parte difficile è tutto dietro quel pulsante. Un cliente può inviare la stessa richiesta ripetutamente. Due server possono osservare lo stesso stato memorizzato. Una richiesta di datastore può fallire dopo una parte della logica di ricompensa è in esecuzione. Un giocatore può disconnettersi tra persistenza e presentazione. Se l'implementazione tratta ogni richiesta come permesso di concedere, duplicare valuta e oggetti sono un risultato atteso piuttosto che un bordo.
Il modello più sicuro è una transazione di proprietà del server. Il client chiede di rivendicare, ma non decide mai se una ricompensa è dovuta, ciò che la ricompensa contiene, o se la sovvenzione è riuscita. Il server deriva il periodo di ricompensa corrente, carica lo stato di profilo autorevole, convalida la ricompensa configurata, tenta una transizione dello stato atomico, e solo allora restituisce un risultato che il client può visualizzare.
Tale separazione è la regola centrale: l'interfaccia utente comunica l'intento; il server possiede l'ammissibilità e la mutazione.
Definire il più piccolo stato autorevole
I premi giornalieri non hanno bisogno di una storia di ogni interazione dell'interfaccia: hanno bisogno di uno stato sufficientemente durevole per rispondere a tre domande: quale periodo di ricompensa è stato commesso l'ultima volta, quale posizione di striscia segue da quello stato, e se la richiesta corrente può spostare lo stato in avanti.
Un profilo pratico di solito ha bisogno di una chiave di periodo stabile, di una chiave di ultima riuscita e di un valore di striscia. Il periodo chiave dovrebbe venire dal tempo del server e una politica di reset documentata. Se il prodotto si resetta a mezzanotte UTC, a un confine regionale configurato, o dopo una durata di rotolamento è una decisione del prodotto, ma la decisione deve essere deterministica sul server.
Tenere la configurazione separata dallo stato del giocatore. Il calendario configurato può definire identificatori di ricompensa, quantità, nomi di valuta, comportamento di striscia e date attive. Lo stato del giocatore dovrebbe fare riferimento a una versione di configurazione convalidata o un identificatore di ricompensa stabile piuttosto che copiare i carichi di pagamento arbitrari del cliente in archiviazione.
Convalida il telecomando prima di toccare lo storage
Roblox guida di sicurezza tratta ogni valore che attraversa il confine client-server come non attendibile. Per un reclamo quotidiano, la richiesta dovrebbe essere volutamente noiosa. In molti progetti il server non ha bisogno di ricompensa, numero di striscia, o indice di giorno dal client affatto; può derivare quei valori stessi.
Prima di iniziare il lavoro di datastore, il server dovrebbe applicare una piccola catena di rifiuto:
- confermare la richiesta arrivata sul server previsto RemoteEvent o RemoteFunction;
- respingere i tipi inaspettati, gli identificatori extra o i carichi di pagamento malformati;
- tasso-limite tentativi di rivendicazione per giocatore sul server;
- verificare il profilo del giocatore e la relativa configurazione delle funzionalità sono disponibili;
- rifiuta le richieste mentre un reclamo per quel giocatore è già in fase di elaborazione a livello locale.
Protegge la capacità del server e riduce gli abusi. La garanzia durevole deve ancora sopravvivere a due server, retries, ricollegamenti e riavviamenti di processo.
Rendere ammissibilità e impegno un aggiornamento atomico
Un `GetAsync()` seguito poi da `SetAsync()` lascia una finestra di gara. Due server possono leggere lo stesso stato non reclamato, entrambi decidono che il giocatore è idoneo, e entrambi scrivere una sovvenzione. Roblox documenti `UpdateAsync()` come l'operazione più sicura multi-server perché legge il valore attuale e richiama il callback quando gli aggiornamenti concomitanti conflitto.
Il callback riceve l'ultimo valore memorizzato, verifica se il periodo attuale è già stato commesso, e restituisce uno stato nuovo o `nil` per annullare. Il callback non deve cedere, quindi non deve chiamare servizi esterni, attendere per le istanze, o eseguire il riconoscimento visibile stesso.
Lo stato impegnato dovrebbe includere un marcatore di sovvenzione durevole: il periodo di ricompensa e l'identificatore di ricompensa stabile o chiave di transazione che ha vinto l'aggiornamento.
Questo modello converte le richieste ripetute in letture ripetute dello stesso risultato. La prima transizione valida vince.
Chiudere il divario tra la persistenza e la consegna dei premi
Lo stato del profilo atomico impedisce due transizioni di rivendicazione, ma il design ha ancora bisogno di un ordine di consegna chiaro. Se la valuta viene aggiunta prima che il marcatore di rivendicazione è durevole, un guasto del datastore può lasciare il valore concesso senza un record.
Commettere un identificatore di transazione e uno stato di consegna, quindi rendere la consegna di ricompensa sicuro da ripetere contro tale identificatore. Valuta, inventario, distintivo, o servizi di diritto dovrebbero riconoscere che una particolare transazione è già stata applicata. Un percorso di recupero può ispezionare record e riprovare senza creare una seconda ricompensa.
Non ogni esperienza ha bisogno di un registro complesso, ma ogni esperienza ha bisogno di una risposta esplicita alla domanda parziale. “La richiesta probabilmente finisce” non è una garanzia.
Conservare l'ordine di funzionamento durante i ritiri
Le chiamate di Datastore possono fallire, e LiveOps Goblin runtime Foundation utilizza un wrapper di datastore sicuro con il comportamento di riprovazione e di backoff.Ricerca non è la stessa di inviare nuovamente la stessa operazione da diversi compiti indipendenti. Roblox avverte che i retries ingenui possono riordinare operazioni statali.
Utilizzare un percorso di rivendicazione serializzato per giocatore, preservare l'ordine dei cambiamenti del profilo, e mantenere stabile l'identificatore di transazione attraverso i retries.Ricerca solo l'operazione fallita con backoff limitato. Non ricompense un nuovo periodo di ricompensa o chiave di transazione su ogni tentativo. Se il giocatore lascia, il recupero durevole dovrebbe essere in grado di continuare da stato memorizzato piuttosto che da una bandiera in memoria.
I sistemi diagnostici dovrebbero distinguere richieste rifiutate, limiti di tasso, avvisi di datastore, risultati già reclamati, reclami impegnati e recupero di consegna.Questi eventi sono prove operative; non devono esporre segreti o fabbricare attività quando nessun provider di analisi è configurato.
Tenere la configurazione sicura prima che raggiunga il gioco
LiveOps Goblin convalida quantità impossibili, chiavi di datastore mancanti, nomi di valute ambigue, codici duplicati e programmi scaduti prima di produrre una configurazione Roblox.
Una definizione di ricompensa dovrebbe utilizzare identificatori stabili, quantità limitate, obiettivi di valuta o di inventario noti, regole di pianificazione esplicite e una versione che può essere tracciata nella diagnostica. I calendari vuoti dovrebbero rimanere vuoti fino a quando un creatore aggiunge ricompense reali. I valori demo nella configurazione di produzione sono più pericolosi di uno stato vuoto onesto perché possono diventare mutazioni di economia reale.
Quando un calendario cambia, decidere cosa succede ai giocatori a metà strada. I identificatori di gratifica stabile e la configurazione versioned rendono questa politica testabile. Le ipotesi di posizione solo rendono facile per “il terzo giorno” fare riferimento a ricompense diverse prima e dopo un aggiornamento.
Testare i fallimenti, non solo il percorso felice
Una matrice di test utile giornaliera dovrebbe includere più di “richiedere una volta e ricevere le monete”.
- due richieste rapide dallo stesso cliente;
- richieste da due contesti server contro lo stesso profilo memorizzato;
- un reclamo per un periodo già impegnato;
- carichi remoti malformati e comportamento di tasso-limite;
- datastore conflitto, fallimento transitorio e percorsi di riprovazione esauriti;
- scollegare dopo impegno ma prima della conferma del cliente;
- riprova di consegna utilizzando lo stesso identificatore di transazione;
- un cambiamento di versione del calendario durante una striscia attiva;
- una configurazione di ricompensa mancante o non valida;
- analisi disabilitate con diagnostica ancora funzionante.
Il risultato atteso non è semplicemente “no crash”. Ogni test dovrebbe affermare lo stato durevole finale, il numero di sovvenzioni applicate, il risultato visibile dal cliente e l’evento diagnostico.
Una lista di controllo dell'implementazione concisa
Il design finale può essere rivisto con dieci domande. L'idoneità derivata sul server? È il tempo di ripristino deterministico? Il client invia solo l'intento? Le richieste remote sono convalidate e delimitate dal server? È la transizione di richiesta atomica? Lo stato memorizzato include un marcatore di transazione stabile? Può premiare la consegna essere ripetuto senza duplicazione?
Quando tutte le dieci risposte sono concrete, una ricompensa quotidiana smette di essere un fragile pulsante handler e diventa una piccola, comprensibile transazione LiveOps.








