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 | 56 | private static final String STATS_NAME = "attributes.cache"; |
57 | 57 | |
58 | 58 | private final AttributesDao attributesDao; |
59 | - private final Cache attributesCache; | |
60 | - | |
59 | + private final AttributesCacheWrapper cacheWrapper; | |
61 | 60 | private final DefaultCounter hitCounter; |
62 | 61 | private final DefaultCounter missCounter; |
63 | 62 | |
64 | 63 | public CachedAttributesService(AttributesDao attributesDao, |
65 | - CacheManager cacheManager, | |
64 | + AttributesCacheWrapper cacheWrapper, | |
66 | 65 | StatsFactory statsFactory) { |
67 | 66 | this.attributesDao = attributesDao; |
68 | - this.attributesCache = cacheManager.getCache(ATTRIBUTES_CACHE); | |
67 | + this.cacheWrapper = cacheWrapper; | |
69 | 68 | |
70 | 69 | this.hitCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "hit"); |
71 | 70 | this.missCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "miss"); |
... | ... | @@ -77,7 +76,7 @@ public class CachedAttributesService implements AttributesService { |
77 | 76 | Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey); |
78 | 77 | |
79 | 78 | AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey); |
80 | - Cache.ValueWrapper cachedAttributeValue = attributesCache.get(attributeCacheKey); | |
79 | + Cache.ValueWrapper cachedAttributeValue = cacheWrapper.get(attributeCacheKey); | |
81 | 80 | if (cachedAttributeValue != null) { |
82 | 81 | hitCounter.increment(); |
83 | 82 | AttributeKvEntry cachedAttributeKvEntry = (AttributeKvEntry) cachedAttributeValue.get(); |
... | ... | @@ -87,7 +86,7 @@ public class CachedAttributesService implements AttributesService { |
87 | 86 | ListenableFuture<Optional<AttributeKvEntry>> result = attributesDao.find(tenantId, entityId, scope, attributeKey); |
88 | 87 | return Futures.transform(result, foundAttrKvEntry -> { |
89 | 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 | 90 | return foundAttrKvEntry; |
92 | 91 | }, MoreExecutors.directExecutor()); |
93 | 92 | } |
... | ... | @@ -119,7 +118,7 @@ public class CachedAttributesService implements AttributesService { |
119 | 118 | private Map<String, Cache.ValueWrapper> findCachedAttributes(EntityId entityId, String scope, Collection<String> attributeKeys) { |
120 | 119 | Map<String, Cache.ValueWrapper> cachedAttributes = new HashMap<>(); |
121 | 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 | 122 | if (cachedAttributeValue != null) { |
124 | 123 | hitCounter.increment(); |
125 | 124 | cachedAttributes.put(attributeKey, cachedAttributeValue); |
... | ... | @@ -133,11 +132,11 @@ public class CachedAttributesService implements AttributesService { |
133 | 132 | private List<AttributeKvEntry> mergeDbAndCacheAttributes(EntityId entityId, String scope, List<AttributeKvEntry> cachedAttributes, Set<String> notFoundAttributeKeys, List<AttributeKvEntry> foundInDbAttributes) { |
134 | 133 | for (AttributeKvEntry foundInDbAttribute : foundInDbAttributes) { |
135 | 134 | AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, foundInDbAttribute.getKey()); |
136 | - attributesCache.put(attributeCacheKey, foundInDbAttribute); | |
135 | + cacheWrapper.put(attributeCacheKey, foundInDbAttribute); | |
137 | 136 | notFoundAttributeKeys.remove(foundInDbAttribute.getKey()); |
138 | 137 | } |
139 | 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 | 141 | List<AttributeKvEntry> mergedAttributes = new ArrayList<>(cachedAttributes); |
143 | 142 | mergedAttributes.addAll(foundInDbAttributes); |
... | ... | @@ -185,7 +184,7 @@ public class CachedAttributesService implements AttributesService { |
185 | 184 | private void evictAttributesFromCache(TenantId tenantId, EntityId entityId, String scope, List<String> attributeKeys) { |
186 | 185 | try { |
187 | 186 | for (String attributeKey : attributeKeys) { |
188 | - attributesCache.evict(new AttributeCacheKey(scope, entityId, attributeKey)); | |
187 | + cacheWrapper.evict(new AttributeCacheKey(scope, entityId, attributeKey)); | |
189 | 188 | } |
190 | 189 | } catch (Exception e) { |
191 | 190 | log.error("[{}][{}] Failed to remove values from cache.", tenantId, entityId, e); | ... | ... |