Mise à jour et enregistrement de milliers d’objects à la fois sur Parse Server à l’aide de code cloud. Le code ne fonctionne pas pour plus de 2 objects. (Parse.Object.saveAll ())

Dans mon serveur d’parsing, j’ai une classe appelée Stats qui contient les colonnes secondsPlayed (number) et timeScore (number)

J’utilise le code en nuage pour mettre à jour toutes les lignes de la colonne timeScore

Le code ci-dessous ne fonctionne que lors de la mise à jour et de l’enregistrement de 1 ou 2 objects results.length . Si Parse.Query retourne plus de 2 résultats, le code se bloque et j’obtiens l’erreur suivante.

 error: Failed running cloud function timeScore for user undefined with: Input: {} Error: {"code":101,"message":"Object not found."} functionName=timeScore, code=101, message=Object not found., , user=undefined error: Error generating response. ParseError { code: 101, message: 'Object not found.' } code=101, message=Object not found. error: Object not found. code=101, message=Object not found. 

C’est un problème car j’ai besoin de mettre à jour et de sauvegarder des milliers d’objects. Quel est le meilleur moyen et le plus rapide de le faire?

Pourquoi mon code fonctionne-t-il pour 2 objects mais pas pour plus de 2? Comment puis-je réparer cela?

Voici mon code

  var _ = require("underscore"); Parse.Cloud.define("timeScore", function(request, response) { var query = new Parse.Query("Stats"); query.greaterThan("secondsPlayed", 1000); query.find().then(function(results) { _.each(results, function(result) { var secondsPlayed = result.get("secondsPlayed") || 0; result.set("timeScore", secondsPlayed*2); }); return Parse.Object.saveAll(results); }).then(function(results) { response.success(results); }, function(error) { response.error(error); }); }); 

Voici comment je l’appelle

 #!/usr/bin/env node var Parse = require("parse/node"); Parse.initialize("xx", "xx"); Parse.serverURL = "http://randomapp.herokuapp.com/parse"; Parse.Cloud.run('timeScore'); 

METTRE À JOUR:

Ci-dessous, mon dernier code. Tout fonctionne bien sauf le fait que j’obtiens l’erreur suivante sans raison apparente.

 heroku[router]: at=error code=H12 desc="Request timeout" method=POST path="/parse/functions/timeScore 

Je reçois l’erreur de dépassement de délai indépendamment de la taille de lot que je choisis et je l’obtiens toutes les 30 secondes. Je le reçois un total de 5 fois. Après la 5ème fois je ne l’obtiens plus. Je reçois la cinquième et dernière erreur au bout de 2,5 minutes environ (30 secondes * 5). Cette erreur n’a aucune incidence sur le processus. Tous les objects 250k sont mis à jour et enregistrés indépendamment de batchSize.

Je pensais que peut-être parce que je results.error jamais results.error ou results.success le serveur pensait que je travaillais toujours et montrait l’erreur. Cependant, j’ai mis à jour mon code comme suit et j’obtiens toujours les erreurs de dépassement de délai.

De plus, après chaque erreur de temporisation, processBatch () est appelée à nouveau depuis le début. Depuis que j’ai 5 erreurs de timeout, processBatch () est appelé 5 fois. Donc, après la 5ème erreur de timeout, 5 fonctions processBatch () s’exécutant simultanément (je l’ai confirmé avec les journaux).

Quelle est la cause des erreurs de timeout heroku que je reçois? Comment je le répare?

 var _ = require("underscore"); Parse.Cloud.define("timeScore", function(request, response) { var counter = 0; function processBatch(query, batchSize, startingAt, process) { query.limit(batchSize); query.skip(startingAt); return query.find().then(results => { return process(results).then(() => results.length); }).then(length => { return (length === batchSize)? processBatch(query, batchSize, startingAt+length, process) : {}; }); } function setTimeScores(stats) { console.log("LENGTH " + stats.length); _.each(stats, stat => { counter ++; stat.set("timeScore", counter); }); return Parse.Object.saveAll(stats); } var query = new Parse.Query("Stats"); processBatch(query, 2500, 0, setTimeScores).then(results => { response.success(results); }).catch(error => { response.error(error); }); }); 

Pour gérer un nombre d’objects supérieur à la limite de requête maximale, créez une fonction plus abstraite qui utilise limit() de requête et skip() pour faire défiler les données:

 function processBatch(query, batchSize, startingAt, process) { query.limit(batchSize); query.skip(startingAt); return query.find().then(results => { return process(results).then(() => results.length); }).then(length => { return (length === batchSize)? processBatch(query, batchSize, startingAt+length, process) : {}; }); } 

Ceci dit, obtenez un lot d’objects long, défini par query , puis faites quelque chose avec les objects récupérés, puis, s’il y en a plus, refait la même chose, en ignorant les objects déjà traités.

Votre étape de processus ressemble à ceci:

 function setTimeScores(stats) { _.each(stats, stat => { var secondsPlayed = stat.get("secondsPlayed") || 0; stat.set("timeScore", secondsPlayed*2); }); return Parse.Object.saveAll(stats); } 

Appelez ça comme ça:

 let query = new Parse.Query("Stats"); query.greaterThan("secondsPlayed", 1000); processBatch(query, 100, 0, setTimeScores); 

EDIT dans le contexte d’une fonction cloud, appelez-le comme ça …

 Parse.Cloud.define("computeStats", function(request, response) { let query = new Parse.Query("Stats"); query.greaterThan("secondsPlayed", 1000); processBatch(query, 100, 0, setTimeScores).then(results => { response.success(results); }).catch(error => { response.error(error); }); });