committed by
GitHub
176 changed files with 3433 additions and 1570 deletions
@ -0,0 +1,34 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.service.session; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("SessionCache") |
|||
public class SessionCaffeineCache extends CaffeineTbTransactionalCache<DeviceId, TransportProtos.DeviceSessionsCacheEntry> { |
|||
|
|||
public SessionCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.SESSIONS_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.service.session; |
|||
|
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.data.redis.serializer.RedisSerializer; |
|||
import org.springframework.data.redis.serializer.SerializationException; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("SessionCache") |
|||
public class SessionRedisCache extends RedisTbTransactionalCache<DeviceId, TransportProtos.DeviceSessionsCacheEntry> { |
|||
|
|||
public SessionRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.ASSET_CACHE, cacheSpecsMap, connectionFactory, configuration, new RedisSerializer<>() { |
|||
@Override |
|||
public byte[] serialize(TransportProtos.DeviceSessionsCacheEntry deviceSessionsCacheEntry) throws SerializationException { |
|||
return deviceSessionsCacheEntry.toByteArray(); |
|||
} |
|||
|
|||
@Override |
|||
public TransportProtos.DeviceSessionsCacheEntry deserialize(byte[] bytes) throws SerializationException { |
|||
try { |
|||
return TransportProtos.DeviceSessionsCacheEntry.parseFrom(bytes); |
|||
} catch (InvalidProtocolBufferException e) { |
|||
throw new RuntimeException("Failed to deserialize session cache entry"); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.controller; |
|||
|
|||
import org.junit.BeforeClass; |
|||
import org.junit.extensions.cpsuite.ClasspathSuite; |
|||
import org.junit.runner.RunWith; |
|||
import org.thingsboard.server.queue.memory.InMemoryStorage; |
|||
|
|||
@RunWith(ClasspathSuite.class) |
|||
@ClasspathSuite.ClassnameFilters({ |
|||
// "org.thingsboard.server.controller.sql.WebsocketApiSqlTest",
|
|||
// "org.thingsboard.server.controller.sql.EntityQueryControllerSqlTest",
|
|||
// "org.thingsboard.server.controller.sql.TbResourceControllerSqlTest",
|
|||
// "org.thingsboard.server.controller.sql.DeviceProfileControllerSqlTest",
|
|||
"org.thingsboard.server.controller.sql.*Test", |
|||
}) |
|||
public class ControllerSqlTestSuite { |
|||
|
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.transport; |
|||
|
|||
import org.junit.extensions.cpsuite.ClasspathSuite; |
|||
import org.junit.runner.RunWith; |
|||
|
|||
@RunWith(ClasspathSuite.class) |
|||
@ClasspathSuite.ClassnameFilters({ |
|||
"org.thingsboard.server.transport.*.rpc.*Test", |
|||
"org.thingsboard.server.transport.*.telemetry.timeseries.sql.*Test", |
|||
"org.thingsboard.server.transport.*.telemetry.attributes.*Test", |
|||
"org.thingsboard.server.transport.*.attributes.updates.*Test", |
|||
"org.thingsboard.server.transport.*.attributes.request.*Test", |
|||
"org.thingsboard.server.transport.*.claim.*Test", |
|||
"org.thingsboard.server.transport.*.provision.*Test", |
|||
"org.thingsboard.server.transport.*.credentials.*Test", |
|||
"org.thingsboard.server.transport.lwm2m.*.sql.*Test" |
|||
}) |
|||
public class TransportSqlTestSuite { |
|||
|
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.Setter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.LinkedHashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.UUID; |
|||
|
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public class CaffeineTbCacheTransaction<K extends Serializable, V extends Serializable> implements TbCacheTransaction<K, V> { |
|||
@Getter |
|||
private final UUID id = UUID.randomUUID(); |
|||
private final CaffeineTbTransactionalCache<K, V> cache; |
|||
@Getter |
|||
private final List<K> keys; |
|||
@Getter |
|||
@Setter |
|||
private boolean failed; |
|||
|
|||
private final Map<Object, Object> pendingPuts = new LinkedHashMap<>(); |
|||
|
|||
@Override |
|||
public void putIfAbsent(K key, V value) { |
|||
pendingPuts.put(key, value); |
|||
} |
|||
|
|||
@Override |
|||
public boolean commit() { |
|||
return cache.commit(id, pendingPuts); |
|||
} |
|||
|
|||
@Override |
|||
public void rollback() { |
|||
cache.rollback(id); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.CacheManager; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Collection; |
|||
import java.util.Collections; |
|||
import java.util.HashMap; |
|||
import java.util.HashSet; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.locks.Lock; |
|||
import java.util.concurrent.locks.ReentrantLock; |
|||
|
|||
@RequiredArgsConstructor |
|||
public abstract class CaffeineTbTransactionalCache<K extends Serializable, V extends Serializable> implements TbTransactionalCache<K, V> { |
|||
|
|||
private final CacheManager cacheManager; |
|||
@Getter |
|||
private final String cacheName; |
|||
|
|||
private final Lock lock = new ReentrantLock(); |
|||
private final Map<K, Set<UUID>> objectTransactions = new HashMap<>(); |
|||
private final Map<UUID, CaffeineTbCacheTransaction<K, V>> transactions = new HashMap<>(); |
|||
|
|||
@Override |
|||
public TbCacheValueWrapper<V> get(K key) { |
|||
return SimpleTbCacheValueWrapper.wrap(cacheManager.getCache(cacheName).get(key)); |
|||
} |
|||
|
|||
@Override |
|||
public void put(K key, V value) { |
|||
lock.lock(); |
|||
try { |
|||
failAllTransactionsByKey(key); |
|||
cacheManager.getCache(cacheName).put(key, value); |
|||
} finally { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void putIfAbsent(K key, V value) { |
|||
lock.lock(); |
|||
try { |
|||
failAllTransactionsByKey(key); |
|||
doPutIfAbsent(key, value); |
|||
} finally { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void evict(K key) { |
|||
lock.lock(); |
|||
try { |
|||
failAllTransactionsByKey(key); |
|||
doEvict(key); |
|||
} finally { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void evict(Collection<K> keys) { |
|||
lock.lock(); |
|||
try { |
|||
keys.forEach(key -> { |
|||
failAllTransactionsByKey(key); |
|||
doEvict(key); |
|||
}); |
|||
} finally { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void evictOrPut(K key, V value) { |
|||
//No need to put the value in case of Caffeine, because evict will cancel concurrent transaction used to "get" the missing value from cache.
|
|||
evict(key); |
|||
} |
|||
|
|||
@Override |
|||
public TbCacheTransaction<K, V> newTransactionForKey(K key) { |
|||
return newTransaction(Collections.singletonList(key)); |
|||
} |
|||
|
|||
@Override |
|||
public TbCacheTransaction<K, V> newTransactionForKeys(List<K> keys) { |
|||
return newTransaction(keys); |
|||
} |
|||
|
|||
void doPutIfAbsent(Object key, Object value) { |
|||
cacheManager.getCache(cacheName).putIfAbsent(key, value); |
|||
} |
|||
|
|||
void doEvict(K key) { |
|||
cacheManager.getCache(cacheName).evict(key); |
|||
} |
|||
|
|||
TbCacheTransaction<K, V> newTransaction(List<K> keys) { |
|||
lock.lock(); |
|||
try { |
|||
var transaction = new CaffeineTbCacheTransaction<>(this, keys); |
|||
var transactionId = transaction.getId(); |
|||
for (K key : keys) { |
|||
objectTransactions.computeIfAbsent(key, k -> new HashSet<>()).add(transactionId); |
|||
} |
|||
transactions.put(transactionId, transaction); |
|||
return transaction; |
|||
} finally { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
|
|||
public boolean commit(UUID trId, Map<Object, Object> pendingPuts) { |
|||
lock.lock(); |
|||
try { |
|||
var tr = transactions.get(trId); |
|||
var success = !tr.isFailed(); |
|||
if (success) { |
|||
for (K key : tr.getKeys()) { |
|||
Set<UUID> otherTransactions = objectTransactions.get(key); |
|||
if (otherTransactions != null) { |
|||
for (UUID otherTrId : otherTransactions) { |
|||
if (trId == null || !trId.equals(otherTrId)) { |
|||
transactions.get(otherTrId).setFailed(true); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
pendingPuts.forEach(this::doPutIfAbsent); |
|||
} |
|||
removeTransaction(trId); |
|||
return success; |
|||
} finally { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
|
|||
void rollback(UUID id) { |
|||
lock.lock(); |
|||
try { |
|||
removeTransaction(id); |
|||
} finally { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
|
|||
private void removeTransaction(UUID id) { |
|||
CaffeineTbCacheTransaction<K, V> transaction = transactions.remove(id); |
|||
if (transaction != null) { |
|||
for (var key : transaction.getKeys()) { |
|||
Set<UUID> transactions = objectTransactions.get(key); |
|||
if (transactions != null) { |
|||
transactions.remove(id); |
|||
if (transactions.isEmpty()) { |
|||
objectTransactions.remove(key); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void failAllTransactionsByKey(K key) { |
|||
Set<UUID> transactionsIds = objectTransactions.get(key); |
|||
if (transactionsIds != null) { |
|||
for (UUID otherTrId : transactionsIds) { |
|||
transactions.get(otherTrId).setFailed(true); |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.data.redis.connection.RedisConnection; |
|||
import org.springframework.data.redis.connection.RedisStringCommands; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Objects; |
|||
|
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public class RedisTbCacheTransaction<K extends Serializable, V extends Serializable> implements TbCacheTransaction<K, V> { |
|||
|
|||
private final RedisTbTransactionalCache<K, V> cache; |
|||
private final RedisConnection connection; |
|||
|
|||
@Override |
|||
public void putIfAbsent(K key, V value) { |
|||
cache.put(connection, key, value, RedisStringCommands.SetOption.UPSERT); |
|||
} |
|||
|
|||
@Override |
|||
public boolean commit() { |
|||
try { |
|||
var execResult = connection.exec(); |
|||
var result = execResult != null && execResult.stream().anyMatch(Objects::nonNull); |
|||
return result; |
|||
} finally { |
|||
connection.close(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void rollback() { |
|||
try { |
|||
connection.discard(); |
|||
} finally { |
|||
connection.close(); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,180 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.cache.support.NullValue; |
|||
import org.springframework.data.redis.connection.RedisConnection; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.data.redis.connection.RedisStringCommands; |
|||
import org.springframework.data.redis.core.types.Expiration; |
|||
import org.springframework.data.redis.serializer.RedisSerializer; |
|||
import org.springframework.data.redis.serializer.StringRedisSerializer; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Arrays; |
|||
import java.util.Collection; |
|||
import java.util.List; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
@Slf4j |
|||
public abstract class RedisTbTransactionalCache<K extends Serializable, V extends Serializable> implements TbTransactionalCache<K, V> { |
|||
|
|||
private static final byte[] BINARY_NULL_VALUE = RedisSerializer.java().serialize(NullValue.INSTANCE); |
|||
|
|||
@Getter |
|||
private final String cacheName; |
|||
private final RedisConnectionFactory connectionFactory; |
|||
private final RedisSerializer<String> keySerializer = new StringRedisSerializer(); |
|||
private final RedisSerializer<V> valueSerializer; |
|||
private final Expiration evictExpiration; |
|||
private final Expiration cacheTtl; |
|||
|
|||
public RedisTbTransactionalCache(String cacheName, |
|||
CacheSpecsMap cacheSpecsMap, |
|||
RedisConnectionFactory connectionFactory, |
|||
TBRedisCacheConfiguration configuration, |
|||
RedisSerializer<V> valueSerializer) { |
|||
this.cacheName = cacheName; |
|||
this.connectionFactory = connectionFactory; |
|||
this.valueSerializer = valueSerializer; |
|||
this.evictExpiration = Expiration.from(configuration.getEvictTtlInMs(), TimeUnit.MILLISECONDS); |
|||
if (cacheSpecsMap.getSpecs() != null && cacheSpecsMap.getSpecs().get(cacheName) != null) { |
|||
CacheSpecs cacheSpecs = cacheSpecsMap.getSpecs().get(cacheName); |
|||
this.cacheTtl = Expiration.from(cacheSpecs.getTimeToLiveInMinutes(), TimeUnit.MINUTES); |
|||
} else { |
|||
this.cacheTtl = Expiration.persistent(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public TbCacheValueWrapper<V> get(K key) { |
|||
try (var connection = connectionFactory.getConnection()) { |
|||
byte[] rawKey = getRawKey(key); |
|||
byte[] rawValue = connection.get(rawKey); |
|||
if (rawValue == null) { |
|||
return null; |
|||
} else if (Arrays.equals(rawValue, BINARY_NULL_VALUE)) { |
|||
return SimpleTbCacheValueWrapper.empty(); |
|||
} else { |
|||
V value = valueSerializer.deserialize(rawValue); |
|||
return SimpleTbCacheValueWrapper.wrap(value); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void put(K key, V value) { |
|||
try (var connection = connectionFactory.getConnection()) { |
|||
put(connection, key, value, RedisStringCommands.SetOption.UPSERT); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void putIfAbsent(K key, V value) { |
|||
try (var connection = connectionFactory.getConnection()) { |
|||
put(connection, key, value, RedisStringCommands.SetOption.SET_IF_ABSENT); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void evict(K key) { |
|||
try (var connection = connectionFactory.getConnection()) { |
|||
connection.del(getRawKey(key)); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void evict(Collection<K> keys) { |
|||
try (var connection = connectionFactory.getConnection()) { |
|||
connection.del(keys.stream().map(this::getRawKey).toArray(byte[][]::new)); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void evictOrPut(K key, V value) { |
|||
try (var connection = connectionFactory.getConnection()) { |
|||
var rawKey = getRawKey(key); |
|||
var records = connection.del(rawKey); |
|||
if (records == null || records == 0) { |
|||
//We need to put the value in case of Redis, because evict will NOT cancel concurrent transaction used to "get" the missing value from cache.
|
|||
connection.set(rawKey, getRawValue(value), evictExpiration, RedisStringCommands.SetOption.UPSERT); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public TbCacheTransaction<K, V> newTransactionForKey(K key) { |
|||
byte[][] rawKey = new byte[][]{getRawKey(key)}; |
|||
RedisConnection connection = watch(rawKey); |
|||
return new RedisTbCacheTransaction<>(this, connection); |
|||
} |
|||
|
|||
@Override |
|||
public TbCacheTransaction<K, V> newTransactionForKeys(List<K> keys) { |
|||
RedisConnection connection = watch(keys.stream().map(this::getRawKey).toArray(byte[][]::new)); |
|||
return new RedisTbCacheTransaction<>(this, connection); |
|||
} |
|||
|
|||
private RedisConnection watch(byte[][] rawKeysList) { |
|||
var connection = connectionFactory.getConnection(); |
|||
try { |
|||
connection.watch(rawKeysList); |
|||
connection.multi(); |
|||
} catch (Exception e) { |
|||
connection.close(); |
|||
throw e; |
|||
} |
|||
return connection; |
|||
} |
|||
|
|||
private byte[] getRawKey(K key) { |
|||
String keyString = cacheName + key.toString(); |
|||
byte[] rawKey; |
|||
try { |
|||
rawKey = keySerializer.serialize(keyString); |
|||
} catch (Exception e) { |
|||
log.warn("Failed to serialize the cache key: {}", key, e); |
|||
throw new RuntimeException(e); |
|||
} |
|||
if (rawKey == null) { |
|||
log.warn("Failed to serialize the cache key: {}", key); |
|||
throw new IllegalArgumentException("Failed to serialize the cache key!"); |
|||
} |
|||
return rawKey; |
|||
} |
|||
|
|||
private byte[] getRawValue(V value) { |
|||
if (value == null) { |
|||
return BINARY_NULL_VALUE; |
|||
} else { |
|||
try { |
|||
return valueSerializer.serialize(value); |
|||
} catch (Exception e) { |
|||
log.warn("Failed to serialize the cache value: {}", value, e); |
|||
throw new RuntimeException(e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void put(RedisConnection connection, K key, V value, RedisStringCommands.SetOption setOption) { |
|||
byte[] rawKey = getRawKey(key); |
|||
byte[] rawValue = getRawValue(value); |
|||
connection.set(rawKey, rawValue, cacheTtl, setOption); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import lombok.AccessLevel; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.Cache; |
|||
|
|||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE) |
|||
public class SimpleTbCacheValueWrapper<T> implements TbCacheValueWrapper<T> { |
|||
|
|||
private final T value; |
|||
|
|||
@Override |
|||
public T get() { |
|||
return value; |
|||
} |
|||
|
|||
public static <T> SimpleTbCacheValueWrapper<T> empty() { |
|||
return new SimpleTbCacheValueWrapper<>(null); |
|||
} |
|||
|
|||
public static <T> SimpleTbCacheValueWrapper<T> wrap(T value) { |
|||
return new SimpleTbCacheValueWrapper<>(value); |
|||
} |
|||
|
|||
@SuppressWarnings("unchecked") |
|||
public static <T> SimpleTbCacheValueWrapper<T> wrap(Cache.ValueWrapper source) { |
|||
return source == null ? null : new SimpleTbCacheValueWrapper<>((T) source.get()); |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import org.springframework.data.redis.serializer.RedisSerializer; |
|||
import org.springframework.data.redis.serializer.SerializationException; |
|||
|
|||
public class TbRedisSerializer<T> implements RedisSerializer<T> { |
|||
|
|||
private final RedisSerializer<Object> java = RedisSerializer.java(); |
|||
|
|||
@Override |
|||
public byte[] serialize(T t) throws SerializationException { |
|||
return java.serialize(t); |
|||
} |
|||
|
|||
@Override |
|||
public T deserialize(byte[] bytes) throws SerializationException { |
|||
return (T) java.deserialize(bytes); |
|||
} |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Collection; |
|||
import java.util.List; |
|||
import java.util.function.Function; |
|||
import java.util.function.Supplier; |
|||
|
|||
public interface TbTransactionalCache<K extends Serializable, V extends Serializable> { |
|||
|
|||
String getCacheName(); |
|||
|
|||
TbCacheValueWrapper<V> get(K key); |
|||
|
|||
void put(K key, V value); |
|||
|
|||
void putIfAbsent(K key, V value); |
|||
|
|||
void evict(K key); |
|||
|
|||
void evict(Collection<K> keys); |
|||
|
|||
void evictOrPut(K key, V value); |
|||
|
|||
TbCacheTransaction<K, V> newTransactionForKey(K key); |
|||
|
|||
TbCacheTransaction<K, V> newTransactionForKeys(List<K> keys); |
|||
|
|||
default V getAndPutInTransaction(K key, Supplier<V> dbCall, boolean cacheNullValue) { |
|||
TbCacheValueWrapper<V> cacheValueWrapper = get(key); |
|||
if (cacheValueWrapper != null) { |
|||
return cacheValueWrapper.get(); |
|||
} |
|||
var cacheTransaction = newTransactionForKey(key); |
|||
try { |
|||
V dbValue = dbCall.get(); |
|||
if (dbValue != null || cacheNullValue) { |
|||
cacheTransaction.putIfAbsent(key, dbValue); |
|||
cacheTransaction.commit(); |
|||
return dbValue; |
|||
} else { |
|||
cacheTransaction.rollback(); |
|||
return null; |
|||
} |
|||
} catch (Throwable e) { |
|||
cacheTransaction.rollback(); |
|||
throw e; |
|||
} |
|||
} |
|||
|
|||
default <R> R getAndPutInTransaction(K key, Supplier<R> dbCall, Function<V, R> cacheValueToResult, Function<R, V> dbValueToCacheValue, boolean cacheNullValue) { |
|||
TbCacheValueWrapper<V> cacheValueWrapper = get(key); |
|||
if (cacheValueWrapper != null) { |
|||
var cacheValue = cacheValueWrapper.get(); |
|||
return cacheValue == null ? null : cacheValueToResult.apply(cacheValue); |
|||
} |
|||
var cacheTransaction = newTransactionForKey(key); |
|||
try { |
|||
R dbValue = dbCall.get(); |
|||
if (dbValue != null || cacheNullValue) { |
|||
cacheTransaction.putIfAbsent(key, dbValueToCacheValue.apply(dbValue)); |
|||
cacheTransaction.commit(); |
|||
return dbValue; |
|||
} else { |
|||
cacheTransaction.rollback(); |
|||
return null; |
|||
} |
|||
} catch (Throwable e) { |
|||
cacheTransaction.rollback(); |
|||
throw e; |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache.device; |
|||
|
|||
import lombok.Builder; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Getter |
|||
@EqualsAndHashCode |
|||
@RequiredArgsConstructor |
|||
@Builder |
|||
public class DeviceCacheKey implements Serializable { |
|||
|
|||
private final TenantId tenantId; |
|||
private final DeviceId deviceId; |
|||
private final String deviceName; |
|||
|
|||
public DeviceCacheKey(TenantId tenantId, DeviceId deviceId) { |
|||
this(tenantId, deviceId, null); |
|||
} |
|||
|
|||
public DeviceCacheKey(TenantId tenantId, String deviceName) { |
|||
this(tenantId, null, deviceName); |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
if (deviceId != null) { |
|||
return tenantId + "_" + deviceId; |
|||
} else { |
|||
return tenantId + "_n_" + deviceName; |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache.device; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.Device; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("DeviceCache") |
|||
public class DeviceCaffeineCache extends CaffeineTbTransactionalCache<DeviceCacheKey, Device> { |
|||
|
|||
public DeviceCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.DEVICE_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache.device; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.cache.TbRedisSerializer; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.Device; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("DeviceCache") |
|||
public class DeviceRedisCache extends RedisTbTransactionalCache<DeviceCacheKey, Device> { |
|||
|
|||
public DeviceRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.DEVICE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.asset; |
|||
|
|||
import lombok.Data; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
@Data |
|||
@RequiredArgsConstructor |
|||
class AssetCacheEvictEvent { |
|||
|
|||
private final TenantId tenantId; |
|||
private final String newName; |
|||
private final String oldName; |
|||
|
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.asset; |
|||
|
|||
import lombok.Builder; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Getter |
|||
@EqualsAndHashCode |
|||
@RequiredArgsConstructor |
|||
@Builder |
|||
public class AssetCacheKey implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 4196610233744512673L; |
|||
|
|||
private final TenantId tenantId; |
|||
private final String name; |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return tenantId + "_" + name; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.asset; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.asset.Asset; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("AssetCache") |
|||
public class AssetCaffeineCache extends CaffeineTbTransactionalCache<AssetCacheKey, Asset> { |
|||
|
|||
public AssetCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.ASSET_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.asset; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.asset.Asset; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.cache.TbRedisSerializer; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("AssetCache") |
|||
public class AssetRedisCache extends RedisTbTransactionalCache<AssetCacheKey, Asset> { |
|||
|
|||
public AssetRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.ASSET_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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 org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("AttributeCache") |
|||
public class AttributeCaffeineCache extends CaffeineTbTransactionalCache<AttributeCacheKey, AttributeKvEntry> { |
|||
|
|||
public AttributeCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.ATTRIBUTES_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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 org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.cache.TbRedisSerializer; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("AttributeCache") |
|||
public class AttributeRedisCache extends RedisTbTransactionalCache<AttributeCacheKey, AttributeKvEntry> { |
|||
|
|||
public AttributeRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.ATTRIBUTES_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); |
|||
} |
|||
} |
|||
@ -1,63 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,64 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.cache.Cache; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
import java.util.Arrays; |
|||
|
|||
import static org.thingsboard.server.common.data.CacheConstants.ASSET_CACHE; |
|||
import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CACHE; |
|||
import static org.thingsboard.server.common.data.CacheConstants.EDGE_CACHE; |
|||
|
|||
@Component |
|||
@AllArgsConstructor |
|||
public class EntitiesCacheManagerImpl implements EntitiesCacheManager { |
|||
|
|||
private final CacheManager cacheManager; |
|||
|
|||
@Override |
|||
public void removeDeviceFromCacheByName(TenantId tenantId, String name) { |
|||
Cache cache = cacheManager.getCache(DEVICE_CACHE); |
|||
cache.evict(Arrays.asList(tenantId, name)); |
|||
} |
|||
|
|||
@Override |
|||
public void removeDeviceFromCacheById(TenantId tenantId, DeviceId deviceId) { |
|||
if (deviceId == null) { |
|||
return; |
|||
} |
|||
Cache cache = cacheManager.getCache(DEVICE_CACHE); |
|||
cache.evict(Arrays.asList(tenantId, deviceId)); |
|||
} |
|||
|
|||
@Override |
|||
public void removeAssetFromCacheByName(TenantId tenantId, String name) { |
|||
Cache cache = cacheManager.getCache(ASSET_CACHE); |
|||
cache.evict(Arrays.asList(tenantId, name)); |
|||
} |
|||
|
|||
@Override |
|||
public void removeEdgeFromCacheByName(TenantId tenantId, String name) { |
|||
Cache cache = cacheManager.getCache(EDGE_CACHE); |
|||
cache.evict(Arrays.asList(tenantId, name)); |
|||
} |
|||
|
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.cache; |
|||
|
|||
import org.springframework.cache.interceptor.KeyGenerator; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.dao.device.DeviceCredentialsService; |
|||
|
|||
import java.lang.reflect.Method; |
|||
|
|||
import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE; |
|||
|
|||
@Component("previousDeviceCredentialsId") |
|||
public class PreviousDeviceCredentialsIdKeyGenerator implements KeyGenerator { |
|||
|
|||
private static final String NOT_VALID_DEVICE = DEVICE_CREDENTIALS_CACHE + "_notValidDeviceCredentialsId"; |
|||
|
|||
@Override |
|||
public Object generate(Object o, Method method, Object... objects) { |
|||
DeviceCredentialsService deviceCredentialsService = (DeviceCredentialsService) o; |
|||
TenantId tenantId = (TenantId) objects[0]; |
|||
DeviceCredentials deviceCredentials = (DeviceCredentials) objects[1]; |
|||
if (deviceCredentials.getDeviceId() != null) { |
|||
DeviceCredentials oldDeviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, deviceCredentials.getDeviceId()); |
|||
if (oldDeviceCredentials != null) { |
|||
return DEVICE_CREDENTIALS_CACHE + "_" + oldDeviceCredentials.getCredentialsId(); |
|||
} |
|||
} |
|||
return NOT_VALID_DEVICE; |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.device; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("DeviceCredentialsCache") |
|||
public class DeviceCredentialsCaffeineCache extends CaffeineTbTransactionalCache<String, DeviceCredentials> { |
|||
|
|||
public DeviceCredentialsCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.DEVICE_CREDENTIALS_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.device; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.cache.TbRedisSerializer; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("DeviceCredentialsCache") |
|||
public class DeviceCredentialsRedisCache extends RedisTbTransactionalCache<String, DeviceCredentials> { |
|||
|
|||
public DeviceCredentialsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.DEVICE_CREDENTIALS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.device; |
|||
|
|||
import lombok.Data; |
|||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Data |
|||
public class DeviceProfileCacheKey implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 8220455917177676472L; |
|||
|
|||
private final TenantId tenantId; |
|||
private final String name; |
|||
private final DeviceProfileId deviceProfileId; |
|||
private final boolean defaultProfile; |
|||
|
|||
private DeviceProfileCacheKey(TenantId tenantId, String name, DeviceProfileId deviceProfileId, boolean defaultProfile) { |
|||
this.tenantId = tenantId; |
|||
this.name = name; |
|||
this.deviceProfileId = deviceProfileId; |
|||
this.defaultProfile = defaultProfile; |
|||
} |
|||
|
|||
public static DeviceProfileCacheKey fromName(TenantId tenantId, String name) { |
|||
return new DeviceProfileCacheKey(tenantId, name, null, false); |
|||
} |
|||
|
|||
public static DeviceProfileCacheKey fromId(DeviceProfileId id) { |
|||
return new DeviceProfileCacheKey(null, null, id, false); |
|||
} |
|||
|
|||
public static DeviceProfileCacheKey defaultProfile(TenantId tenantId) { |
|||
return new DeviceProfileCacheKey(tenantId, null, null, true); |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
if (deviceProfileId != null) { |
|||
return deviceProfileId.toString(); |
|||
} else if (defaultProfile) { |
|||
return tenantId.toString(); |
|||
} else { |
|||
return tenantId + "_" + name; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.device; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("DeviceProfileCache") |
|||
public class DeviceProfileCaffeineCache extends CaffeineTbTransactionalCache<DeviceProfileCacheKey, DeviceProfile> { |
|||
|
|||
public DeviceProfileCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.DEVICE_PROFILE_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.device; |
|||
|
|||
import lombok.Data; |
|||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
@Data |
|||
public class DeviceProfileEvictEvent { |
|||
|
|||
private final TenantId tenantId; |
|||
private final String newName; |
|||
private final String oldName; |
|||
private final DeviceProfileId deviceProfileId; |
|||
private final boolean defaultProfile; |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.device; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.cache.TbRedisSerializer; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("DeviceProfileCache") |
|||
public class DeviceProfileRedisCache extends RedisTbTransactionalCache<DeviceProfileCacheKey, DeviceProfile> { |
|||
|
|||
public DeviceProfileRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.DEVICE_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.edge; |
|||
|
|||
import lombok.Data; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
@Data |
|||
@RequiredArgsConstructor |
|||
class EdgeCacheEvictEvent { |
|||
|
|||
private final TenantId tenantId; |
|||
private final String newName; |
|||
private final String oldName; |
|||
|
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.edge; |
|||
|
|||
import lombok.Builder; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Getter |
|||
@EqualsAndHashCode |
|||
@RequiredArgsConstructor |
|||
@Builder |
|||
public class EdgeCacheKey implements Serializable { |
|||
|
|||
private final TenantId tenantId; |
|||
private final String name; |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return tenantId + "_" + name; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.edge; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("EdgeCache") |
|||
public class EdgeCaffeineCache extends CaffeineTbTransactionalCache<EdgeCacheKey, Edge> { |
|||
|
|||
public EdgeCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.EDGE_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.edge; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.cache.TbRedisSerializer; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("EdgeCache") |
|||
public class EdgeRedisCache extends RedisTbTransactionalCache<EdgeCacheKey, Edge> { |
|||
|
|||
public EdgeRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.EDGE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entity; |
|||
|
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.context.ApplicationEventPublisher; |
|||
import org.springframework.transaction.support.TransactionSynchronizationManager; |
|||
import org.thingsboard.server.cache.TbTransactionalCache; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public abstract class AbstractCachedEntityService<K extends Serializable, V extends Serializable, E> extends AbstractEntityService { |
|||
|
|||
@Autowired |
|||
protected TbTransactionalCache<K, V> cache; |
|||
|
|||
@Autowired |
|||
private ApplicationEventPublisher eventPublisher; |
|||
|
|||
protected void publishEvictEvent(E event) { |
|||
if (TransactionSynchronizationManager.isActualTransactionActive()) { |
|||
eventPublisher.publishEvent(event); |
|||
} else { |
|||
handleEvictEvent(event); |
|||
} |
|||
} |
|||
|
|||
public abstract void handleEvictEvent(E event); |
|||
|
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entityview; |
|||
|
|||
import lombok.Builder; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.EntityViewId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Getter |
|||
@EqualsAndHashCode |
|||
@Builder |
|||
public class EntityViewCacheKey implements Serializable { |
|||
|
|||
private final TenantId tenantId; |
|||
private final String name; |
|||
private final EntityId entityId; |
|||
private final EntityViewId entityViewId; |
|||
|
|||
private EntityViewCacheKey(TenantId tenantId, String name, EntityId entityId, EntityViewId entityViewId) { |
|||
this.tenantId = tenantId; |
|||
this.name = name; |
|||
this.entityId = entityId; |
|||
this.entityViewId = entityViewId; |
|||
} |
|||
|
|||
public static EntityViewCacheKey byName(TenantId tenantId, String name) { |
|||
return new EntityViewCacheKey(tenantId, name, null, null); |
|||
} |
|||
|
|||
public static EntityViewCacheKey byEntityId(TenantId tenantId, EntityId entityId) { |
|||
return new EntityViewCacheKey(tenantId, null, entityId, null); |
|||
} |
|||
|
|||
public static EntityViewCacheKey byId(EntityViewId id) { |
|||
return new EntityViewCacheKey(null, null, null, id); |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
if (entityViewId != null) { |
|||
return entityViewId.toString(); |
|||
} else if (entityId != null) { |
|||
return tenantId + "_" + entityId; |
|||
} else { |
|||
return tenantId + "_n_" + name; |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entityview; |
|||
|
|||
import lombok.Builder; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import org.thingsboard.server.common.data.EntityView; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.List; |
|||
|
|||
@Getter |
|||
@EqualsAndHashCode |
|||
@Builder |
|||
public class EntityViewCacheValue implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 1959004642076413174L; |
|||
|
|||
private final EntityView entityView; |
|||
private final List<EntityView> entityViews; |
|||
|
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entityview; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) |
|||
@Service("EntityViewCache") |
|||
public class EntityViewCaffeineCache extends CaffeineTbTransactionalCache<EntityViewCacheKey, EntityViewCacheValue> { |
|||
|
|||
public EntityViewCaffeineCache(CacheManager cacheManager) { |
|||
super(cacheManager, CacheConstants.ENTITY_VIEW_CACHE); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entityview; |
|||
|
|||
import lombok.Data; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.EntityViewId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
@Data |
|||
@RequiredArgsConstructor |
|||
class EntityViewEvictEvent { |
|||
|
|||
private final TenantId tenantId; |
|||
private final EntityViewId id; |
|||
private final EntityId newEntityId; |
|||
private final EntityId oldEntityId; |
|||
private final String newName; |
|||
private final String oldName; |
|||
|
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entityview; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.cache.CacheSpecsMap; |
|||
import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
|||
import org.thingsboard.server.common.data.CacheConstants; |
|||
import org.thingsboard.server.cache.RedisTbTransactionalCache; |
|||
import org.thingsboard.server.cache.TbRedisSerializer; |
|||
|
|||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") |
|||
@Service("EntityViewCache") |
|||
public class EntityViewRedisCache extends RedisTbTransactionalCache<EntityViewCacheKey, EntityViewCacheValue> { |
|||
|
|||
public EntityViewRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { |
|||
super(CacheConstants.ENTITY_VIEW_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue