Wrapped attr cache requests, fixed bug
This commit is contained in:
parent
ab76d81c6f
commit
c7df356fb7
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright © 2016-2021 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.server.dao.attributes;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
||||
|
||||
import static org.thingsboard.server.common.data.CacheConstants.ATTRIBUTES_CACHE;
|
||||
|
||||
@Service
|
||||
@ConditionalOnProperty(prefix = "cache.attributes", value = "enabled", havingValue = "true")
|
||||
@Primary
|
||||
@Slf4j
|
||||
public class AttributesCacheWrapper {
|
||||
private final Cache attributesCache;
|
||||
|
||||
public AttributesCacheWrapper(CacheManager cacheManager) {
|
||||
this.attributesCache = cacheManager.getCache(ATTRIBUTES_CACHE);
|
||||
}
|
||||
|
||||
public Cache.ValueWrapper get(AttributeCacheKey attributeCacheKey) {
|
||||
try {
|
||||
return attributesCache.get(attributeCacheKey);
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve element from cache for key {}. Reason - {}.", attributeCacheKey, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void put(AttributeCacheKey attributeCacheKey, AttributeKvEntry attributeKvEntry) {
|
||||
try {
|
||||
attributesCache.put(attributeCacheKey, attributeKvEntry);
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to put element from cache for key {}. Reason - {}.", attributeCacheKey, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void evict(AttributeCacheKey attributeCacheKey) {
|
||||
try {
|
||||
attributesCache.evict(attributeCacheKey);
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to evict element from cache for key {}. Reason - {}.", attributeCacheKey, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,16 +56,15 @@ public class CachedAttributesService implements AttributesService {
|
||||
private static final String STATS_NAME = "attributes.cache";
|
||||
|
||||
private final AttributesDao attributesDao;
|
||||
private final Cache attributesCache;
|
||||
|
||||
private final AttributesCacheWrapper cacheWrapper;
|
||||
private final DefaultCounter hitCounter;
|
||||
private final DefaultCounter missCounter;
|
||||
|
||||
public CachedAttributesService(AttributesDao attributesDao,
|
||||
CacheManager cacheManager,
|
||||
AttributesCacheWrapper cacheWrapper,
|
||||
StatsFactory statsFactory) {
|
||||
this.attributesDao = attributesDao;
|
||||
this.attributesCache = cacheManager.getCache(ATTRIBUTES_CACHE);
|
||||
this.cacheWrapper = cacheWrapper;
|
||||
|
||||
this.hitCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "hit");
|
||||
this.missCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "miss");
|
||||
@ -77,7 +76,7 @@ public class CachedAttributesService implements AttributesService {
|
||||
Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey);
|
||||
|
||||
AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey);
|
||||
Cache.ValueWrapper cachedAttributeValue = attributesCache.get(attributeCacheKey);
|
||||
Cache.ValueWrapper cachedAttributeValue = cacheWrapper.get(attributeCacheKey);
|
||||
if (cachedAttributeValue != null) {
|
||||
hitCounter.increment();
|
||||
AttributeKvEntry cachedAttributeKvEntry = (AttributeKvEntry) cachedAttributeValue.get();
|
||||
@ -87,7 +86,7 @@ public class CachedAttributesService implements AttributesService {
|
||||
ListenableFuture<Optional<AttributeKvEntry>> result = attributesDao.find(tenantId, entityId, scope, attributeKey);
|
||||
return Futures.transform(result, foundAttrKvEntry -> {
|
||||
// TODO: think if it's a good idea to store 'empty' attributes
|
||||
attributesCache.put(attributeKey, foundAttrKvEntry.orElse(null));
|
||||
cacheWrapper.put(attributeCacheKey, foundAttrKvEntry.orElse(null));
|
||||
return foundAttrKvEntry;
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
@ -119,7 +118,7 @@ public class CachedAttributesService implements AttributesService {
|
||||
private Map<String, Cache.ValueWrapper> findCachedAttributes(EntityId entityId, String scope, Collection<String> attributeKeys) {
|
||||
Map<String, Cache.ValueWrapper> cachedAttributes = new HashMap<>();
|
||||
for (String attributeKey : attributeKeys) {
|
||||
Cache.ValueWrapper cachedAttributeValue = attributesCache.get(new AttributeCacheKey(scope, entityId, attributeKey));
|
||||
Cache.ValueWrapper cachedAttributeValue = cacheWrapper.get(new AttributeCacheKey(scope, entityId, attributeKey));
|
||||
if (cachedAttributeValue != null) {
|
||||
hitCounter.increment();
|
||||
cachedAttributes.put(attributeKey, cachedAttributeValue);
|
||||
@ -133,11 +132,11 @@ public class CachedAttributesService implements AttributesService {
|
||||
private List<AttributeKvEntry> mergeDbAndCacheAttributes(EntityId entityId, String scope, List<AttributeKvEntry> cachedAttributes, Set<String> notFoundAttributeKeys, List<AttributeKvEntry> foundInDbAttributes) {
|
||||
for (AttributeKvEntry foundInDbAttribute : foundInDbAttributes) {
|
||||
AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, foundInDbAttribute.getKey());
|
||||
attributesCache.put(attributeCacheKey, foundInDbAttribute);
|
||||
cacheWrapper.put(attributeCacheKey, foundInDbAttribute);
|
||||
notFoundAttributeKeys.remove(foundInDbAttribute.getKey());
|
||||
}
|
||||
for (String key : notFoundAttributeKeys){
|
||||
attributesCache.put(new AttributeCacheKey(scope, entityId, key), null);
|
||||
cacheWrapper.put(new AttributeCacheKey(scope, entityId, key), null);
|
||||
}
|
||||
List<AttributeKvEntry> mergedAttributes = new ArrayList<>(cachedAttributes);
|
||||
mergedAttributes.addAll(foundInDbAttributes);
|
||||
@ -185,7 +184,7 @@ public class CachedAttributesService implements AttributesService {
|
||||
private void evictAttributesFromCache(TenantId tenantId, EntityId entityId, String scope, List<String> attributeKeys) {
|
||||
try {
|
||||
for (String attributeKey : attributeKeys) {
|
||||
attributesCache.evict(new AttributeCacheKey(scope, entityId, attributeKey));
|
||||
cacheWrapper.evict(new AttributeCacheKey(scope, entityId, attributeKey));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}] Failed to remove values from cache.", tenantId, entityId, e);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user