Utilizzo delle infotable
Le infotable vengono memorizzate nella cache come oggetto singolo. Per questo motivo, la manipolazione diretta delle infotable non è supportata in ThingWorx 8.5 e versioni successive in quanto può causare problemi di prestazioni e comportamenti imprevisti. Quando si recupera una proprietà infotable da un oggetto, viene creato un oggetto proxy che rimanda all'oggetto originale. Le modifiche dirette si verificano solo per la copia locale e l'oggetto originale viene aggiornato con le chiamate di funzione. Se è necessario un clone completo dell'oggetto in modo che le modifiche non vengano inviate al proxy fino a quando non sono aggiornati tutti i dati, utilizzare l'opzione di clone della risorsa. Negli esempi riportati di seguito per le infotable a riga singola viene utilizzato un oggetto wrapper, mentre per le infotable a più righe viene utilizzata l'opzione di clone completo, in quanto non si ha necessità di aggiornare ogni modifica di riga.
L'esempio seguente crea un oggetto proxy locale (le chiamate al metodo aggiornano l'oggetto originale e salvano nella cache):
Things["data1"] cerca un oggetto "data1" per nome.
Things["data1"].info la proprietà infotable "info" dell'oggetto "data1"
var myinfo = Things["data1"].info
L'esempio seguente crea un clone completo e le modifiche non vengono inviate nuovamente al proxy nell'oggetto originale:
var myinfo = Resources["InfoTableFunctions"].Clone({ t1: Things["data1"].info });
I dati delle proprietà in ThingWorx 8.5 e versioni successive vengono trattati in modo diverso rispetto alle release precedenti. Tutti i dati vengono ora memorizzati in un livello della cache per consentirne l'utilizzo in locale o in remoto in un ambiente di clustering a disponibilità elevata. Negli ambienti precedenti i dati memorizzati vengono modificati direttamente, ma nel livello della cache devono essere spostati all'interno e all'esterno della cache man mano che vengono modificati. In un ambiente di clustering la cache è distribuita, pertanto l'ulteriore latenza di rete e la serializzazione dei cavi rallentano ogni singola richiesta effettuata.
La memorizzazione di grandi quantità di dati in una proprietà come infotable è diventata molto costosa e può causare arresti anomali del sistema negli ambienti cluster. Quando viene modificata, ora l'infotable viene completamente letta e scritta nella proprietà. In un ambiente cluster l'oggetto completo viene serializzato, deserializzato e inviato attraverso il cavo. Le infotable di grandi dimensioni devono essere spostate nel database, non memorizzate in una singola proprietà. Possono essere convertite in tabelle definite dall'utente o inserite in una tabella dati.
In un ambiente cluster viene utilizzato Apache Ignite. L'inserimento di oggetti di grandi dimensioni può rendere Ignite non dinamico. Ignite mette in coda le scritture e i backup e, quando vengono inseriti valori di grandi dimensioni, la relativa gestione può richiedere tempo e potrebbe verificarsi il back up dell'elaborazione. Se le dimensioni del backup sono estese, i thread di sistema Ignite iniziano a bloccarsi e questo può comportare la chiusura di un nodo da parte di Ignite, in quanto ritenuto non dinamico. I dati possono diventare sempre più obsoleti.
Per il corretto funzionamento delle applicazioni in un ambiente cluster, potrebbe essere necessario modificarle per ridurre la dimensione dei dati memorizzati nelle proprietà. Questa necessità si verifica in genere in presenza di infotable con migliaia di righe.
Esempio: ordinamento di infotable
Questo esempio era valido prima che venisse aggiunto il livello di memorizzazione nella cache. Aggiornava direttamente la tabella in memoria.
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
me.yourInfoTable.Sort(sort);
Questa operazione ora deve essere eseguita nel modo descritto di seguito.
Creare una infotable locale, apportare le modifiche, quindi assegnarla nuovamente alla proprietà infotable dell'oggetto.
In questo modo l'oggetto viene estratto dalla cache e ne viene creata una copia. La copia può quindi essere modificata senza impatto sulla proprietà originale finché l'insieme non viene completato.
Se ciò non dovesse accadere, ogni modifica alla infotable comporterebbe la riscrittura dell'intero oggetto nella cache, con conseguente peggioramento delle prestazioni.
var localInfoTable = me.yourInfoTable;
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
localInfoTable.Sort(sort);
me.yourInfoTable = localInfoTable;
Esempio: aggiornamento dei valori di campo per infotable a riga singola
Procedura errata:
Ogni riga di questo script estrae l'intera infotable dalla cache, modifica un valore e la inserisce nuovamente nella cache. I round trip nella cache richiedono tempo poiché ogni volta viene elaborata l'intera infotable. Qui vengono eseguite sei chiamate alla cache che, in un sistema remoto, possono rallentare notevolmente lo script.
Things["data1"].info.v1 = 1;
Things["data1"].info.v2 = 2;
Things["data1"].info.v3 = 3;
Procedura corretta:
In questo esempio si ottiene un clone della infotable dalla cache, i dati vengono tutti aggiornati in locale, quindi la infotable viene reinserita nella cache. Le chiamate alla cache vengono ridotte solo a due.
var myinfo = Things["data1"].info
myinfo.v1 = 1
myinfo.v2 = 2
myinfo.v3 = 3
Things["data1"].info = myinfo
Esempio: aggiornamento dei valori di campo per infotable a riga singola
Nell'esempio riportato di seguito viene mostrato come, quando una infotable viene assegnata a una variabile locale, si tratta di un clone. Le modifiche apportate all'oggetto originale non vengono rappresentate nel valore clonato.
// 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;
Esempio: modifica del comportamento con infotable a più righe
Come si può notare di seguito, il clone della infotable è comunque un oggetto proxy. I metodi richiamati per l'oggetto proxy hanno effetto sull'oggetto principale. Il seguente comportamento è coerente con il proxy, ma differisce da quello di ThingWorx 8.4. Se utilizzassimo me.p2 = prop2 in ThingWorx 8.4, verrebbe interrotto il riferimento all'oggetto originale. Ciò non accade in ThingWorx 9, poiché vengono conservati come lo stesso proxy dell'oggetto.
// 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);
Esempio: creazione di una infotable a più righe
In questo esempio vengono aggiunte righe a una infotable:
Procedura errata:
Sebbene sembri corretta perché utilizza un metodo nel database AddRow, di fatto comporta l'invio al proxy della modifica dell'oggetto originale per ogni iterazione del loop. In questo modo, la infotable viene scritta nella cache per ogni iterazione del loop ed è preferibile evitarlo.
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;
Procedura corretta:
In questo esempio l'oggetto viene clonato in modo da poterlo modificare senza ottenere effetti, se non dopo che è stato assegnato nuovamente all'oggetto originale.
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;
Funziona anche l'esempio che segue. Poiché non si utilizzano i metodi dell'oggetto proxy, l'oggetto originale non viene modificato finché non viene assegnato.
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;
È stato utile?