Commit c7df356fb7cc4780b6ca72a22722798bf6028410
Committed by
Andrew Shvayka
1 parent
ab76d81c
Wrapped attr cache requests, fixed bug
Showing
2 changed files
with
72 additions
and
10 deletions
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); |