|
Regola scadenza voce cache
|
Descrizione
|
|---|---|
|
Mai
|
La voce nella cache non viene mai rimossa in base alla quantità di tempo trascorso al suo interno. Tuttavia, può comunque essere rimossa se la cache raggiunge la configurazione della dimensione massima o utilizzando il servizio DeleteEntry. L'impostazione Tempo di scadenza voce cache (secondi) viene ignorata quando è configurata la regola di scadenza Never.
|
|
Tempo di scadenza dall'ultimo accesso
|
La voce viene rimossa se non è stata letta entro il tempo di scadenza specificato.
|
|
Tempo di scadenza dalla creazione
|
La voce viene rimossa dopo che è trascorso il tempo specificato dalla sua creazione.
|
|
Tempo di scadenza dall'ultima modifica
|
La voce viene rimossa se non è stata modificata entro il tempo di scadenza specificato.
|
|
Tempo di scadenza dall'ultimo contatto
|
La voce viene rimossa se non vi è stato alcun accesso o modifica entro il tempo di scadenza specificato.
|
|
Nome servizio
|
Descrizione
|
|---|---|
|
PutEntry
|
• Aggiunge una voce alla cache.
• Valore di input - Infotable di una riga che utilizza la data shape configurata dell'oggetto CacheThing.
|
|
GetEntry
|
• Restituisce il risultato di una infotable di una riga dalla cache.
• Se la voce non viene trovata (mancato riscontro nella cache) e la cache non è configurata con Cache Performs Loading of Missing Entries, viene restituita una infotable vuota. Se la cache è configurata con tale opzione, viene chiamato automaticamente il servizio LoadEntry e viene restituito il risultato.
• Possono verificarsi mancati riscontri nella cache se la voce non è mai stata aggiunta alla cache, è stata rimossa o è scaduta.
• Valore di input - Infotable di una riga che utilizza la data shape configurata dell'oggetto CacheThing. È necessario completare solo i valori di Primary Key.
|
|
GetEntryByKey
|
• Restituisce il risultato di una infotable di una riga dalla cache.
• Se la voce non viene trovata, viene restituita una infotable vuota. Possono verificarsi mancati riscontri nella cache se la voce non è mai stata aggiunta alla cache, è stata rimossa o è scaduta.
• Valore di input - Stringa che rappresenta la chiave principale della voce da recuperare. Questo servizio è disponibile solo se la data shape configurata dispone di una sola chiave principale. È ideale per l'utilizzo con le chiavi principali di tipo stringa, ma supporta anche la maggior parte dei tipi con una conversione di stringa ben definita.
|
|
LoadEntry
|
• Consente di recuperare automaticamente i dati della cache dall'origine dati quando si verifica un mancato riscontro nella cache.
• Questo servizio deve essere sostituito se l'opzione Cache Performs Loading of Missing Entries è attivata.
|
|
DeleteEntry
|
• Elimina una voce dalla cache.
• In un ambiente ad alta disponibilità, influisce solo sul nodo in cui viene chiamato il servizio DeleteEntry.
• Valore di input - Infotable di una riga che utilizza la data shape configurata dell'oggetto CacheThing. È necessario completare solo i valori di Primary Key.
|
|
DeleteEntryByKey
|
• Elimina una voce dalla cache.
• In un ambiente ad alta disponibilità, influisce solo sul nodo in cui viene chiamato il servizio DeleteEntryByKey.
• Valore di input - Stringa che rappresenta la chiave principale della voce da recuperare. Questo servizio è disponibile solo se la data shape configurata dispone di una sola chiave principale.
|
|
PurgeCache
|
• Rimuove tutte le voci della cache.
• In un ambiente ad alta disponibilità, influisce solo sul nodo in cui viene chiamato il servizio PurgeCache.
|
|
GetDataShape
|
Restituisce la data shape configurata della cache.
|
|
SetDataShape
|
Imposta il campo della data shape nella tabella di configurazione della cache. La modifica di questo valore comporta l'eliminazione automatica del contenuto della cache.
|
|
GetEstimatedEntryCount
|
Restituisce il numero stimato di voci nella cache. Le operazioni PUT e DELETE in corso, così come i processi di scadenza o di rimozione, possono influire sulla precisione.
|
|
EstimateEntrySize
|
• Restituisce la dimensione stimata di una voce se fosse stata aggiunta alla cache. In questo modo, la voce non viene inserita nella cache e non sono necessarie altre voci già presenti al suo interno. Questo servizio può essere utile per stimare un valore appropriato di Dimensione massima cache (MB) o per impedire l'aggiunta di voci di grandi dimensioni alla cache.
• Valore di input - Infotable di una riga che utilizza la data shape configurata dell'oggetto CacheThing.
|
|
Metriche della cache
|
Descrizione
|
|---|---|
|
thingworx_cache_hit_rate
|
Rapporto tra le richieste di cache che hanno restituito una voce nella cache
|
|
thingworx_cache_hits
|
Numero di volte in cui i metodi di ricerca nella cache hanno restituito un valore memorizzato nella cache
|
|
thingworx_cache_request_count
|
Numero di volte in cui i metodi di ricerca nella cache hanno restituito un valore memorizzato o non memorizzato nella cache
|
|
thingworx_cache_miss_rate
|
Rapporto tra i metodi di ricerca nella cache che hanno restituito un valore non memorizzato nella cache (caricato di recente) o null
|
|
thingworx_cache_misses
|
Numero di volte in cui i metodi di ricerca nella cache hanno restituito un valore non memorizzato nella cache (caricato di recente) o null
|
|
thingworx_cache_eviction_count
|
Numero di volte in cui una voce è stata rimossa
|
|
thingworx_cache_average_load_penalty
|
Tempo medio impiegato per il caricamento di nuovi valori
|
|
thingworx_cache_weighted_size
|
Dimensione approssimativa corrente della cache in byte
|
|
thingworx_cache_max_weight
|
Dimensione massima della cache in byte prima della rimozione
|
|
thingworx_cache_estimated_entry_count
|
Numero stimato di voci nella cache
|
|
thingworx_cache_global_max_size
|
Dimensione massima globale configurata per tutte le cache in byte
|
// Input is x as a LONG
// Output is result as LONG
// MyTimesTwoCache CacheThing is configured with a DataShape with two fields:
// operand: (LONG, primaryKey)
// timesTwoValue: (LONG)
result = -1;
// Check the cache first, to see if we have already calculated x*2
// GetEntryByKey is a convenience method that takes the String value the configured DataShape's Primary Key ("key" in this example)
// cacheResult is an InfoTable with the DataShape of the cache
let cacheResult = Things["MyTimesTwoCache"].GetEntryByKey({ operand: x.toString() });
if (cacheResult.getRowCount() === 0) {
// Cache didn't have a result, so calculate it
let timesTwo = x*2;
// Put the result in the cache for the next time we need this multiple
// operand and value are from the Cache's configured DataShape
let cacheInput = getInfoTableForPut(x, timesTwo);
Things["MyTimesTwoCache"].PutEntry({
values: cacheInput
});
// Turn ScriptLogger to debug mode to see the logger messages
logger.debug("PutEntry the following entry into the MyTimesTwoCache: {operand: " + x + ", timesTwoValue: " + timesTwo + "}");
// Set the global result Output variable
result = timesTwo;
} else {
// If results are found, they are always in the first row of the InfoTable
let row = cacheResult.getRow(0);
logger.debug("Found the following entry already in MyTimesTwoCache: {operand: " + row.operand + ", timesTwoValue: " + row.timesTwoValue + "}");
result = row.timesTwoValue;
}
function getInfoTableForPut(operand, timesTwoValue) {
let infoTable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({
infoTableName: "InfoTable",
dataShapeName: Things["MyTimesTwoCache"].GetDataShape()
});
infoTable.AddRow({"operand": operand, "timesTwoValue ": timesTwoValue });
return infoTable;
}
/*
This Service queries QueryImplementingThingsV2 and caches the results as needed
Service Name: CachingQueryImplementingThingsV2 (Overridden on CacheThing)
Input: values InfoTable with Cached_QueryImplementingThingsV2_DataShape
Cached_QueryImplementingThingsV2_DataShape:
maxItems: NUMBER, Primary Key
nameMask: STRING, Primary Key
query: QUERY, Primary Key
isSortFirst: BOOLEAN, Primary Key
result: INFOTABLE, DataShape RootEntityListV2 (NOT a Primary Key!)
*/
let cacheEntryInfoTable = getCacheEntryInfoTable();
cacheEntryInfoTable.AddRow({
maxItems: maxItems /* NUMBER */,
nameMask: nameMask /* STRING */,
query: query /* QUERY */,
isSortFirst: isSortFirst /* BOOLEAN */
});
let getEntryResult = me.GetEntry({values: cacheEntryInfoTable});
if (getEntryResult.getRowCount() === 0) {
// Cache didn't have results, so call QueryImplementingThingsV2
let queryResult = ThingTemplates["GenericThing"].QueryImplementingThingsV2({
maxItems: maxItems /* NUMBER */,
nameMask: nameMask /* STRING */,
query: query /* QUERY */,
isSortFirst: isSortFirst /* BOOLEAN */
});
// Add the result to the cache, with the primaryKey parameters used to uniquely identify the query.
let newCacheEntryInfoTable = getCacheEntryInfoTable();
newCacheEntryInfoTable.AddRow({
maxItems: maxItems /* NUMBER */,
nameMask: nameMask /* STRING */,
query: query /* QUERY */,
isSortFirst: isSortFirst /* BOOLEAN */,
result: queryResult /* INFOTABLE */
});
me.PutEntry({
values: newCacheEntryInfoTable
});
logger.debug("Entry not found in Cache, retrieved from QueryImplementingThingsV2:" + queryResult.ToJSON());
result = queryResult;
} else {
logger.debug("Found entry from Cache:" + getEntryResult.ToJSON());
let row = getEntryResult.getRow(0);
result = row.result;
}
function getCacheEntryInfoTable() {
return Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({
infoTableName: "InfoTable",
dataShapeName: "Cached_QueryImplementingThingsV2_DataShape"
});
}
/*
This Service simply proxies a query to QueryImplementingThingsV2 for Read Through caching
Service Name: LoadEntry (Overridden on CacheThing)
Input: values InfoTable with Cached_QueryImplementingThingsV2_DataShape
Cached_QueryImplementingThingsV2_DataShape:
maxItems: NUMBER, Primary Key
nameMask: STRING, Primary Key
query: QUERY, Primary Key
isSortFirst: BOOLEAN, Primary Key
result: INFOTABLE, DataShape RootEntityListV2 (NOT a Primary Key!)
*/
let queryResult = ThingTemplates["GenericThing"].QueryImplementingThingsV2({
maxItems: values.maxItems /* NUMBER */,
nameMask: values.nameMask /* STRING */,
query: values.query /* QUERY */,
isSortFirst: values.isSortFirst /* BOOLEAN */
});
// Copy the results into a new InfoTable.
// This prevents some internal ThingWorx casting issues with some InfoTables
let resultTable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({
infoTableName: "InfoTable",
dataShapeName: me.GetDataShape() // Returns Cached_QueryImplementingThingsV2_DataShape
});
resultTable.AddRow({
maxItems: values.maxItems /* NUMBER {"defaultValue":500} */,
nameMask: values.nameMask /* STRING */,
query: values.query /* QUERY */,
isSortFirst: values.isSortFirst /* BOOLEAN */,
result: queryResult
});
let result = resultTable;
Questo servizio completa automaticamente i dati demo nell'oggetto DataTable nell'intervallo di date interrogato. |
/* Reads the Cached results of BetweenDatesDataTableQuery Service.
If Cache doesn't have the result, call BetweenDatesDataTableQuery and load results into Cache.
Service Name: CachingBetweenDatesDataTableQuery
Inputs: StartDate[DATETIME, required], EndDate[DATETIME, required]
Output: LONG
*/
// This example uses CacheThing.GetEntry, which requires a one-row infoTable populated with the CacheThing's DataShapes primaryKey getEntryByKey
let cacheEntryInfoTable = getCacheEntryInfoTable();
cacheEntryInfoTable.AddRow({"startDate": StartDate, "endDate": EndDate});
let getEntryResult = Things["CacheThingDemo"].GetEntry({
values: cacheEntryInfoTable
});
if (getEntryResult.getRowCount() === 0) {
// Cache didn't have results, so go to backing DataTable, by calling the BetweenDatesDataTableQuery Service
let queryResult = Things["CacheThingDemo"].BetweenDatesDataTableQuery({
StartDate: StartDate,
EndDate: EndDate
});
// Turn ScriptLogger to debug mode to see the logger messages
logger.debug("PutEntry called for BetweenDatesQueryCache: {StartDate: " + StartDate + ", EndDate: " + EndDate + " value: " + queryResult + "}");
if (!queryResult || queryResult < 0) {
// BetweenDatesDataTableQuery should always populate with demo data if no data is in the StartDate - EndDate range
throw new Error("BetweenDatesDataTableQuery did not return results");
}
let newCacheEntryInfoTable = getCacheEntryInfoTable();
newCacheEntryInfoTable.AddRow({"startDate": StartDate, "endDate": EndDate, "longValue": queryResult});
Things["CacheThingDemo"].PutEntry({
values: newCacheEntryInfoTable
});
result = queryResult;
} else {
let row = getEntryResult.getRow(0);
logger.debug("Found the following entry already in Cache : {StartDate: " + row.startDate + ", EndDate: " + row.endDate + ", LongValue: " + row.longValue + "}");
result = row.longValue;
}
function getCacheEntryInfoTable() {
return Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({
infoTableName: "InfoTable",
dataShapeName: "TimeSpanValueCacheDataShape"
});
}
/* This service queries a range of dates, based on the dateKey column, and returns the greatest longKey value found.
If there are no entries between StartDate and EndDate this Service dynamically populates demo data into demoDataTable, and returns that result.
Service Name: BetweenDatesDataTableQuery
Inputs: StartDate[DATETIME, required], EndDate[DATETIME, required]
Output: LONG
*/
if (StartDate >= EndDate) {
throw Error("StartDate must be before EndDate");
}
let dataTable = Things["DemoDataTable"];
let queryResult = queryGreatestLongKeyBetweenDates(dataTable, StartDate, EndDate);
if (queryResult.getRowCount() === 0) {
// If we don't get any results, first populate the date range with random values, then retry
// Turn ScriptLogger to debug mode to see the logger messages
logger.debug("No values found between [" + StartDate + "] and [" + EndDate + "], populating 100 demo values and re-querying");
populateDemoDataTable(dataTable, StartDate, EndDate);
// Re-query the now populated DateTable
queryResult = queryGreatestLongKeyBetweenDates(dataTable, StartDate, EndDate);
result = queryResult.getRow(0).get("longKey");
} else {
result = queryResult.getRow(0).get("longKey");
}
// Queries the DataTable for the largest longKey column value between the given dates
// Returns: One-row InfoTable with the found row.
function queryGreatestLongKeyBetweenDates(dateTable, startDate, endDate) {
let greatestBetweenDatesQuery = {
"filters": {
"type": "Between",
"fieldName": "dateKey",
"from": startDate,
"to": endDate
},
"sorts": [{
"fieldName": "longKey",
"isAscending": false
}]
};
// Run the Query to find the greatest Value Between Two Dates
let queryResult = dataTable.QueryDataTableEntries({
maxItems: 1,
query: greatestBetweenDatesQuery,
});
logger.debug("Queried between [" + StartDate + "] and [" + EndDate + "], found:" + queryResult.toJSON());
return queryResult;
}
function populateDemoDataTable(dataTable, startDate, endDate) {
// add 100 random entries between startDate and endDate
for (let entry = 0; entry < 100; entry++) {
let randomTimeBetween = randomDate(startDate, endDate);
let entry = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape({
infoTableName: "InfoTable",
dataShapeName: "TimeValueDataShape"
});
entry.AddRow({
"longKey": Math.floor(Math.random() * 1000),
"dateKey": randomTimeBetween
});
Things["DemoDataTable"].AddDataTableEntry({
values: entry /* INFOTABLE */ ,
});
}
}
function randomDate(startDate, endDate) {
let randomTime = Math.random() * (endDate.getTime() - startDate.getTime()) + startDate.getTime();
return new Date(randomTime);
}