Cet article vous montre comment combiner:
un script de code cloud (déclenché par un API post-hook)
une statistique usager (pour garder une trace de la dernière sauvegarde des données d'un utilisateur)
une collection d'entités personnalisées (pour les sauvegardes utilisateur)
pour créer un système de sauvegarde simple pour les données du compte utilisateur de votre application.
Notez que cette solution utilise des entités personnalisées et nécessite donc un abonnement brainCloud Plus. Consultez l'article lié pour savoir comment mettre à jour votre abonnement: https://help.getbraincloud.com/en/articles/3275913-changing-your-plan
Notez également que l'utilisation d'entités personnalisées entraîne des frais d'utilisation de données approfondies. Le coût de la sauvegarde des comptes joueurs varie en fonction de la quantité moyenne de données par joueur, du délai entre les sauvegardes et de la durée de conservation des sauvegardes. La bonne nouvelle est que cette approche ne sauvegarde que les comptes actifs - aucun espace de stockage n'est gaspillé pour les utilisateurs ayant quitté votre application.
---
Comment ça marche
Le script s'exécutera à chaque fois qu'un utilisateur s'authentifiera
Le script vérifiera quand les données de l'utilisateur ont été sauvegardées pour la dernière fois - et si cela remonte à plus de 24 heures - il exportera une copie des données de l'utilisateur et les stockera dans une entité personnalisée
Les sauvegardes des utilisateurs seront supprimées automatiquement après 30 jours
Avec ce système en place, il sera possible de visualiser les anciennes copies des données d'un utilisateur, ce qui sera utile pour déboguer et/ou récupérer le compte d'un utilisateur en cas de défaillance de l'application (ou de l'utilisateur) de quelque nature que ce soit.
Attention: la restauration des données sauvegardées est manuelle. Les développeurs devront copier-coller soigneusement les données dans les entités appropriées pour que l'utilisateur puisse restaurer son compte. Pour toute question, n'hésitez pas à contacter l'assistance brainCloud.
---
Mise en place
Nous créons le système en 5 étapes:
Créer le type
playerBackup
d'entité personnaliséeCréer la statistique usager
lastBackup
Créer le script de Cloud Code
authPosthook_backupPlayerAccount
Configurer le hook API
Tester
Étape 1: Créer le type d'entité personnalisée playerBackup
N'oubliez pas: vous devez disposer d'un forfait Plus pour les entités personnalisées.
Il est très important que cette solution utilise des entités personnalisées:
Les entités usager ne sont pas adaptées, car elles appartiennent à un utilisateur et seront supprimées si le compte utilisateur est supprimé (et ne protègent donc pas contre une suppression accidentelle de compte!). De plus, elles ne prennent pas en charge la durée de vie.
Les entités globales ne conviennent pas car elles sont destinées à des collections d'objets plus petites, généralement inférieures à 1 000. Elles ne s'adapteront pas aux niveaux dont vous avez besoin pour cette solution, où des milliers (voire des millions !) d'utilisateurs peuvent avoir plusieurs sauvegardes chacune sur une période de 30 jours.
Pour créer la collection d’entités personnalisées:
Accéder à Conception | Données Cloud | Entités personnalisées
Cliquez sur [+ Créer un type d'entité]
Entrez playerBackup pour le nom
Entrez l'identifiant pour l'identifiant
Assurez-vous que "Propriétaire" est défini sur "false". Ceci est important pour que la sauvegarde existe même si l'utilisateur est supprimé, et également pour que vos sauvegardes incluent d'autres sauvegardes ! "Migrate" doit également être défini sur "false".
Vous souhaiterez peut-être définir les notes sur les sauvegardes quotidiennes des joueurs actifs
Les autres valeurs peuvent être laissées telles quelles
Cliquez sur [Créer] pour créer la collection de types d'entités
Créez ensuite trois index pour faciliter la recherche:
Créer l'index profileId + saveDate
Définir le Nom sur
profileId_1_saveDate_1
Régler les Clés sur
{ "data.profileId": 1, "data.saveDate": 1 }
Créer le profileId + createdAt index
Définir le Nom sur
profileId_1_createdAt_min1
Régler les Clés sur
{ "data.profileId": 1, "createdAt": -1 }
Créer un e-mail facultatif + createdAt index
Définir le Nom sur
email_1_createdAt_min1
Régler les clés sur
{ "data.emailAddress": 1, "createdAt": -1 }
Définissez les options sur les paramètres JSON ci-dessous
{
"partialFilterExpression": {
"data.emailAddress": {
"$exists": true
}
}
}
---
Étape 2: Créer la dernière statistique usager de sauvegarde
Le script utilise une user statistic
pour enregistrer l'heure de la dernière sauvegarde en UTC millisecond
s. Veillez à ajuster la valeur maximale de cette statistique, car elle n'est pas suffisamment élevée pour nos besoins.
Dans le portail de conception:
Accéder à Conception | Règles statistiques | Statistiques usager
Cliquez sur le [+]
Entrez lastBackup comme nom
Entrez la sauvegarde pour la catégorie
Assurez-vous que le type est défini sur Long
Entrez
32503698000373
comme valeur maximale (cela vous amènera à l'année 3000!)Pour la description, indiquez l'heure en millisecondes de la dernière sauvegarde de l'utilisateur
Les autres valeurs peuvent être laissées telles quelles.
Cliquez sur [Enregistrer] pour créer la statistique
---
Étape 3: Créer le script de Cloud Code authPosthook_backupPlayerAccount
Passons maintenant au cœur de la solution. Le script exportera le compte du joueur et le stockera dans une entité personnalisée pour le protéger.
Avant d'effectuer l'exportation, le script vérifie d'abord quand la dernière sauvegarde a été effectuée. Si elle remonte à moins de 24 heures ( 86,400,000
en millisecondes), elle est ignorée. L'entité playerBackup est créée avec une durée de vie (TTL) de 30 jours (en 2,592,000,000
millisecondes), après quoi elle est automatiquement supprimée. Ces valeurs sont implémentées comme constantes dans le script et peuvent être ajustées selon les besoins de votre application.
Pour créer le script:
Accéder à Conception | Code Cloud | Scripts
Cliquez sur Actions | Créer un script
Entrez
authPostHook_backupPlayerAccount
comme nom de scriptEntrez Effectuer une sauvegarde quotidienne du lecteur comme description
Vous pouvez laisser le reste des valeurs par défaut telles quelles
Passez ensuite à l’onglet Éditeur et copiez-collez le code ci-dessous:
Cliquez sur [Enregistrer] pour enregistrer le script
"use strict";
function getFieldSafely( parentObject, fieldName, valueIfAbsent ) {
if (parentObject.hasOwnProperty(fieldName)) {
return parentObject[fieldName];
} else {
return valueIfAbsent;
}
}
function main() {
var response = {};
const BACKUP_INTERVAL = 86400000; // 24 hours
const TTL = 2592000000; // 30 days
const ENTITY_COLLECTION = "playerBackup";
const LAST_BACKUP_STAT = "lastBackup";
var message = data.message;
// Utiliser la réponse d'authentification (c'est-à-dire data.message)
// pour obtenir certaines des valeurs dont nous avons besoin
var currentTime = data.message.server_time;
var lastBackupMillis = getFieldSafely(
data.message.statistics, LAST_BACKUP_STAT, 0);
// Avons-nous besoin d'effectuer une sauvegarde?
if ( (currentTime - lastBackupMillis) < BACKUP_INTERVAL ) {
// Non. Quittez simplement plus tôt
message.backupMessage = "Skipping backup (recently backed up)";
response.status = 200;
response.data = message;
return response;
} else {
// Effectuer la sauvegarde
var customEntityProxy = bridge.getCustomEntityServiceProxy();
var playerStatisticsProxy =
bridge.getPlayerStatisticsServiceProxy();
var userProxy = bridge.getUserServiceProxy();
var optionsJson = { "includeEntities": true };
var profileId = data.message.profileId;
// Mettre à jour les statistiques avant d'exporter - pour éviter
// les problèmes de concurrence.
var stat_lastBackup = {};
stat_lastBackup[LAST_BACKUP_STAT] = "SET#"+currentTime;
playerStatisticsProxy.processStatistics(stat_lastBackup);
var userExport =
userProxy.sysGetUserExport(profileId, optionsJson);
if (userExport.status == 200) {
var saveDate = new Date().toISOString().slice(0, 10);
// Formater l'identifiant
var identifier = "";
var playerName = getFieldSafely(
data.message, "playerName", "" );
var emailAddress = getFieldSafely(
data.message, "emailAddress", null);
if ((playerName !== null) && (playerName !== "")) {
if ((emailAddress !== null) && (emailAddress !== "")) {
identifier = playerName +
" (" + emailAddress + ") - " + saveDate;
} else {
identifier = playerName +
" (" + profileId + ") - " + saveDate;
}
} else {
if ((emailAddress !== null) && (emailAddress !== "")) {
identifier = emailAddress + " - " + saveDate;
} else {
identifier = profileId + " - " + saveDate;
}
}
var dataJson = {
"profileId": profileId,
"saveDate" : saveDate,
"identifier": identifier,
"exportData": userExport.data
};
// Écrire l'adresse e-mail uniquement si elle est définie...
if ((emailAddress !== "") && (emailAddress !== null)) {
dataJson.emailAddress = emailAddress;
}
var backupResult =
customEntityProxy.createEntity(
ENTITY_COLLECTION, dataJson, {"other": 1}, TTL, false);
if (backupResult.status == 200) {
message.backupMessage = "new backup entity " +
backupResult.data.entityId +
" saved in custom entity collection " +
ENTITY_COLLECTION;
} else {
message.backupMessage =
"Unexpected error backing up player data";
message.backupResult = backupResult;
// Réinitialiser l'heure de lastBackup à ce qu'elle était précédemment
stat_lastBackup[LAST_BACKUP_STAT] = "SET#"+lastBackupMillis;
playerStatisticsProxy.processStatistics(stat_lastBackup);
}
} else {
message.backupMessage =
"Unexpected error exporting player data";
message.backupResult = userExport;
// Réinitialiser l'heure de lastBackup à ce qu'elle était précédemment
stat_lastBackup[LAST_BACKUP_STAT] = "SET#"+lastBackupMillis;
playerStatisticsProxy.processStatistics(stat_lastBackup);
}
response.status = 200;
response.data = message;
return response;
}
}
main();
---
Étape 4: Configurer un hook API pour appeler le script
Vous devez connecter ce script à l'appel d'authentification. Pour cela:
Accéder à Conception | Code Cloud | API Hooks
Cliquez sur [+ Créer]
Sélectionnez Authentifier pour le service
Sélectionnez Authentifier pour l'opération
Sélectionnez la publication pour pré/post
Sélectionner
authPostHook_backupPlayerAccount
pour le scriptSupprimer
"key": "value"
du champ Paramètres (laisser uniquement les accolades vides)Cliquez sur [Enregistrer]
---
Étape 5: Testez-le!
Nous devrions maintenant être tous prêts.
Accédez à l'explorateur d'API ( Conception | Code Cloud | Explorateur d'API ), sélectionnez le service d'authentification et l'opération d'authentification, puis cliquez sur [Exécuter] .
Vous devriez voir un nouveau champ "backupMessage" dans les résultats d'authentification qui indique qu'une sauvegarde des données du joueur a été créée.
Cliquez à nouveau sur [Exécuter] - et cette fois, le message indiquera que la sauvegarde a été ignorée - car une sauvegarde récente existe déjà.
---
Recherche de sauvegardes
Maintenant que les sauvegardes sont créées, comment les rechercher?
C'est assez simple:
Accéder à Surveillance | Surveillance globale | Entités personnalisées
Cliquez sur le type d'entité playerBackup
Cliquez sur le bouton [Filtre], puis saisissez une requête de filtre et cliquez sur [Appliquer]
Voici quelques exemples simples:
Rechercher toutes les sauvegardes pour un joueur donné (c'est-à-dire profileId):
{
"data.profileId": "aaa-bbb-ccc"
}
Rechercher des remplaçants pour un joueur spécifique à un jour spécifique:
{
"data.profileId": "aaa-bbb-ccc",
"data.saveDate": "2022-04-29"
}
Rechercher toutes les sauvegardes pour une adresse e-mail donnée:
{
"data.emailAddress": "bruce@waynetech.com",
"data.saveDate": "2022-04-29"
}
Remarque: vous pouvez bien sûr rechercher d'autres données de joueurs, mais assurez-vous de créer des index qui couvrent les domaines de votre recherche.
Si vous avez des questions, n'hésitez pas à contacter notre équipe d'assistance!