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