Commit c7df356fb7cc4780b6ca72a22722798bf6028410

Authored by vzikratyi
Committed by Andrew Shvayka
1 parent ab76d81c

Wrapped attr cache requests, fixed bug

  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.attributes;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  20 +import org.springframework.cache.Cache;
  21 +import org.springframework.cache.CacheManager;
  22 +import org.springframework.context.annotation.Primary;
  23 +import org.springframework.stereotype.Service;
  24 +import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  25 +
  26 +import static org.thingsboard.server.common.data.CacheConstants.ATTRIBUTES_CACHE;
  27 +
  28 +@Service
  29 +@ConditionalOnProperty(prefix = "cache.attributes", value = "enabled", havingValue = "true")
  30 +@Primary
  31 +@Slf4j
  32 +public class AttributesCacheWrapper {
  33 + private final Cache attributesCache;
  34 +
  35 + public AttributesCacheWrapper(CacheManager cacheManager) {
  36 + this.attributesCache = cacheManager.getCache(ATTRIBUTES_CACHE);
  37 + }
  38 +
  39 + public Cache.ValueWrapper get(AttributeCacheKey attributeCacheKey) {
  40 + try {
  41 + return attributesCache.get(attributeCacheKey);
  42 + } catch (Exception e) {
  43 + log.debug("Failed to retrieve element from cache for key {}. Reason - {}.", attributeCacheKey, e.getMessage());
  44 + return null;
  45 + }
  46 + }
  47 +
  48 + public void put(AttributeCacheKey attributeCacheKey, AttributeKvEntry attributeKvEntry) {
  49 + try {
  50 + attributesCache.put(attributeCacheKey, attributeKvEntry);
  51 + } catch (Exception e) {
  52 + log.debug("Failed to put element from cache for key {}. Reason - {}.", attributeCacheKey, e.getMessage());
  53 + }
  54 + }
  55 +
  56 + public void evict(AttributeCacheKey attributeCacheKey) {
  57 + try {
  58 + attributesCache.evict(attributeCacheKey);
  59 + } catch (Exception e) {
  60 + log.debug("Failed to evict element from cache for key {}. Reason - {}.", attributeCacheKey, e.getMessage());
  61 + }
  62 + }
  63 +}
