Dans l'API sur laquelle je travaille, il existe une opération de suppression en masse qui accepte un tableau d'ID:
["1000", ..., "2000"]
J'étais libre d'implémenter l'opération de suppression comme je l'entendais, j'ai donc décidé de rendre le tout transactionnel: c'est-à-dire que si un seul ID n'est pas valide, la demande entière échoue. J'appellerai cela le mode strict .
try{
savepoint = conn.setSavepoint();
for(id : IDs)
if( !deleteItem(id) ){
conn.rollback(savepoint);
sendHttp400AndBeDoneWithIt();
return;
}
conn.commit();
}
L'alternative (implémentée ailleurs dans notre suite logicielle) est de faire ce que nous pouvons dans le backend et de signaler les défaillances dans un tableau. Cette partie du logiciel traite moins de demandes, donc la réponse ne finit pas par être un tableau gigantesque ... en théorie.
Un bug récent survenu sur un serveur pauvre en ressources m'a fait revoir le code, et maintenant je remets en question ma décision initiale - mais cette fois, je suis davantage motivé par les besoins de l'entreprise que par les meilleures pratiques. Si, par exemple, j'échoue à la demande entière, l'utilisateur devra réessayer alors que si un certain nombre d'éléments sont supprimés, l'utilisateur peut terminer l'action puis demander à un administrateur de faire le reste (pendant que je travaille sur la correction du bogue !). Ce serait le mode permissif .
J'ai essayé de chercher en ligne des conseils sur la question, mais je suis venu les mains vides. Je viens donc à vous: qu'attend-on le plus des opérations en vrac de cette nature? Dois-je rester plus strict ou dois-je être plus permissif?
Réponses:
C'est correct de faire une version «stricte» ou «sympa» d'un point de terminaison de suppression, mais vous devez clairement dire à l'utilisateur ce qui s'est passé.
Nous effectuons une action de suppression avec ce point de terminaison. Probable
DELETE /resource/bulk/
ou quelque chose de similaire. Je ne suis pas pointilleux. Ce qui importe ici, c'est que peu importe si vous décidez d'être strict ou gentil, vous devez rapporter exactement ce qui s'est passé.Par exemple, une API avec laquelle je travaillais avait un
DELETE /v1/student/
point de terminaison qui acceptait les ID en bloc. Nous envoyions régulièrement la demande pendant les tests, obtenions une200
réponse et supposions que tout allait bien, pour découvrir plus tard que tout le monde sur la liste était toujours dans la base de données (défini sur inactif) ou pas réellement supprimé en raison d'une erreur qui foiré les appels futursGET /v1/student
parce que nous avons récupéré des données que nous n'attendions pas.La solution à cela est venue dans une mise à jour ultérieure qui a ajouté un corps à la réponse avec les identifiants qui n'ont pas été supprimés. Il s'agit - à ma connaissance - d'une sorte de meilleure pratique.
En fin de compte, peu importe ce que vous faites, assurez-vous de fournir un moyen de faire savoir à l'utilisateur final ce qui se passe et peut-être pourquoi cela se passe. IE, si nous choisissions un format strict, la réponse pourrait être
400 - DELETE failed on ID 1221 not found
. Si nous avons choisi une version «sympa», cela pourrait l'être207 - {message:"failed, some ids not deleted", failedids:{1221, 23432, 1224}}
(excusez mon pauvre formatage json).Bonne chance!
la source
207 Multi-Status
pourrait être approprié pour cette réponse d'échec partielleIl faut être strict et permissif.
Habituellement, les charges en vrac sont réparties en 2 phases:
Au cours de la phase de validation, chaque enregistrement est examiné strictement pour s'assurer qu'il répond aux exigences des spécifications des données. On peut facilement inspecter des dizaines de milliers d'enregistrements en quelques secondes. Les enregistrements valides sont placés dans un nouveau fichier à charger, les enregistrements invalides sont marqués et supprimés et généralement placés dans un fichier séparé (sauter le fichier). Une notification est ensuite envoyée sur les enregistrements dont la validation a échoué afin qu'ils puissent être inspectés et diagnostiqués à des fins de dépannage.
Une fois les données validées, elles sont ensuite chargées. Habituellement, il est chargé par lots s'il est suffisamment volumineux pour éviter les transactions de longue durée ou s'il y a une défaillance, il sera plus facile de récupérer. La taille du lot dépend de la taille de l'ensemble de données. Si l'on n'a que quelques 1000 enregistrements, un lot serait OK. Ici, vous pouvez être un peu permissif à l'égard des échecs, mais vous pouvez définir un seuil de lot échoué pour arrêter toute l'opération. Peut-être que si [N] lots échouaient, on arrêterait toute l'opération (si le serveur était en panne ou quelque chose de similaire). Habituellement, il n'y a pas d'échecs à ce stade car les données ont déjà été validées, mais s'il y avait des problèmes d'environnement ou autres, rechargez simplement le ou les lots qui ont échoué. Cela rend la récupération un peu plus facile.
la source
Il n'y a pas de réponse canonique à cela. Les besoins et les conséquences pour l'utilisateur doivent être examinés et les compromis évalués. L'OP a donné certaines des informations requises, mais voici comment je procéderais:
Question 1 : "Quelle est la conséquence pour l'utilisateur si une suppression individuelle échoue?"
La réponse devrait conduire le reste du comportement de conception / implémenté.
Si, comme l'indique le type OP, c'est simplement que l'utilisateur remarque l'exception et ouvre un ticket d'incident, mais qu'il n'est pas autrement affecté (les éléments non supprimés n'affectent pas les tâches suivantes), alors j'irais avec permissive avec une notification automatique à toi.
Si les suppressions échouées doivent être résolues avant que l'utilisateur puisse continuer, alors strict est clairement préférable.
Donner à l'utilisateur l'option (par exemple, essentiellement un indicateur ignorer les échecs avec le strict ou le permissif par défaut) peut être l'approche la plus conviviale.
Question 2 : «Y aurait-il des problèmes de cohérence / cohérence des données si des tâches ultérieures étaient effectuées avec des éléments non supprimés toujours dans le magasin de données?»
Encore une fois, la réponse conduirait à la meilleure conception / comportement. Oui -> Strict, Non -> Permissif, Peut-être -> Strict ou Sélectionné par l'utilisateur (en particulier si on peut compter sur l'utilisateur pour déterminer avec précision les conséquences).
la source
Je pense que cela dépend si vous voulez une évolutivité ou non. Si vous n'avez pas l'intention d'avoir beaucoup de pièces d'identité, cela ne devrait pas trop d'importance. Si vous avez l'intention d'avoir un million d'ID, ou mieux encore, si vous n'êtes pas absolument sûr que cela ne se produira pas, vous pouvez passer une heure à supprimer les ID juste pour le réinitialiser complètement en raison de 1 ID invalide.
la source
Je dirais qu'un point important ici est ce que cela signifie pour une masse de choses à supprimer.
Ces ID sont-ils en quelque sorte logiquement liés, ou s'agit-il simplement d'une commodité / performance - un regroupement par lots de ceux-ci?
En cas de connexion, même vaguement, je choisirais
strict
. Si c'est juste un mode batch (par exemple, l'utilisateur clique sur "enregistrer" pour ses dernières minutes de travail, et ce n'est qu'alors que le batch est transmis), alors j'irais pour lapermissive
version.Comme l'indique l'autre réponse: dans tous les cas, dites à "l'utilisateur" exactement ce qui s'est passé.
la source