Gérez vos données en utilisant le versionnage, le listing et la mise en cache.
Versionnage
Le versionnage se produit lorsque vous définissez, mettez à jour et incrémentez des données. Les fonctions SetAsync(), UpdateAsync() et IncrementAsync() créent des sauvegardes versionnées de vos données en utilisant la première écriture de chaque clé dans chaque heure UTC. Les écritures successives sur une clé dans la même heure UTC écrasent définitivement les données précédentes.
Les sauvegardes versionnées expirent 30 jours après qu'une nouvelle écriture les remplace. La dernière version n'expire jamais.
Les fonctions suivantes effectuent des opérations de versionnage :
| Fonction | Description |
|---|---|
Liste toutes les versions pour une clé en retournant une instance de DataStoreVersionPages que vous pouvez utiliser pour énumérer tous les numéros de version. Vous pouvez filtrer les versions en utilisant une plage de temps. | |
Récupère une version spécifique d'une clé en utilisant le numéro de version de la clé. | |
Supprime une version spécifique d'une clé. Cette fonction crée également une version « tombstone » tout en conservant la version précédente. Par exemple, si vous appelez RemoveAsync("User_1234") puis que vous essayez d'appeler GetAsync("User_1234"), vous obtenez nil. Toutefois, vous pouvez toujours utiliser ListVersionsAsync() et GetVersionAsync() pour récupérer les anciennes versions des données. |
Vous pouvez utiliser le versionnage pour gérer les demandes des utilisateurs. Si un utilisateur signale qu'un problème s'est produit le 2020-10-09T01:42, vous pouvez revenir à une version précédente des données en utilisant l'exemple suivant :
local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local DATA_STORE_KEY = "User_1234"
local maxDate = DateTime.fromUniversalTime(2020, 10, 09, 01, 42)
-- Obtient la version la plus proche du temps donné
local listSuccess, pages = pcall(function()
return gameStore:ListVersionsAsync(DATA_STORE_KEY, Enum.SortDirection.Descending, nil, maxDate.UnixTimestampMillis)
end)
if listSuccess then
local items = pages:GetCurrentPage()
if #items > 0 then
-- Lit la version la plus proche
local closestEntry = items[1]
local success, value, info = pcall(function()
return gameStore:GetVersionAsync(DATA_STORE_KEY, closestEntry.Version)
end)
-- Restaure la valeur actuelle en la remplaçant par la version la plus proche
if success then
local setOptions = Instance.new("DataStoreSetOptions")
setOptions:SetMetadata(info:GetMetadata())
gameStore:SetAsync(DATA_STORE_KEY, value, nil, setOptions)
end
else
-- Aucune entrée trouvée
end
end
Instantanés
L'API Cloud ouverte des magasins de données Snapshot vous permet de prendre un instantané de tous les magasins de données d'un jeu une fois par jour. Avant de publier toute mise à jour de jeu qui modifie votre logique de stockage de données, assurez-vous de prendre un instantané. Prendre un instantané garantit que vous avez les données les plus récentes disponibles de la version précédente du jeu.
Par exemple, sans instantané, si vous publiez une mise à jour à 3h30 UTC qui cause une corruption de données, les données corrompues écrasent toutes les données écrites entre 3h00 et 3h30 UTC. Cependant, si vous prenez un instantané à 3h29 UTC, les données corrompues n'écrasent rien écrit avant 3h29 UTC, et les dernières données pour toutes les clés écrites entre 3h00 et 3h29 UTC sont préservées.
Listing et préfixes
Les magasins de données vous permettent de lister par préfixe. Par exemple, lister par les premiers n caractères d'un nom, comme "d", "do" ou "dog" pour toute clé ou magasin de données avec un préfixe de "dog".
Vous pouvez spécifier un préfixe lors de la liste de tous les magasins de données ou clés, et obtenir uniquement des objets qui correspondent à ce préfixe. Les fonctions ListDataStoresAsync() et ListKeysAsync() retournent un objet DataStoreListingPages que vous pouvez utiliser pour énumérer la liste.
| Fonction | Description |
|---|---|
| ListDataStoresAsync() | Liste tous les magasins de données. |
| ListKeysAsync() | Liste toutes les clés dans un magasin de données. |
Domaines
Vous pouvez organiser davantage les clés dans un magasin de données en définissant une chaîne unique comme domaine pour le deuxième paramètre de GetDataStore(). Le domaine par défaut (si aucun domaine n'est donné) est global. Le domaine est automatiquement ajouté au début de toutes les clés dans toutes les opérations effectuées sur le magasin de données.
| Clé | Domaine |
|---|---|
| houses/User_1234 | houses |
| pets/User_1234 | pets |
| inventory/User_1234 | inventory |
La combinaison du nom du magasin de données, du domaine et de la clé identifie de manière unique une clé. Les trois valeurs sont nécessaires pour identifier une clé avec un domaine. Par exemple, vous pouvez lire une clé de domaine global nommée User_1234 comme suit :
local DataStoreService = game:GetService("DataStoreService")
local inventoryStore = DataStoreService:GetDataStore("PlayerInventory")
local success, currentGold = pcall(function()
return inventoryStore:GetAsync("User_1234")
end)
Si la clé User_1234 a un domaine de gold, toutefois, vous ne pouvez la lire que comme suit :
local DataStoreService = game:GetService("DataStoreService")
local inventoryStore = DataStoreService:GetDataStore("PlayerInventory", "gold")
local success, currentGold = pcall(function()
return inventoryStore:GetAsync("User_1234")
end)
Propriété AllScopes
DataStoreOptions contient une propriété AllScopes qui vous permet de retourner des clés de tous les domaines dans une liste. Vous pouvez ensuite utiliser la propriété KeyName d'un élément de la liste pour des opérations courantes de magasin de données comme lire des données avec GetAsync() et supprimer des données avec RemoveAsync().
Lorsque vous utilisez la propriété AllScopes, le deuxième paramètre de GetDataStore() doit être une chaîne vide ("").
local DataStoreService = game:GetService("DataStoreService")local options = Instance.new("DataStoreOptions")options.AllScopes = truelocal ds = DataStoreService:GetDataStore("DS1", "", options)
Si vous activez la propriété AllScopes et créez une nouvelle clé dans le magasin de données, vous devez toujours spécifier un domaine pour cette clé au format domaine/nom_de_clé. Si vous ne le faites pas, les API renvoient une erreur. Par exemple, gold/player_34545 est acceptable avec gold comme domaine, mais player_34545 entraîne une erreur.
| global/K1 | house/K1 |
| global/L2 | house/L2 |
| global/M3 | house/M3 |
Mise en cache
Utilisez la mise en cache pour stocker temporairement des données provenant de magasins de données afin d'améliorer les performances et de réduire le nombre de demandes faites au serveur. Par exemple, un jeu peut mettre en cache une copie de ses données pour y accéder rapidement sans avoir à effectuer un nouvel appel au magasin de données.
La mise en cache s'applique aux modifications que vous apportez aux clés de magasin de données en utilisant :
- GetAsync() pour lire des données.
- SetAsync() pour créer des données.
GetVersionAsync(), ListVersionsAsync(), ListKeysAsync() et ListDataStoresAsync() n'implémentent pas de mise en cache et récupèrent toujours les dernières données du backend du service.
Par défaut, le moteur utilise GetAsync() pour stocker les valeurs que vous récupérez du backend dans un cache local pendant quatre secondes. De plus, par défaut, les demandes GetAsync() pour les clés mises en cache retournent la valeur mise en cache au lieu de continuer vers le backend. Vos demandes GetAsync() qui retournent une valeur mise en cache ne comptent pas dans vos limites de serveur et limites de débit.
Tous les appels GetAsync() qui récupèrent une valeur non mise en cache du backend mettent à jour le cache immédiatement et redémarrent le minuteur de quatre secondes.
Désactiver la mise en cache
Pour désactiver la mise en cache et ne pas utiliser le cache pour récupérer la valeur la plus à jour des serveurs, ajoutez le paramètre DataStoreGetOptions à votre appel GetAsync() et définissez la propriété UseCache sur false pour ignorer toutes les clés dans le cache.
Désactiver la mise en cache est utile si vous avez plusieurs serveurs écrivant sur une clé avec une grande fréquence et que vous devez obtenir la dernière valeur des serveurs. Cependant, cela peut vous amener à consommer plus de vos limites et quotas de magasins de données, car les demandes GetAsync() contournant la mise en cache comptent toujours pour vos limites de débit et de serveur.
Pour des lectures de vérification immédiates après une écriture, utilisez GetAsync() avec DataStoreGetOptions.UseCache = false. Par défaut, GetAsync() utilise un cache local de quatre secondes, donc une lecture de vérification normale peut retourner des données obsolètes.
Ceci est particulièrement important après des opérations d'écriture comme UpdateAsync(), SetAsync(), IncrementAsync() ou RemoveAsync() qui retournent une erreur. Dans ces cas, votre code doit déterminer s'il doit réessayer, rembourser ou prendre d'autres mesures correctives.
L'exemple suivant montre comment contourner le cache lors de la vérification du résultat d'une écriture :
local ok = pcall(function()
store:UpdateAsync(key, transform)
end)
if not ok then
local options = Instance.new("DataStoreGetOptions")
options.UseCache = false
local success, value = pcall(function()
return store:GetAsync(key, options)
end)
if success then
-- décider sur la base de l'état du backend, pas de l'état mis en cache
end
end
Sérialisation
Le DataStoreService stocke les données au format JSON. Lorsque vous enregistrez des données Luau dans Studio, Roblox utilise un processus appelé sérialisation pour convertir ces données en JSON afin de les enregistrer dans les magasins de données. Roblox convertit ensuite vos données de nouveau en Luau et vous les renvoie dans un autre processus appelé désérialisation.
La sérialisation et la désérialisation prennent en charge les types de données Luau suivants :
- Nombres
- Vous ne devez pas stocker les valeurs numériques spéciales inf, -inf et nan, car ces valeurs ne respectent pas les normes JSON. Vous ne pouvez pas accéder aux clés contenant ces valeurs avec Open Cloud.
- Tables
- Les tables ne doivent contenir que d'autres types de données pris en charge
- Les clés numériques sont traduites en chaînes si la longueur de la table est de 0
Si vous essayez de stocker un type de données que la sérialisation ne prend pas en charge, vous :
- Échouez à stocker ce type de données et obtenez un message d'erreur.
- Réussissez à stocker ce type de données en tant que nil.
Pour déboguer pourquoi votre type de données est stocké en tant que nil, vous pouvez utiliser la fonction JSONEncode. Lorsque vous passez votre type de données Luau à cette fonction, vous le recevez en retour au format que Roblox l'aurait stocké avec les magasins de données, ce qui vous permet de prévisualiser et d'examiner les données retournées.