Utilisation de tables d'informations
Les tables d'informations sont stockées en mémoire sous la forme d'un objet unique dans le cache. C'est pourquoi, dans ThingWorx 8.5 et versions ultérieures, la manipulation directe de tables d'informations n'est pas prise en charge car elle peut entraîner des comportements inattendus et des problèmes de performances. Lorsque vous récupérez une propriété de table d'informations d'un objet, un objet proxy est créé, qui repasse à l'objet original. Les modifications directes n'auront lieu que dans la copie locale, mais les appels de fonction mettront à jour l'objet original. Si vous avez besoin d'un clonage complet de l'objet afin qu'aucune modification ne soit effectuée par proxy tant que toutes les données n'ont pas été mises à jour, utilisez l'option de clonage de la ressource. Dans les exemples ci-dessous, pour les tables d'informations à ligne unique, nous utilisons un objet wrapper, mais pour les tables d'informations à plusieurs lignes, nous utilisons l'option de clonage complet, car nous ne souhaitons pas mettre à jour chaque modification de ligne.
L'exemple suivant crée un objet proxy local (les appels de méthode mettent à jour l'objet original et sont enregistrés dans le cache) :
Things["data1"] recherche un objet "Data1" par son nom.
Things["data1"].info : la propriété de table d'informations "info" sur l'objet "Data1".
var myinfo = Things["data1"].info
L'exemple suivant crée un clone complet sans modification renvoyé par proxy à l'objet original :
var myinfo = Resources["InfoTableFunctions"].Clone({ t1: Things["data1"].info });
Dans ThingWorx 8.5 et versions ultérieures, les données de propriété sont traitées différemment que dans les versions précédentes. Toutes les données sont désormais stockées dans une couche de cache afin qu'elles puissent être utilisées localement ou à distance dans un environnement de clustering haute disponibilité. Dans les environnements précédents, les données stockées étaient modifiées directement. Dans la couche de mise en cache, les données doivent être déplacées dans et hors du cache au fur et à mesure de leur modification. Dans un environnement de clustering, le cache est distribué. Par conséquent, la latence du réseau supplémentaire et la sérialisation du fil augmentent le temps nécessaire au traitement de chaque demande.
Le stockage de grandes quantités de données dans une propriété en tant que table d'informations est désormais très coûteux et peut provoquer des pannes du système dans les environnements en cluster. La table d'informations est désormais entièrement lue et écrite dans la propriété lorsqu'elle est modifiée. Dans un environnement en cluster, l'objet complet est également sérialisé, désérialisé et envoyé sur le fil. Vous devez déplacer les tables volumineuses dans la base de données, et non les stocker dans une propriété unique. Elles peuvent être converties en tables définies par l'utilisateur ou placées dans une table de données.
Dans un environnement en grappe, Apache Ignite est utilisé. Le transfert d'objets volumineux peut entraîner l'indisponibilité d'Ignite. Ignite place en file d'attente les écritures et les sauvegardes. Lorsque des valeurs volumineuses sont transférées, leur gestion peut prendre du temps, ce qui peut entraîner du retard dans le traitement. Si la sauvegarde est volumineuse, les threads du système Ignite commencent à se bloquer, ce qui peut amener Ignite à arrêter un noeud en considérant qu'il ne répond pas. Les données peuvent devenir plus obsolètes.
Pour assurer le bon fonctionnement d'applications dans un environnement en cluster, il peut être nécessaire de les modifier pour réduire la taille des données stockées dans les propriétés. Ce problème de volume trop élevé est généralement causé par des tables d'informations comportant des milliers de lignes.
Exemple : tri de tables d'informations
Cet exemple fonctionnait avant l'ajout de la couche de mise en cache. Il permettait de mettre directement à jour la table en mémoire.
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
me.yourInfoTable.Sort(sort);
Toutefois, cette opération doit maintenant être effectuée comme suit :
Créez une table d'informations locale, effectuez vos modifications, puis réaffectez-la à la propriété de table d'informations de l'objet.
Cette opération extrait l'objet du cache et effectue une copie. Vous pouvez alors modifier la copie sans impact sur la propriété d'origine jusqu'à ce que le jeu soit terminé.
Si ce n'était pas le cas, chaque contact de table d'informations entraînerait l'écriture de l'ensemble de l'objet dans le cache, ce qui entraînerait une dégradation des performances.
var localInfoTable = me.yourInfoTable;
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
localInfoTable.Sort(sort);
me.yourInfoTable = localInfoTable;
Exemple : mise à jour de valeurs de champ pour les tables d'informations à une seule ligne
Mauvaise méthode :
Chaque ligne de ce script récupère l'ensemble de la table d'informations à partir du cache, modifie une valeur, puis la remet dans le cache. Les allers-retours vers le cache prennent du temps, car il traite l'ensemble de la table d'informations à chaque fois. Cette opération permet d'effectuer six appels au cache, ce qui, dans un système distant, peut sensiblement ralentir le script.
Things["data1"].info.v1 = 1;
Things["data1"].info.v2 = 2;
Things["data1"].info.v3 = 3;
Bonne méthode :
Cet exemple récupère un clone de la table d'informations à partir du cache, met à jour toutes les données localement, puis remet la table d'informations dans le cache. Il réduit les appels du cache à deux appels seulement.
var myinfo = Things["data1"].info
myinfo.v1 = 1
myinfo.v2 = 2
myinfo.v3 = 3
Things["data1"].info = myinfo
Exemple : mise à jour de valeurs de champ dans des tables d'informations à une seule ligne
Dans l'exemple ci-dessous, nous montrons que lorsqu'une table d'informations est affectée à une variable locale, il s'agit d'un clone. Les modifications apportées à l'objet original ne seront pas représentées dans la valeur clonée.
// creates a clone of InfoTable
var myinfo = Things["data1"].info;
// sets value of v1 to 5 in local InfoTable
myinfo.v1 = 5;
// change the orignal data1's v1 field value to 4, will not update the local value, it is still 5
Things["data1"].info.v1 = 4;
// assigning local info table to data2 so its v1 will have a value of 5
Things["data2"].info = myinfo;
Exemple : changement de comportement avec des tables d'informations à plusieurs lignes
Ci-dessous, vous pouvez constater que le clone de la table d'informations est toujours un objet proxy. Les méthodes appelées sur l'objet proxy prendront effet sur l'objet principal. Ce qui suit est conforme au proxy, mais diffère du comportement de ThingWorx 8.4. Dans ThingWorx 8.4, si nous faisions l'opération me.p2 = prop2, cela risquerait de rompre la référence à l'objet original. Ce n'est pas le cas dans ThingWorx 9 car ils sont traités comme le même objet proxy.
// An InfoTable local object for the "v1" field
var newEntry = new Object();
newEntry.v1 = 1;
// creates a proxy object from local object prop1 -> me.p1
var prop1 = me.p1;
prop1.v1=4;
// creates a proxy object from local object prop2 -> me.p2
var prop2 = me.p2;
prop2.v1=5;
// updates the me.p1 object, this breaks the proxy between prop1 -> me.p1
me.p1=prop2;
// prop2 reference is unchanged, still proxied
me.p2=prop2;
// this will not change me.p1 since the reference was broken when the object assignement to prop2 was done
prop1.AddRow(newEntry);
// this will update me.p2, the object reference is the same
prop2.AddRow(newEntry);
Exemple : génération d'une table d'informations à plusieurs lignes
Dans cet exemple, nous voulons ajouter des lignes à une table d'informations :
Mauvaise méthode :
Bien que cette opération semble correcte car elle utilise une méthode sur la base de données AddRow, elle communique en réalité cette modification par proxy à l'objet original pour chaque itération de la boucle. Cela entraîne l'écriture de la table d'informations dans le cache pour chaque itération de la boucle indésirable.
var myinfo = Things["data1"].info;
for (i=0; i < 10; i++) {
var row = new Object();
row.v1 = i;
row.v2 = i * 2;
row.v3 = i * 3;
myinfo.AddRow(row);
}
Things["data1"].info = myinfo;
Bonne méthode :
Dans cet exemple, nous avons cloné l'objet afin de pouvoir le manipuler sans aucun effet jusqu'à ce qu'il soit réaffecté à l'objet original.
var myinfo = Resources["InfoTableFunctions"].Clone({ t1: Things["data1"].info });
for (i=0; i < 10; i++) {
var row = new Object();
row.v1 = i;
row.v2 = i * 2;
row.v3 = i * 3;
myinfo.AddRow(row);
}
Things["data1"].info = myinfo;
L'exemple suivant fonctionne également. Etant donné que nous n'utilisons pas les méthodes d'objet proxy, l'objet original n'est pas modifié tant qu'il n'est pas affecté.
var myinfo = Things["data1"].info;
for (i=0; i < 10; i++) {
var row = new Object();
row.v1 = i;
row.v2 = i * 2* 10;
row.v3 = i * 3* 100;
myinfo.rows[i] = row;
}
Things["data1"].info = myinfo;
Est-ce que cela a été utile ?