@@ -56,16 +56,15 @@ public class CachedAttributesService implements AttributesService { @@ -56,16 +56,15 @@ public class CachedAttributesService implements AttributesService {
56 private static final String STATS_NAME = "attributes.cache"; 56 private static final String STATS_NAME = "attributes.cache";
57 57
58 private final AttributesDao attributesDao; 58 private final AttributesDao attributesDao;
59 - private final Cache attributesCache;  
60 - 59 + private final AttributesCacheWrapper cacheWrapper;
61 private final DefaultCounter hitCounter; 60 private final DefaultCounter hitCounter;
62 private final DefaultCounter missCounter; 61 private final DefaultCounter missCounter;
63 62
64 public CachedAttributesService(AttributesDao attributesDao, 63 public CachedAttributesService(AttributesDao attributesDao,
65 - CacheManager cacheManager, 64 + AttributesCacheWrapper cacheWrapper,
66 StatsFactory statsFactory) { 65 StatsFactory statsFactory) {
67 this.attributesDao = attributesDao; 66 this.attributesDao = attributesDao;
68 - this.attributesCache = cacheManager.getCache(ATTRIBUTES_CACHE); 67 + this.cacheWrapper = cacheWrapper;
69 68
70 this.hitCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "hit"); 69 this.hitCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "hit");
71 this.missCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "miss"); 70 this.missCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "miss");
@@ -77,7 +76,7 @@ public class CachedAttributesService implements AttributesService { @@ -77,7 +76,7 @@ public class CachedAttributesService implements AttributesService {
77 Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey); 76 Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey);
78 77
79 AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey); 78 AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey);
80 - Cache.ValueWrapper cachedAttributeValue = attributesCache.get(attributeCacheKey); 79 + Cache.ValueWrapper cachedAttributeValue = cacheWrapper.get(attributeCacheKey);
81 if (cachedAttributeValue != null) { 80 if (cachedAttributeValue != null) {
82 hitCounter.increment(); 81 hitCounter.increment();
83 AttributeKvEntry cachedAttributeKvEntry = (AttributeKvEntry) cachedAttributeValue.get(); 82 AttributeKvEntry cachedAttributeKvEntry = (AttributeKvEntry) cachedAttributeValue.get();
@@ -87,7 +86,7 @@ public class CachedAttributesService implements AttributesService { @@ -87,7 +86,7 @@ public class CachedAttributesService implements AttributesService {
87 ListenableFuture<Optional<AttributeKvEntry>> result = attributesDao.find(tenantId, entityId, scope, attributeKey); 86 ListenableFuture<Optional<AttributeKvEntry>> result = attributesDao.find(tenantId, entityId, scope, attributeKey);
88 return Futures.transform(result, foundAttrKvEntry -> { 87 return Futures.transform(result, foundAttrKvEntry -> {
89 // TODO: think if it's a good idea to store 'empty' attributes 88 // TODO: think if it's a good idea to store 'empty' attributes
90 - attributesCache.put(attributeKey, foundAttrKvEntry.orElse(null)); 89 + cacheWrapper.put(attributeCacheKey, foundAttrKvEntry.orElse(null));
91 return foundAttrKvEntry; 90 return foundAttrKvEntry;
92 }, MoreExecutors.directExecutor()); 91 }, MoreExecutors.directExecutor());
93 } 92 }
@@ -119,7 +118,7 @@ public class CachedAttributesService implements AttributesService { @@ -119,7 +118,7 @@ public class CachedAttributesService implements AttributesService {
119 private Map<String, Cache.ValueWrapper> findCachedAttributes(EntityId entityId, String scope, Collection<String> attributeKeys) { 118 private Map<String, Cache.ValueWrapper> findCachedAttributes(EntityId entityId, String scope, Collection<String> attributeKeys) {
120 Map<String, Cache.ValueWrapper> cachedAttributes = new HashMap<>(); 119 Map<String, Cache.ValueWrapper> cachedAttributes = new HashMap<>();
121 for (String attributeKey : attributeKeys) { 120 for (String attributeKey : attributeKeys) {
122 - Cache.ValueWrapper cachedAttributeValue = attributesCache.get(new AttributeCacheKey(scope, entityId, attributeKey)); 121 + Cache.ValueWrapper cachedAttributeValue = cacheWrapper.get(new AttributeCacheKey(scope, entityId, attributeKey));
123 if (cachedAttributeValue != null) { 122 if (cachedAttributeValue != null) {
124 hitCounter.increment(); 123 hitCounter.increment();
125 cachedAttributes.put(attributeKey, cachedAttributeValue); 124 cachedAttributes.put(attributeKey, cachedAttributeValue);
@@ -133,11 +132,11 @@ public class CachedAttributesService implements AttributesService { @@ -133,11 +132,11 @@ public class CachedAttributesService implements AttributesService {
133 private List<AttributeKvEntry> mergeDbAndCacheAttributes(EntityId entityId, String scope, List<AttributeKvEntry> cachedAttributes, Set<String> notFoundAttributeKeys, List<AttributeKvEntry> foundInDbAttributes) { 132 private List<AttributeKvEntry> mergeDbAndCacheAttributes(EntityId entityId, String scope, List<AttributeKvEntry> cachedAttributes, Set<String> notFoundAttributeKeys, List<AttributeKvEntry> foundInDbAttributes) {
134 for (AttributeKvEntry foundInDbAttribute : foundInDbAttributes) { 133 for (AttributeKvEntry foundInDbAttribute : foundInDbAttributes) {
135 AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, foundInDbAttribute.getKey()); 134 AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, foundInDbAttribute.getKey());
136 - attributesCache.put(attributeCacheKey, foundInDbAttribute); 135 + cacheWrapper.put(attributeCacheKey, foundInDbAttribute);
137 notFoundAttributeKeys.remove(foundInDbAttribute.getKey()); 136 notFoundAttributeKeys.remove(foundInDbAttribute.getKey());
138 } 137 }
139 for (String key : notFoundAttributeKeys){ 138 for (String key : notFoundAttributeKeys){
140 - attributesCache.put(new AttributeCacheKey(scope, entityId, key), null); 139 + cacheWrapper.put(new AttributeCacheKey(scope, entityId, key), null);
141 } 140 }
142 List<AttributeKvEntry> mergedAttributes = new ArrayList<>(cachedAttributes); 141 List<AttributeKvEntry> mergedAttributes = new ArrayList<>(cachedAttributes);
143 mergedAttributes.addAll(foundInDbAttributes); 142 mergedAttributes.addAll(foundInDbAttributes);
@@ -185,7 +184,7 @@ public class CachedAttributesService implements AttributesService { @@ -185,7 +184,7 @@ public class CachedAttributesService implements AttributesService {
185 private void evictAttributesFromCache(TenantId tenantId, EntityId entityId, String scope, List<String> attributeKeys) { 184 private void evictAttributesFromCache(TenantId tenantId, EntityId entityId, String scope, List<String> attributeKeys) {
186 try { 185 try {
187 for (String attributeKey : attributeKeys) { 186 for (String attributeKey : attributeKeys) {
188 - attributesCache.evict(new AttributeCacheKey(scope, entityId, attributeKey)); 187 + cacheWrapper.evict(new AttributeCacheKey(scope, entityId, attributeKey));
189 } 188 }
190 } catch (Exception e) { 189 } catch (Exception e) {
191 log.error("[{}][{}] Failed to remove values from cache.", tenantId, entityId, e); 190 log.error("[{}][{}] Failed to remove values from cache.", tenantId, entityId, e);