Passer au contenu principal
Toutes les collectionsQuestions générales
Sauvegarde des données de sauvegarde des utilisateurs dans des entités personnalisées
Sauvegarde des données de sauvegarde des utilisateurs dans des entités personnalisées

Un moyen simple de sauvegarder les comptes des joueurs au quotidien

Jason Liang avatar
Écrit par Jason Liang
Mis à jour il y a plus de 2 semaines

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:

  1. Créer le type playerBackup d'entité personnalisée

  2. Créer la statistique usager lastBackup

  3. Créer le script de Cloud Code authPosthook_backupPlayerAccount

  4. Configurer le hook API

  5. 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 milliseconds. 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,000en 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,000millisecondes), 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 script

  • Entrez 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 script

  • Supprimer "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!

Avez-vous trouvé la réponse à votre question ?