2010-01-23 10 views
0

J'ai créé quelque chose sur Google App Engine qui sert de backend pour une application iPhone. Dans l'application, il y a des interactions qui sont poussées vers les réseaux sociaux via leurs API. Ainsi, le flux de travail typique est comme ceci:Google App Engine - comment gérez-vous une exception DatastoreTimeoutException?

  1. utilisateur utilise l'application iPhone pour faire "quelque chose"
  2. App App Engine est alerté via HTTP
  3. App Engine avertit réseau social que l'utilisateur a fait "quelque chose". Si l'utilisateur devait vérifier son profil sur ce réseau, son activité via l'application serait affichée. Donc, en ce qui concerne l'utilisateur, ce qu'ils ont probablement fait a fonctionné.
  4. App Engine doit effectuer une certaine persistance par lui-même, mais lorsqu'il essaie, une exception DatastoreTimeException est levée. Et maintenant les données sont dans un état funky.

Alors, quelle est une bonne façon de gérer cela? De par la nature du problème, j'aimerais l'intégrer dans une «transaction», mais il n'y a aucun moyen de réduire ce qui a été envoyé au réseau social. Donc, je pense plus à la façon dont vous gérez une DatastoreTimeException? Devrais-je simplement l'emballer dans un bloc d'essai et lui donner un autre coup? Est-ce une meilleure idée de montrer une erreur à l'utilisateur, puis quand il réessaye, "passez" l'interaction du réseau social pour qu'il ne soit pas expulsé deux fois? Y at-il une autre idée à laquelle je ne pense pas ici?

Répondre

0

http://code.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/DatastoreTimeoutException.html

« Cela peut se produire lorsque vous essayez de mettre, d'obtenir ou de supprimer trop d'entités ou une entité avec trop de propriétés, ou si le datastore est surchargé ou de la difficulté. »

Si l'exception est fréquente, j'imagine que c'est parce que l'opération de banque de données est trop importante, donc réessayer ne va pas vraiment aider. Si vous ne faites que coder défensivement contre le risque que l'exception soit lancée, vous pouvez l'essayer à nouveau (peut-être en mettant en file d'attente une tâche qui le fera.) Mais si vous ne pouvez pas accéder à la banque de données, tâche)

Si vous voulez être pare-balles robustes, et vous pouvez vous assurer que l'opération que vous effectuez sur le réseau social est idempotent (peut être répétée), puis:

  • Faire une note pour vous que vous devez effectuer l'opération de réseau social.
  • Si la note n'a pas pu être enregistrée, abandonnée et renvoyée.
  • Sinon, essayez le fonctionnement du réseau social.
  • En cas de succès, supprimez la note.
  • Avoir une sorte de tâche ou une boucle pour réessayer toutes les notes restantes à l'avenir.

Bien sûr, vous devez être un peu prudent sur le code de réponse que vous donnez au client iPhone, puisque le succès peut prendre un certain temps à long - plus longue que la durée de la demande faite par l'application iPhone. Ainsi, vous souhaitez que votre demande de moteur d'application soit également idempotente, et vous souhaiterez probablement une sorte d'annulation. Si tout ce que vous obtenez du réseau social est un succès ou un échec, et en cas de succès, l'opération ne doit pas être répétée, alors vous êtes en difficulté.C'est une API d'ordures à offrir sur le web, car le simple fait qu'un serveur web vous envoie une réponse réussie ne signifie pas que vous l'avez reçu, il n'y a donc aucun moyen pour l'appelant de savoir qu'il a réussi. . Mais ça arrive.

+0

En pratique, réessayer est souvent un succès; vous obtiendrez périodiquement des délais d'attente de banque de données, même pour les petites opérations. – geoffspear

+0

C'est ce que je veux dire - si cela a échoué parce que le magasin de données a piqué, puis réessayer est génial. Si cela a échoué parce que vos entités sont devenues trop grandes, alors réessayer ne fera que s'amortir pour toujours. En supposant que c'est un problème, la durée détermine si vous pouvez réessayer dans une simple boucle (avant que votre requête expire aussi), ou si vous avez besoin d'une tâche (car cela prendra plus d'une requête pour résoudre l'état funky)). Mais je n'ai pas d'expérience de cela sur le moteur de l'application. –

+0

L'objet a quelques propriétés - une chaîne, une longue, quelques dates et quelques entiers. Est-ce que cela pourrait être considéré comme "trop ​​grand" ou est-il sûr de parier que c'était un pépin (c'est la seule fois que je l'ai vu). – bpapa

0

Je trouve cette déclaration inquiétante: En pratique, réessayer est souvent couronnée de succès; vous obtiendrez périodiquement des délais d'attente de banque de données, même pour les petites opérations. - Wooble 23 janvier à 14:59

Comment GAE peut être pris au sérieux s'il a des problèmes de fiabilité? En général, trouvez-vous que le magasin de données est lent? Quelle est votre estimation de la fréquence de ces exceptions?

+0

Ceci n'est pas une réponse à la question – bpapa

0

Ceci est un problème fondamental avec tout système distribué. En général, il n'y a pas de solution facile à l'épreuve des balles. La meilleure option, si possible, est de s'assurer que l'une de vos opérations ou les deux sont idempotentes, c'est-à-dire que les exécuter plusieurs fois n'a aucun effet. Pour le datastore, c'est assez simple: si vous spécifiez un nom de clé, plusieurs puts se remplaceront par l'autre. Si c'est possible, vous devriez également utiliser l'idempotence dans votre API sociale, afin de pouvoir le ré-exécuter en toute sécurité en cas d'échec.