From 4e91b28a66b629194a6b784343d4376ee4e8673b Mon Sep 17 00:00:00 2001 From: Jan Bols Date: Thu, 19 Jul 2018 10:36:18 +0200 Subject: [PATCH 1/4] Cache assets when finding them by tenant and name cfr the caching of devices. --- .../server/common/data/CacheConstants.java | 1 + .../server/dao/asset/AssetService.java | 2 +- .../server/dao/asset/BaseAssetService.java | 29 ++++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java b/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java index 88f76313f2..21de402721 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java @@ -19,4 +19,5 @@ public class CacheConstants { public static final String DEVICE_CREDENTIALS_CACHE = "deviceCredentials"; public static final String RELATIONS_CACHE = "relations"; public static final String DEVICE_CACHE = "devices"; + public static final String ASSET_CACHE = "assets"; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java index 6dc15c0017..e373f0e27a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java @@ -34,7 +34,7 @@ public interface AssetService { ListenableFuture findAssetByIdAsync(AssetId assetId); - Optional findAssetByTenantIdAndName(TenantId tenantId, String name); + Asset findAssetByTenantIdAndName(TenantId tenantId, String name); Asset saveAsset(Asset asset); diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java index 1eafb07442..6c8b60914e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java @@ -21,6 +21,10 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Customer; @@ -48,15 +52,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; +import static org.thingsboard.server.common.data.CacheConstants.ASSET_CACHE; import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; -import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; -import static org.thingsboard.server.dao.service.Validator.validatePageLink; -import static org.thingsboard.server.dao.service.Validator.validateString; +import static org.thingsboard.server.dao.service.Validator.*; @Service @Slf4j @@ -75,6 +76,9 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ @Autowired private CustomerDao customerDao; + @Autowired + private CacheManager cacheManager; + @Override public Asset findAssetById(AssetId assetId) { log.trace("Executing findAssetById [{}]", assetId); @@ -89,13 +93,16 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ return assetDao.findByIdAsync(assetId.getId()); } + @Cacheable(cacheNames = ASSET_CACHE, key = "{#tenantId, #name}") @Override - public Optional findAssetByTenantIdAndName(TenantId tenantId, String name) { + public Asset findAssetByTenantIdAndName(TenantId tenantId, String name) { log.trace("Executing findAssetByTenantIdAndName [{}][{}]", tenantId, name); validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - return assetDao.findAssetsByTenantIdAndName(tenantId.getId(), name); + return assetDao.findAssetsByTenantIdAndName(tenantId.getId(), name) + .orElse(null); } + @CacheEvict(cacheNames = ASSET_CACHE, key = "{#asset.tenantId, #asset.name}") @Override public Asset saveAsset(Asset asset) { log.trace("Executing saveAsset [{}]", asset); @@ -122,6 +129,14 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ log.trace("Executing deleteAsset [{}]", assetId); validateId(assetId, INCORRECT_ASSET_ID + assetId); deleteEntityRelations(assetId); + + Cache cache = cacheManager.getCache(ASSET_CACHE); + Asset asset = assetDao.findById(assetId.getId()); + List list = new ArrayList<>(); + list.add(asset.getTenantId()); + list.add(asset.getName()); + cache.evict(list); + assetDao.removeById(assetId.getId()); } From fb294561e6403c2afdace8f6629776057c8c72c6 Mon Sep 17 00:00:00 2001 From: Jan Bols Date: Thu, 19 Jul 2018 11:21:04 +0200 Subject: [PATCH 2/4] Cache assets when finding them by tenant and name cfr the caching of devices => add asset in cache directives of config files --- application/src/main/resources/thingsboard.yml | 3 +++ dao/src/test/resources/application-test.properties | 3 +++ 2 files changed, 6 insertions(+) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 2a2728dbb4..89dde0ae51 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -291,6 +291,9 @@ caffeine: devices: timeToLiveInMinutes: 1440 maxSize: 100000 + assets: + timeToLiveInMinutes: 1440 + maxSize: 100000 redis: # standalone or cluster diff --git a/dao/src/test/resources/application-test.properties b/dao/src/test/resources/application-test.properties index f2dab45491..20cf91c3dd 100644 --- a/dao/src/test/resources/application-test.properties +++ b/dao/src/test/resources/application-test.properties @@ -21,6 +21,9 @@ caffeine.specs.deviceCredentials.maxSize=100000 caffeine.specs.devices.timeToLiveInMinutes=1440 caffeine.specs.devices.maxSize=100000 +caffeine.specs.assets.timeToLiveInMinutes=1440 +caffeine.specs.assets.maxSize=100000 + caching.specs.devices.timeToLiveInMinutes=1440 caching.specs.devices.maxSize=100000 From 7c0087e6dfd95c791e5e4ce7f862d94088553a2a Mon Sep 17 00:00:00 2001 From: Jan Bols Date: Thu, 19 Jul 2018 18:27:22 +0200 Subject: [PATCH 3/4] Make RemoteToRuleChainTellNextMsg's parent class RuleNodeToRuleChainTellNextMsg Serializable. --- .../server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java | 2 +- .../actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java index fe0c2efae1..2dcd60af66 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java @@ -28,7 +28,7 @@ import java.io.Serializable; * Created by ashvayka on 19.03.18. */ @Data -final class RemoteToRuleChainTellNextMsg extends RuleNodeToRuleChainTellNextMsg implements TenantAwareMsg, RuleChainAwareMsg, Serializable { +final class RemoteToRuleChainTellNextMsg extends RuleNodeToRuleChainTellNextMsg implements TenantAwareMsg, RuleChainAwareMsg { private static final long serialVersionUID = 2459605482321657447L; private final TenantId tenantId; diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java index 9414892a98..9914463981 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java @@ -21,14 +21,16 @@ import org.thingsboard.server.common.msg.MsgType; import org.thingsboard.server.common.msg.TbActorMsg; import org.thingsboard.server.common.msg.TbMsg; +import java.io.Serializable; import java.util.Set; /** * Created by ashvayka on 19.03.18. */ @Data -class RuleNodeToRuleChainTellNextMsg implements TbActorMsg { +class RuleNodeToRuleChainTellNextMsg implements TbActorMsg, Serializable { + private static final long serialVersionUID = 4577026446412871820L; private final RuleNodeId originator; private final Set relationTypes; private final TbMsg msg; From 222e6fcfe6d56cffa067dde84c5676f8dc2ccb81 Mon Sep 17 00:00:00 2001 From: Mauro Cicolella Date: Fri, 27 Jul 2018 09:23:04 +0200 Subject: [PATCH 4/4] Update Italian translation --- ui/src/app/locale/locale.constant-it_IT.json | 86 ++++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/ui/src/app/locale/locale.constant-it_IT.json b/ui/src/app/locale/locale.constant-it_IT.json index e8f973b0c5..cdae11a4b9 100644 --- a/ui/src/app/locale/locale.constant-it_IT.json +++ b/ui/src/app/locale/locale.constant-it_IT.json @@ -498,25 +498,25 @@ "public-link": "Link pubblico", "copy-public-link": "Copia link pubblico", "public-link-copied-message": "Link pubblico della dashboard copiato negli appunti", - "manage-states": "Manage dashboard states", - "states": "Dashboard states", - "search-states": "Search dashboard states", - "selected-states": "{ count, plural, 1 {1 dashboard state} other {# dashboard states} } selected", - "edit-state": "Edit dashboard state", - "delete-state": "Delete dashboard state", - "add-state": "Add dashboard state", - "state": "Dashboard state", + "manage-states": "Gestisci stati dashboard", + "states": "Stati dashboard", + "search-states": "Ricerca stati dashboard", + "selected-states": "{ count, plural, 1 {1 stato dashboard selezionato} other {# stati dashboard selezionati} }", + "edit-state": "Modifica stato dashboard", + "delete-state": "Elimina stato dashboard", + "add-state": "Aggiungi stato dashboard", + "state": "Stato dashboard", "state-name": "Nome", - "state-name-required": "Dashboard state name is required.", - "state-id": "State Id", - "state-id-required": "Dashboard state id is required.", - "state-id-exists": "Dashboard state with the same id is already exists.", - "is-root-state": "Root state", - "delete-state-title": "Delete dashboard state", - "delete-state-text": "Are you sure you want delete dashboard state with name '{{stateName}}'?", + "state-name-required": "Nome stato dashboard obbligatorio.", + "state-id": "Id stato", + "state-id-required": "Id stato dashboard obbligatorio.", + "state-id-exists": "Uno stato della dashboard con lo stesso id è già presente.", + "is-root-state": "Stato radice", + "delete-state-title": "Elimina stato dashboard", + "delete-state-text": "Sei sicuro di voler eliminare lo stato della dashboard di nome '{{stateName}}'?", "show-details": "Mostra dettagli", "hide-details": "Nascondi dettagli", - "select-state": "Select target state", + "select-state": "Seleziona stato target", "state-controller": "Stato controller" }, "datakey": { @@ -570,7 +570,7 @@ "alias-required": "Alias dispositivo richesto.", "remove-alias": "Rimuovi alias dispositivo", "add-alias": "Aggiungi alias dispositivo", - "name-starts-with": "Dispositivo il cui nome comincia per", + "name-starts-with": "Dispositivo il cui nome inizia per", "device-list": "Lista dispositivi", "use-device-name-filter": "Usa filtro", "device-list-empty": "Nessun dispositivo selezionato.", @@ -680,7 +680,7 @@ "entity-list-empty": "Nessuna entità selezionata.", "entity-type-list-empty": "Nessun tipo di entità selezionato.", "entity-name-filter-required": "Filtro nome entità obbligatorio.", - "entity-name-filter-no-entity-matched": "No entities starting with '{{entity}}' were found.", + "entity-name-filter-no-entity-matched": "Nessuna entità che inizia per '{{entity}}' è stata trovata.", "all-subtypes": "Tutte", "select-entities": "Seleziona entità", "no-aliases-found": "Nessun alias trovato.", @@ -733,7 +733,7 @@ "type-rulechains": "Rule chains", "list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }", "rulechain-name-starts-with": "Rule chains whose names start with '{{prefix}}'", - "type-current-customer": "Current Customer", + "type-current-customer": "Cliente attuale", "search": "Ricerca entità", "selected-entities": "{ count, plural, 1 {1 entità selezionata} other {# entità selezionate} }", "entity-name": "Nome entità", @@ -788,13 +788,13 @@ "delete-extension-text": "Attenzione, dopo la conferma l'estensione e tutti i suoi data non saranno più recuperabili.", "delete-extensions-title": "Sei sicuro di voler eliminare { count, plural, 1 {1 estensione} other {# estensioni} }?", "delete-extensions-text": "Attenzione, dopo la conferma tutte le estensioni selezionate saranno eliminate.", - "converters": "Converters", - "converter-id": "Converter id", + "converters": "Convertitori", + "converter-id": "Id convertitore", "configuration": "Configurazione", - "converter-configurations": "Converter configurations", + "converter-configurations": "Configurazioni convertitore", "token": "Token di sicurezza", - "add-converter": "Add converter", - "add-config": "Add converter configuration", + "add-converter": "Aggiungi convertitore", + "add-config": "Aggiungi configurazione convertitore", "device-name-expression": "Device name expression", "device-type-expression": "Device type expression", "custom": "Custom", @@ -828,7 +828,7 @@ "drop-file": "Trascina un file o fai clic per selezionare un file da caricare.", "mapping": "Mapping", "topic-filter": "Filtro topic", - "converter-type": "Converter type", + "converter-type": "Tipo convertitore", "converter-json": "Json", "json-name-expression": "Device name json expression", "topic-name-expression": "Device name topic expression", @@ -847,10 +847,10 @@ "converter-json-required": "Convertitore json obbligatorio.", "converter-json-parse": "Unable to parse converter json.", "filter-expression": "Filter expression", - "connect-requests": "Connect requests", - "add-connect-request": "Add connect request", - "disconnect-requests": "Disconnect requests", - "add-disconnect-request": "Add disconnect request", + "connect-requests": "Richieste di connessione", + "add-connect-request": "Aggiungi richiesta di connessione", + "disconnect-requests": "Richieste di disconnessione", + "add-disconnect-request": "Aggiungi richiesta di disconnessione", "attribute-requests": "Attribute requests", "add-attribute-request": "Add attribute request", "attribute-updates": "Attribute updates", @@ -919,8 +919,8 @@ "not-available": "Non disponibile" }, - "export-extensions-configuration": "Export extensions configuration", - "import-extensions-configuration": "Import extensions configuration", + "export-extensions-configuration": "Esporta configurazione estensioni", + "import-extensions-configuration": "Importa configurazione estensioni", "import-extensions": "Importa estensione", "import-extension": "Importa estensione", "export-extension": "Esporta estensione", @@ -928,7 +928,7 @@ "invalid-file-error": "File estensione non valido" }, "fullscreen": { - "expand": "Expand to fullscreen", + "expand": "Espandi a tutto schermo", "exit": "Esci da schermo intero", "toggle": "Commuta modalità schermo intero", "fullscreen": "Schermo intero" @@ -937,16 +937,16 @@ "function": "Funzione" }, "grid": { - "delete-item-title": "Are you sure you want to delete this item?", - "delete-item-text": "Be careful, after the confirmation this item and all related data will become unrecoverable.", - "delete-items-title": "Are you sure you want to delete { count, plural, 1 {1 item} other {# items} }?", - "delete-items-action-title": "Delete { count, plural, 1 {1 item} other {# items} }", - "delete-items-text": "Be careful, after the confirmation all selected items will be removed and all related data will become unrecoverable.", - "add-item-text": "Add new item", - "no-items-text": "No items found", - "item-details": "Item details", - "delete-item": "Delete Item", - "delete-items": "Delete Items", + "delete-item-title": "Sei sicuro di voler eliminare questo elemento?", + "delete-item-text": "Attenzione, dopo la conferma questo elemento e tutti i suoi dati non saranno più recuperabili.", + "delete-items-title": "Sei sicuro di voler eliminare { count, plural, 1 {1 elemento} other {# elementi} }?", + "delete-items-action-title": "Elimina { count, plural, 1 {1 elemento} other {# elementi} }", + "delete-items-text": "Attenzione, dopo la conferma tutti gli elementi selezionati saranno rimossi e i relativi dati non saranno più recuperabili.", + "add-item-text": "Aggiungi nuovo elemento", + "no-items-text": "Nessun elemento trovato", + "item-details": "Dettagli elemento", + "delete-item": "Elimina elemento", + "delete-items": "Elimina elementi", "scroll-to-top": "Scroll to top" }, "help": { @@ -985,7 +985,7 @@ "settings": "Impostazioni layout", "color": "Colore", "main": "Main", - "right": "Right", + "right": "Destra", "select": "Select target layout" }, "legend": {