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 static final String STATS_NAME = "attributes.cache";
|
||||||
|
|
||||||
private final AttributesDao attributesDao;
|
private final AttributesDao attributesDao;
|
||||||
private final Cache attributesCache;
|
private final AttributesCacheWrapper cacheWrapper;
|
||||||
|
|
||||||
private final DefaultCounter hitCounter;
|
private final DefaultCounter hitCounter;
|
||||||
private final DefaultCounter missCounter;
|
private final DefaultCounter missCounter;
|
||||||
|
|
||||||
public CachedAttributesService(AttributesDao attributesDao,
|
public CachedAttributesService(AttributesDao attributesDao,
|
||||||
CacheManager cacheManager,
|
AttributesCacheWrapper cacheWrapper,
|
||||||
StatsFactory statsFactory) {
|
StatsFactory statsFactory) {
|
||||||
this.attributesDao = attributesDao;
|
this.attributesDao = attributesDao;
|
||||||
this.attributesCache = cacheManager.getCache(ATTRIBUTES_CACHE);
|
this.cacheWrapper = cacheWrapper;
|
||||||
|
|
||||||
this.hitCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "hit");
|
this.hitCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "hit");
|
||||||
this.missCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "miss");
|
this.missCounter = statsFactory.createDefaultCounter(STATS_NAME, "result", "miss");
|
||||||
@ -77,7 +76,7 @@ public class CachedAttributesService implements AttributesService {
|
|||||||
Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey);
|
Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey);
|
||||||
|
|
||||||
AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey);
|
AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey);
|
||||||
Cache.ValueWrapper cachedAttributeValue = attributesCache.get(attributeCacheKey);
|
Cache.ValueWrapper cachedAttributeValue = cacheWrapper.get(attributeCacheKey);
|
||||||
if (cachedAttributeValue != null) {
|
if (cachedAttributeValue != null) {
|
||||||
hitCounter.increment();
|
hitCounter.increment();
|
||||||
AttributeKvEntry cachedAttributeKvEntry = (AttributeKvEntry) cachedAttributeValue.get();
|
AttributeKvEntry cachedAttributeKvEntry = (AttributeKvEntry) cachedAttributeValue.get();
|
||||||
@ -87,7 +86,7 @@ public class CachedAttributesService implements AttributesService {
|
|||||||
ListenableFuture<Optional<AttributeKvEntry>> result = attributesDao.find(tenantId, entityId, scope, attributeKey);
|
ListenableFuture<Optional<AttributeKvEntry>> result = attributesDao.find(tenantId, entityId, scope, attributeKey);
|
||||||
return Futures.transform(result, foundAttrKvEntry -> {
|
return Futures.transform(result, foundAttrKvEntry -> {
|
||||||
// TODO: think if it's a good idea to store 'empty' attributes
|
// 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;
|
return foundAttrKvEntry;
|
||||||
}, MoreExecutors.directExecutor());
|
}, MoreExecutors.directExecutor());
|
||||||
}
|
}
|
||||||
@ -119,7 +118,7 @@ public class CachedAttributesService implements AttributesService {
|
|||||||
private Map<String, Cache.ValueWrapper> findCachedAttributes(EntityId entityId, String scope, Collection<String> attributeKeys) {
|
private Map<String, Cache.ValueWrapper> findCachedAttributes(EntityId entityId, String scope, Collection<String> attributeKeys) {
|
||||||
Map<String, Cache.ValueWrapper> cachedAttributes = new HashMap<>();
|
Map<String, Cache.ValueWrapper> cachedAttributes = new HashMap<>();
|
||||||
for (String attributeKey : attributeKeys) {
|
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) {
|
if (cachedAttributeValue != null) {
|
||||||
hitCounter.increment();
|
hitCounter.increment();
|
||||||
cachedAttributes.put(attributeKey, cachedAttributeValue);
|
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) {
|
private List<AttributeKvEntry> mergeDbAndCacheAttributes(EntityId entityId, String scope, List<AttributeKvEntry> cachedAttributes, Set<String> notFoundAttributeKeys, List<AttributeKvEntry> foundInDbAttributes) {
|
||||||
for (AttributeKvEntry foundInDbAttribute : foundInDbAttributes) {
|
for (AttributeKvEntry foundInDbAttribute : foundInDbAttributes) {
|
||||||
AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, foundInDbAttribute.getKey());
|
AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, foundInDbAttribute.getKey());
|
||||||
attributesCache.put(attributeCacheKey, foundInDbAttribute);
|
cacheWrapper.put(attributeCacheKey, foundInDbAttribute);
|
||||||
notFoundAttributeKeys.remove(foundInDbAttribute.getKey());
|
notFoundAttributeKeys.remove(foundInDbAttribute.getKey());
|
||||||
}
|
}
|
||||||
for (String key : notFoundAttributeKeys){
|
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);
|
List<AttributeKvEntry> mergedAttributes = new ArrayList<>(cachedAttributes);
|
||||||
mergedAttributes.addAll(foundInDbAttributes);
|
mergedAttributes.addAll(foundInDbAttributes);
|
||||||
@ -185,7 +184,7 @@ public class CachedAttributesService implements AttributesService {
|
|||||||
private void evictAttributesFromCache(TenantId tenantId, EntityId entityId, String scope, List<String> attributeKeys) {
|
private void evictAttributesFromCache(TenantId tenantId, EntityId entityId, String scope, List<String> attributeKeys) {
|
||||||
try {
|
try {
|
||||||
for (String attributeKey : attributeKeys) {
|
for (String attributeKey : attributeKeys) {
|
||||||
attributesCache.evict(new AttributeCacheKey(scope, entityId, attributeKey));
|
cacheWrapper.evict(new AttributeCacheKey(scope, entityId, attributeKey));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[{}][{}] Failed to remove values from cache.", tenantId, entityId, e);
|
log.error("[{}][{}] Failed to remove values from cache.", tenantId, entityId, e);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user