Browse Source

Fix tenants and User Update Time cache

pull/6845/head
Andrii Shvaika 4 years ago
parent
commit
18893d9cf3
  1. 16
      application/src/main/java/org/thingsboard/server/service/security/auth/TokenOutdatingService.java
  2. 30
      application/src/main/resources/thingsboard.yml
  3. 15
      application/src/test/java/org/thingsboard/server/service/security/auth/TokenOutdatingTest.java
  4. 3
      common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java
  5. 7
      common/data/src/main/java/org/thingsboard/server/common/data/security/event/UserAuthDataChangedEvent.java
  6. 45
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantCacheKey.java
  7. 3
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantCaffeineCache.java
  8. 3
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantEvictEvent.java
  9. 6
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsCaffeineCache.java
  10. 5
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsRedisCache.java
  11. 3
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantRedisCache.java
  12. 19
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
  13. 99
      dao/src/test/java/org/thingsboard/server/dao/service/BaseTenantServiceTest.java
  14. 3
      dao/src/test/resources/application-test.properties

16
application/src/main/java/org/thingsboard/server/service/security/auth/TokenOutdatingService.java

@ -40,23 +40,23 @@ public class TokenOutdatingService {
private final CacheManager cacheManager; private final CacheManager cacheManager;
private final JwtTokenFactory tokenFactory; private final JwtTokenFactory tokenFactory;
private final JwtSettings jwtSettings; private final JwtSettings jwtSettings;
private Cache tokenOutdatageTimeCache; private Cache usersUpdateTimeCache;
@PostConstruct @PostConstruct
protected void initCache() { protected void initCache() {
tokenOutdatageTimeCache = cacheManager.getCache(CacheConstants.TOKEN_OUTDATAGE_TIME_CACHE); usersUpdateTimeCache = cacheManager.getCache(CacheConstants.USERS_UPDATE_TIME_CACHE);
} }
@EventListener(classes = UserAuthDataChangedEvent.class) @EventListener(classes = UserAuthDataChangedEvent.class)
public void onUserAuthDataChanged(UserAuthDataChangedEvent userAuthDataChangedEvent) { public void onUserAuthDataChanged(UserAuthDataChangedEvent event) {
outdateOldUserTokens(userAuthDataChangedEvent.getUserId()); usersUpdateTimeCache.put(toKey(event.getUserId()), event.getTs());
} }
public boolean isOutdated(JwtToken token, UserId userId) { public boolean isOutdated(JwtToken token, UserId userId) {
Claims claims = tokenFactory.parseTokenClaims(token).getBody(); Claims claims = tokenFactory.parseTokenClaims(token).getBody();
long issueTime = claims.getIssuedAt().getTime(); long issueTime = claims.getIssuedAt().getTime();
return Optional.ofNullable(tokenOutdatageTimeCache.get(toKey(userId), Long.class)) return Optional.ofNullable(usersUpdateTimeCache.get(toKey(userId), Long.class))
.map(outdatageTime -> { .map(outdatageTime -> {
if (System.currentTimeMillis() - outdatageTime <= SECONDS.toMillis(jwtSettings.getRefreshTokenExpTime())) { if (System.currentTimeMillis() - outdatageTime <= SECONDS.toMillis(jwtSettings.getRefreshTokenExpTime())) {
return MILLISECONDS.toSeconds(issueTime) < MILLISECONDS.toSeconds(outdatageTime); return MILLISECONDS.toSeconds(issueTime) < MILLISECONDS.toSeconds(outdatageTime);
@ -68,17 +68,13 @@ public class TokenOutdatingService {
* as all the tokens issued before the outdatage time * as all the tokens issued before the outdatage time
* are now expired by themselves * are now expired by themselves
* */ * */
tokenOutdatageTimeCache.evict(toKey(userId)); usersUpdateTimeCache.evict(toKey(userId));
return false; return false;
} }
}) })
.orElse(false); .orElse(false);
} }
public void outdateOldUserTokens(UserId userId) {
tokenOutdatageTimeCache.put(toKey(userId), System.currentTimeMillis());
}
private String toKey(UserId userId) { private String toKey(UserId userId) {
return userId.getId().toString(); return userId.getId().toString();
} }

30
application/src/main/resources/thingsboard.yml

@ -28,7 +28,7 @@ server:
# Server SSL credentials # Server SSL credentials
credentials: credentials:
# Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
type: "${SSL_CREDENTIALS_TYPE:PEM}" type: "${SSL_CREDENTIALS_TYPE:PEM}"
# PEM server credentials # PEM server credentials
pem: pem:
# Path to the server certificate file (holds server certificate or certificate chain, may include server private key) # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
@ -397,15 +397,19 @@ cache:
tenants: tenants:
timeToLiveInMinutes: "${CACHE_SPECS_TENANTS_TTL:1440}" timeToLiveInMinutes: "${CACHE_SPECS_TENANTS_TTL:1440}"
maxSize: "${CACHE_SPECS_TENANTS_MAX_SIZE:10000}" maxSize: "${CACHE_SPECS_TENANTS_MAX_SIZE:10000}"
tenantsExist:
# environment variables are intentionally the same as in 'tenants' cache to be equal.
timeToLiveInMinutes: "${CACHE_SPECS_TENANTS_TTL:1440}"
maxSize: "${CACHE_SPECS_TENANTS_MAX_SIZE:10000}"
deviceProfiles: deviceProfiles:
timeToLiveInMinutes: "${CACHE_SPECS_DEVICE_PROFILES_TTL:1440}" timeToLiveInMinutes: "${CACHE_SPECS_DEVICE_PROFILES_TTL:1440}"
maxSize: "${CACHE_SPECS_DEVICE_PROFILES_MAX_SIZE:10000}" maxSize: "${CACHE_SPECS_DEVICE_PROFILES_MAX_SIZE:10000}"
attributes: attributes:
timeToLiveInMinutes: "${CACHE_SPECS_ATTRIBUTES_TTL:1440}" timeToLiveInMinutes: "${CACHE_SPECS_ATTRIBUTES_TTL:1440}"
maxSize: "${CACHE_SPECS_ATTRIBUTES_MAX_SIZE:100000}" maxSize: "${CACHE_SPECS_ATTRIBUTES_MAX_SIZE:100000}"
tokensOutdatageTime: usersUpdateTime:
timeToLiveInMinutes: "${CACHE_SPECS_TOKENS_OUTDATAGE_TIME_TTL:20000}" timeToLiveInMinutes: "${CACHE_SPECS_USERS_UPDATE_TIME_TTL:20000}"
maxSize: "${CACHE_SPECS_TOKENS_OUTDATAGE_TIME_MAX_SIZE:10000}" maxSize: "${CACHE_SPECS_USERS_UPDATE_TIME_MAX_SIZE:10000}"
otaPackages: otaPackages:
timeToLiveInMinutes: "${CACHE_SPECS_OTA_PACKAGES_TTL:60}" timeToLiveInMinutes: "${CACHE_SPECS_OTA_PACKAGES_TTL:60}"
maxSize: "${CACHE_SPECS_OTA_PACKAGES_MAX_SIZE:10}" maxSize: "${CACHE_SPECS_OTA_PACKAGES_MAX_SIZE:10}"
@ -669,7 +673,7 @@ transport:
# Server SSL credentials # Server SSL credentials
credentials: credentials:
# Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
type: "${MQTT_SSL_CREDENTIALS_TYPE:PEM}" type: "${MQTT_SSL_CREDENTIALS_TYPE:PEM}"
# PEM server credentials # PEM server credentials
pem: pem:
# Path to the server certificate file (holds server certificate or certificate chain, may include server private key) # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
@ -712,7 +716,7 @@ transport:
# Server DTLS credentials # Server DTLS credentials
credentials: credentials:
# Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}" type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}"
# PEM server credentials # PEM server credentials
pem: pem:
# Path to the server certificate file (holds server certificate or certificate chain, may include server private key) # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
@ -790,7 +794,7 @@ transport:
# Whether to enable LWM2M bootstrap server X509 Certificate/RPK support # Whether to enable LWM2M bootstrap server X509 Certificate/RPK support
enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:false}" enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:false}"
# Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
type: "${LWM2M_BS_CREDENTIALS_TYPE:PEM}" type: "${LWM2M_BS_CREDENTIALS_TYPE:PEM}"
# PEM server credentials # PEM server credentials
pem: pem:
# Path to the server certificate file (holds server certificate or certificate chain, may include server private key) # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
@ -817,7 +821,7 @@ transport:
# Whether to load X509 trust certificates # Whether to load X509 trust certificates
enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:false}" enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:false}"
# Trust certificates store type (PEM - pem certificates file; KEYSTORE - java keystore) # Trust certificates store type (PEM - pem certificates file; KEYSTORE - java keystore)
type: "${LWM2M_TRUST_CREDENTIALS_TYPE:PEM}" type: "${LWM2M_TRUST_CREDENTIALS_TYPE:PEM}"
# PEM certificates # PEM certificates
pem: pem:
# Path to the certificates file (holds trust certificates) # Path to the certificates file (holds trust certificates)
@ -841,8 +845,8 @@ transport:
psm_activity_timer: "${LWM2M_PSM_ACTIVITY_TIMER:10000}" psm_activity_timer: "${LWM2M_PSM_ACTIVITY_TIMER:10000}"
paging_transmission_window: "${LWM2M_PAGING_TRANSMISSION_WINDOW:10000}" paging_transmission_window: "${LWM2M_PAGING_TRANSMISSION_WINDOW:10000}"
network_config: # In this section you can specify custom parameters for LwM2M network configuration and expose the env variables to configure outside network_config: # In this section you can specify custom parameters for LwM2M network configuration and expose the env variables to configure outside
# - key: "PROTOCOL_STAGE_THREAD_COUNT" # - key: "PROTOCOL_STAGE_THREAD_COUNT"
# value: "${LWM2M_PROTOCOL_STAGE_THREAD_COUNT:4}" # value: "${LWM2M_PROTOCOL_STAGE_THREAD_COUNT:4}"
snmp: snmp:
enabled: "${SNMP_ENABLED:true}" enabled: "${SNMP_ENABLED:true}"
response_processing: response_processing:
@ -928,9 +932,9 @@ queue:
tb_version_control: tb_version_control:
- key: max.poll.interval.ms - key: max.poll.interval.ms
value: "${TB_QUEUE_KAFKA_VC_MAX_POLL_INTERVAL_MS:600000}" value: "${TB_QUEUE_KAFKA_VC_MAX_POLL_INTERVAL_MS:600000}"
# tb_rule_engine.sq: # tb_rule_engine.sq:
# - key: max.poll.records # - key: max.poll.records
# value: "${TB_QUEUE_KAFKA_SQ_MAX_POLL_RECORDS:1024}" # value: "${TB_QUEUE_KAFKA_SQ_MAX_POLL_RECORDS:1024}"
other: # In this section you can specify custom parameters for Kafka consumer/producer and expose the env variables to configure outside other: # In this section you can specify custom parameters for Kafka consumer/producer and expose the env variables to configure outside
- key: "request.timeout.ms" # refer to https://docs.confluent.io/platform/current/installation/configuration/producer-configs.html#producerconfigs_request.timeout.ms - key: "request.timeout.ms" # refer to https://docs.confluent.io/platform/current/installation/configuration/producer-configs.html#producerconfigs_request.timeout.ms
value: "${TB_QUEUE_KAFKA_REQUEST_TIMEOUT_MS:30000}" # (30 seconds) value: "${TB_QUEUE_KAFKA_REQUEST_TIMEOUT_MS:30000}" # (30 seconds)

15
application/src/test/java/org/thingsboard/server/service/security/auth/TokenOutdatingTest.java

@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.UserCredentials;
import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEvent;
import org.thingsboard.server.common.data.security.model.JwtToken; import org.thingsboard.server.common.data.security.model.JwtToken;
import org.thingsboard.server.config.JwtSettings; import org.thingsboard.server.config.JwtSettings;
import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.customer.CustomerService;
@ -99,7 +100,7 @@ public class TokenOutdatingTest {
JwtToken jwtToken = createAccessJwtToken(userId); JwtToken jwtToken = createAccessJwtToken(userId);
SECONDS.sleep(1); // need to wait before outdating so that outdatage time is strictly after token issue time SECONDS.sleep(1); // need to wait before outdating so that outdatage time is strictly after token issue time
tokenOutdatingService.outdateOldUserTokens(userId); tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(userId));
assertTrue(tokenOutdatingService.isOutdated(jwtToken, userId)); assertTrue(tokenOutdatingService.isOutdated(jwtToken, userId));
SECONDS.sleep(1); SECONDS.sleep(1);
@ -117,7 +118,7 @@ public class TokenOutdatingTest {
}); });
SECONDS.sleep(1); SECONDS.sleep(1);
tokenOutdatingService.outdateOldUserTokens(userId); tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(userId));
assertThrows(JwtExpiredTokenException.class, () -> { assertThrows(JwtExpiredTokenException.class, () -> {
accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(accessJwtToken)); accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(accessJwtToken));
@ -133,7 +134,7 @@ public class TokenOutdatingTest {
}); });
SECONDS.sleep(1); SECONDS.sleep(1);
tokenOutdatingService.outdateOldUserTokens(userId); tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(userId));
assertThrows(CredentialsExpiredException.class, () -> { assertThrows(CredentialsExpiredException.class, () -> {
refreshTokenAuthenticationProvider.authenticate(new RefreshAuthenticationToken(refreshJwtToken)); refreshTokenAuthenticationProvider.authenticate(new RefreshAuthenticationToken(refreshJwtToken));
@ -145,20 +146,20 @@ public class TokenOutdatingTest {
JwtToken jwtToken = createAccessJwtToken(userId); JwtToken jwtToken = createAccessJwtToken(userId);
SECONDS.sleep(1); SECONDS.sleep(1);
tokenOutdatingService.outdateOldUserTokens(userId); tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(userId));
int refreshTokenExpirationTime = 5; int refreshTokenExpirationTime = 3;
jwtSettings.setRefreshTokenExpTime(refreshTokenExpirationTime); jwtSettings.setRefreshTokenExpTime(refreshTokenExpirationTime);
SECONDS.sleep(refreshTokenExpirationTime - 2); SECONDS.sleep(refreshTokenExpirationTime - 2);
assertTrue(tokenOutdatingService.isOutdated(jwtToken, userId)); assertTrue(tokenOutdatingService.isOutdated(jwtToken, userId));
assertNotNull(cacheManager.getCache(CacheConstants.TOKEN_OUTDATAGE_TIME_CACHE).get(userId.getId().toString())); assertNotNull(cacheManager.getCache(CacheConstants.USERS_UPDATE_TIME_CACHE).get(userId.getId().toString()));
SECONDS.sleep(3); SECONDS.sleep(3);
assertFalse(tokenOutdatingService.isOutdated(jwtToken, userId)); assertFalse(tokenOutdatingService.isOutdated(jwtToken, userId));
assertNull(cacheManager.getCache(CacheConstants.TOKEN_OUTDATAGE_TIME_CACHE).get(userId.getId().toString())); assertNull(cacheManager.getCache(CacheConstants.USERS_UPDATE_TIME_CACHE).get(userId.getId().toString()));
} }
private JwtToken createAccessJwtToken(UserId userId) { private JwtToken createAccessJwtToken(UserId userId) {

3
common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java

@ -27,9 +27,10 @@ public class CacheConstants {
public static final String SECURITY_SETTINGS_CACHE = "securitySettings"; public static final String SECURITY_SETTINGS_CACHE = "securitySettings";
public static final String TENANT_PROFILE_CACHE = "tenantProfiles"; public static final String TENANT_PROFILE_CACHE = "tenantProfiles";
public static final String TENANTS_CACHE = "tenants"; public static final String TENANTS_CACHE = "tenants";
public static final String TENANTS_EXIST_CACHE = "tenantsExist";
public static final String DEVICE_PROFILE_CACHE = "deviceProfiles"; public static final String DEVICE_PROFILE_CACHE = "deviceProfiles";
public static final String ATTRIBUTES_CACHE = "attributes"; public static final String ATTRIBUTES_CACHE = "attributes";
public static final String TOKEN_OUTDATAGE_TIME_CACHE = "tokensOutdatageTime"; public static final String USERS_UPDATE_TIME_CACHE = "usersUpdateTime";
public static final String OTA_PACKAGE_CACHE = "otaPackages"; public static final String OTA_PACKAGE_CACHE = "otaPackages";
public static final String OTA_PACKAGE_DATA_CACHE = "otaPackagesData"; public static final String OTA_PACKAGE_DATA_CACHE = "otaPackagesData";
public static final String REPOSITORY_SETTINGS_CACHE = "repositorySettings"; public static final String REPOSITORY_SETTINGS_CACHE = "repositorySettings";

7
common/data/src/main/java/org/thingsboard/server/common/data/security/event/UserAuthDataChangedEvent.java

@ -15,16 +15,17 @@
*/ */
package org.thingsboard.server.common.data.security.event; package org.thingsboard.server.common.data.security.event;
import lombok.Data;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
@Data
public class UserAuthDataChangedEvent { public class UserAuthDataChangedEvent {
private final UserId userId; private final UserId userId;
private final long ts;
public UserAuthDataChangedEvent(UserId userId) { public UserAuthDataChangedEvent(UserId userId) {
this.userId = userId; this.userId = userId;
this.ts = System.currentTimeMillis();
} }
public UserId getUserId() {
return userId;
}
} }

45
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantCacheKey.java

@ -1,45 +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.tenant;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import java.io.Serializable;
@Data
@AllArgsConstructor
public class TenantCacheKey implements Serializable {
private static final long serialVersionUID = -121787454251592384L;
private final TenantId tenantId;
private final TenantCacheKeyPrefix keyPrefix;
public static TenantCacheKey fromId(TenantId tenantId) {
return new TenantCacheKey(tenantId, TenantCacheKeyPrefix.TENANT);
}
public static TenantCacheKey fromIdExists(TenantId tenantId) {
return new TenantCacheKey(tenantId, TenantCacheKeyPrefix.EXISTS);
}
public enum TenantCacheKeyPrefix {
TENANT, EXISTS
}
}

3
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantCaffeineCache.java

@ -21,10 +21,11 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; import org.thingsboard.server.cache.CaffeineTbTransactionalCache;
import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.TenantId;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@Service("TenantCache") @Service("TenantCache")
public class TenantCaffeineCache extends CaffeineTbTransactionalCache<TenantCacheKey, Tenant> { public class TenantCaffeineCache extends CaffeineTbTransactionalCache<TenantId, Tenant> {
public TenantCaffeineCache(CacheManager cacheManager) { public TenantCaffeineCache(CacheManager cacheManager) {
super(cacheManager, CacheConstants.TENANTS_CACHE); super(cacheManager, CacheConstants.TENANTS_CACHE);

3
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantEvictEvent.java

@ -21,6 +21,5 @@ import org.thingsboard.server.common.data.id.TenantId;
@Data @Data
public class TenantEvictEvent { public class TenantEvictEvent {
private final TenantId tenantId; private final TenantId tenantId;
// for exists tenant cache private final boolean invalidateExists;
private final boolean isExistsTenant;
} }

6
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsCaffeineCache.java

@ -21,13 +21,15 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; import org.thingsboard.server.cache.CaffeineTbTransactionalCache;
import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantInfo;
import org.thingsboard.server.common.data.id.TenantId;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@Service("TenantExistsCache") @Service("TenantExistsCache")
public class TenantExistsCaffeineCache extends CaffeineTbTransactionalCache<TenantCacheKey, Boolean> { public class TenantExistsCaffeineCache extends CaffeineTbTransactionalCache<TenantId, Boolean> {
public TenantExistsCaffeineCache(CacheManager cacheManager) { public TenantExistsCaffeineCache(CacheManager cacheManager) {
super(cacheManager, CacheConstants.TENANTS_CACHE); super(cacheManager, CacheConstants.TENANTS_EXIST_CACHE);
} }
} }

5
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsRedisCache.java

@ -23,12 +23,13 @@ import org.thingsboard.server.cache.RedisTbTransactionalCache;
import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.cache.TBRedisCacheConfiguration;
import org.thingsboard.server.cache.TbFSTRedisSerializer; import org.thingsboard.server.cache.TbFSTRedisSerializer;
import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.id.TenantId;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@Service("TenantExistsCache") @Service("TenantExistsCache")
public class TenantExistsRedisCache extends RedisTbTransactionalCache<TenantCacheKey, Boolean> { public class TenantExistsRedisCache extends RedisTbTransactionalCache<TenantId, Boolean> {
public TenantExistsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { public TenantExistsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.TENANTS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); super(CacheConstants.TENANTS_EXIST_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>());
} }
} }

3
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantRedisCache.java

@ -24,10 +24,11 @@ import org.thingsboard.server.cache.TBRedisCacheConfiguration;
import org.thingsboard.server.cache.TbFSTRedisSerializer; import org.thingsboard.server.cache.TbFSTRedisSerializer;
import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.TenantId;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@Service("TenantCache") @Service("TenantCache")
public class TenantRedisCache extends RedisTbTransactionalCache<TenantCacheKey, Tenant> { public class TenantRedisCache extends RedisTbTransactionalCache<TenantId, Tenant> {
public TenantRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { public TenantRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.TENANTS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); super(CacheConstants.TENANTS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>());

19
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java

@ -55,7 +55,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId;
@Service @Service
@Slf4j @Slf4j
public class TenantServiceImpl extends AbstractCachedEntityService<TenantCacheKey, Tenant, TenantEvictEvent> implements TenantService { public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Tenant, TenantEvictEvent> implements TenantService {
private static final String DEFAULT_TENANT_REGION = "Global"; private static final String DEFAULT_TENANT_REGION = "Global";
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
@ -115,15 +115,15 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantCacheKe
private AdminSettingsService adminSettingsService; private AdminSettingsService adminSettingsService;
@Autowired @Autowired
protected TbTransactionalCache<TenantCacheKey, Boolean> existsTenantCache; protected TbTransactionalCache<TenantId, Boolean> existsTenantCache;
@TransactionalEventListener(classes = TenantEvictEvent.class) @TransactionalEventListener(classes = TenantEvictEvent.class)
@Override @Override
public void handleEvictEvent(TenantEvictEvent event) { public void handleEvictEvent(TenantEvictEvent event) {
TenantId tenantId = event.getTenantId(); TenantId tenantId = event.getTenantId();
cache.evict(TenantCacheKey.fromId(tenantId)); cache.evict(tenantId);
if (event.isExistsTenant()) { if (event.isInvalidateExists()) {
existsTenantCache.evict(TenantCacheKey.fromIdExists(tenantId)); existsTenantCache.evict(tenantId);
} }
} }
@ -132,8 +132,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantCacheKe
log.trace("Executing findTenantById [{}]", tenantId); log.trace("Executing findTenantById [{}]", tenantId);
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
return cache.getAndPutInTransaction(TenantCacheKey.fromId(tenantId), return cache.getAndPutInTransaction(tenantId, () -> tenantDao.findById(tenantId, tenantId.getId()), true);
() -> tenantDao.findById(tenantId, tenantId.getId()), true);
} }
@Override @Override
@ -160,8 +159,9 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantCacheKe
tenant.setTenantProfileId(tenantProfile.getId()); tenant.setTenantProfileId(tenantProfile.getId());
} }
tenantValidator.validate(tenant, Tenant::getId); tenantValidator.validate(tenant, Tenant::getId);
boolean create = tenant.getId() == null;
Tenant savedTenant = tenantDao.save(tenant.getId(), tenant); Tenant savedTenant = tenantDao.save(tenant.getId(), tenant);
publishEvictEvent(new TenantEvictEvent(savedTenant.getId(), false)); publishEvictEvent(new TenantEvictEvent(savedTenant.getId(), create));
if (tenant.getId() == null) { if (tenant.getId() == null) {
deviceProfileService.createDefaultDeviceProfile(savedTenant.getId()); deviceProfileService.createDefaultDeviceProfile(savedTenant.getId());
apiUsageStateService.createDefaultApiUsageState(savedTenant.getId(), null); apiUsageStateService.createDefaultApiUsageState(savedTenant.getId(), null);
@ -230,8 +230,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantCacheKe
@Override @Override
public boolean tenantExists(TenantId tenantId) { public boolean tenantExists(TenantId tenantId) {
return existsTenantCache.getAndPutInTransaction(TenantCacheKey.fromIdExists(tenantId), return existsTenantCache.getAndPutInTransaction(tenantId, () -> tenantDao.existsById(tenantId, tenantId.getId()), false);
() -> tenantDao.existsById(tenantId, tenantId.getId()), false);
} }
private PaginatedRemover<TenantId, Tenant> tenantsRemover = new PaginatedRemover<>() { private PaginatedRemover<TenantId, Tenant> tenantsRemover = new PaginatedRemover<>() {

99
dao/src/test/java/org/thingsboard/server/dao/service/BaseTenantServiceTest.java

@ -17,17 +17,12 @@ package org.thingsboard.server.dao.service;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.TbCacheValueWrapper;
import org.thingsboard.server.cache.TbTransactionalCache; import org.thingsboard.server.cache.TbTransactionalCache;
import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.DashboardInfo;
@ -61,19 +56,17 @@ import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileCon
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.tenant.TenantCacheKey;
import org.thingsboard.server.dao.tenant.TenantDao; import org.thingsboard.server.dao.tenant.TenantDao;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.assertj.core.api.Assertions.assertThat;
public abstract class BaseTenantServiceTest extends AbstractServiceTest { public abstract class BaseTenantServiceTest extends AbstractServiceTest {
@ -83,10 +76,10 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
protected TenantDao tenantDao; protected TenantDao tenantDao;
@Autowired @Autowired
protected TbTransactionalCache<TenantCacheKey, Tenant> cache; protected TbTransactionalCache<TenantId, Tenant> cache;
@Autowired @Autowired
protected TbTransactionalCache<TenantCacheKey, Boolean> existsTenantCache; protected TbTransactionalCache<TenantId, Boolean> existsTenantCache;
@Test @Test
public void testSaveTenant() { public void testSaveTenant() {
@ -97,15 +90,15 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Assert.assertNotNull(savedTenant.getId()); Assert.assertNotNull(savedTenant.getId());
Assert.assertTrue(savedTenant.getCreatedTime() > 0); Assert.assertTrue(savedTenant.getCreatedTime() > 0);
Assert.assertEquals(tenant.getTitle(), savedTenant.getTitle()); Assert.assertEquals(tenant.getTitle(), savedTenant.getTitle());
savedTenant.setTitle("My new tenant"); savedTenant.setTitle("My new tenant");
tenantService.saveTenant(savedTenant); tenantService.saveTenant(savedTenant);
Tenant foundTenant = tenantService.findTenantById(savedTenant.getId()); Tenant foundTenant = tenantService.findTenantById(savedTenant.getId());
Assert.assertEquals(foundTenant.getTitle(), savedTenant.getTitle()); Assert.assertEquals(foundTenant.getTitle(), savedTenant.getTitle());
tenantService.deleteTenant(savedTenant.getId()); tenantService.deleteTenant(savedTenant.getId());
} }
@Test @Test
public void testFindTenantById() { public void testFindTenantById() {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
@ -127,13 +120,13 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Assert.assertEquals(new TenantInfo(savedTenant, "Default"), foundTenant); Assert.assertEquals(new TenantInfo(savedTenant, "Default"), foundTenant);
tenantService.deleteTenant(savedTenant.getId()); tenantService.deleteTenant(savedTenant.getId());
} }
@Test(expected = DataValidationException.class) @Test(expected = DataValidationException.class)
public void testSaveTenantWithEmptyTitle() { public void testSaveTenantWithEmptyTitle() {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
tenantService.saveTenant(tenant); tenantService.saveTenant(tenant);
} }
@Test(expected = DataValidationException.class) @Test(expected = DataValidationException.class)
public void testSaveTenantWithInvalidEmail() { public void testSaveTenantWithInvalidEmail() {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
@ -141,7 +134,7 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
tenant.setEmail("invalid@mail"); tenant.setEmail("invalid@mail");
tenantService.saveTenant(tenant); tenantService.saveTenant(tenant);
} }
@Test @Test
public void testDeleteTenant() { public void testDeleteTenant() {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
@ -151,7 +144,7 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Tenant foundTenant = tenantService.findTenantById(savedTenant.getId()); Tenant foundTenant = tenantService.findTenantById(savedTenant.getId());
Assert.assertNull(foundTenant); Assert.assertNull(foundTenant);
} }
@Test @Test
public void testFindTenants() { public void testFindTenants() {
List<Tenant> tenants = new ArrayList<>(); List<Tenant> tenants = new ArrayList<>();
@ -160,13 +153,13 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Assert.assertFalse(pageData.hasNext()); Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty()); Assert.assertTrue(pageData.getData().isEmpty());
tenants.addAll(pageData.getData()); tenants.addAll(pageData.getData());
for (int i=0;i<156;i++) { for (int i = 0; i < 156; i++) {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
tenant.setTitle("Tenant"+i); tenant.setTitle("Tenant" + i);
tenants.add(tenantService.saveTenant(tenant)); tenants.add(tenantService.saveTenant(tenant));
} }
List<Tenant> loadedTenants = new ArrayList<>(); List<Tenant> loadedTenants = new ArrayList<>();
pageLink = new PageLink(17); pageLink = new PageLink(17);
do { do {
@ -176,46 +169,46 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
} }
} while (pageData.hasNext()); } while (pageData.hasNext());
Collections.sort(tenants, idComparator); Collections.sort(tenants, idComparator);
Collections.sort(loadedTenants, idComparator); Collections.sort(loadedTenants, idComparator);
Assert.assertEquals(tenants, loadedTenants); Assert.assertEquals(tenants, loadedTenants);
for (Tenant tenant : loadedTenants) { for (Tenant tenant : loadedTenants) {
tenantService.deleteTenant(tenant.getId()); tenantService.deleteTenant(tenant.getId());
} }
pageLink = new PageLink(17); pageLink = new PageLink(17);
pageData = tenantService.findTenants(pageLink); pageData = tenantService.findTenants(pageLink);
Assert.assertFalse(pageData.hasNext()); Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty()); Assert.assertTrue(pageData.getData().isEmpty());
} }
@Test @Test
public void testFindTenantsByTitle() { public void testFindTenantsByTitle() {
String title1 = "Tenant title 1"; String title1 = "Tenant title 1";
List<Tenant> tenantsTitle1 = new ArrayList<>(); List<Tenant> tenantsTitle1 = new ArrayList<>();
for (int i=0;i<134;i++) { for (int i = 0; i < 134; i++) {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
String suffix = RandomStringUtils.randomAlphanumeric((int)(Math.random()*15)); String suffix = RandomStringUtils.randomAlphanumeric((int) (Math.random() * 15));
String title = title1+suffix; String title = title1 + suffix;
title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase(); title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase();
tenant.setTitle(title); tenant.setTitle(title);
tenantsTitle1.add(tenantService.saveTenant(tenant)); tenantsTitle1.add(tenantService.saveTenant(tenant));
} }
String title2 = "Tenant title 2"; String title2 = "Tenant title 2";
List<Tenant> tenantsTitle2 = new ArrayList<>(); List<Tenant> tenantsTitle2 = new ArrayList<>();
for (int i=0;i<127;i++) { for (int i = 0; i < 127; i++) {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
String suffix = RandomStringUtils.randomAlphanumeric((int)(Math.random()*15)); String suffix = RandomStringUtils.randomAlphanumeric((int) (Math.random() * 15));
String title = title2+suffix; String title = title2 + suffix;
title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase(); title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase();
tenant.setTitle(title); tenant.setTitle(title);
tenantsTitle2.add(tenantService.saveTenant(tenant)); tenantsTitle2.add(tenantService.saveTenant(tenant));
} }
List<Tenant> loadedTenantsTitle1 = new ArrayList<>(); List<Tenant> loadedTenantsTitle1 = new ArrayList<>();
PageLink pageLink = new PageLink(15, 0, title1); PageLink pageLink = new PageLink(15, 0, title1);
PageData<Tenant> pageData = null; PageData<Tenant> pageData = null;
@ -226,12 +219,12 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
} }
} while (pageData.hasNext()); } while (pageData.hasNext());
Collections.sort(tenantsTitle1, idComparator); Collections.sort(tenantsTitle1, idComparator);
Collections.sort(loadedTenantsTitle1, idComparator); Collections.sort(loadedTenantsTitle1, idComparator);
Assert.assertEquals(tenantsTitle1, loadedTenantsTitle1); Assert.assertEquals(tenantsTitle1, loadedTenantsTitle1);
List<Tenant> loadedTenantsTitle2 = new ArrayList<>(); List<Tenant> loadedTenantsTitle2 = new ArrayList<>();
pageLink = new PageLink(4, 0, title2); pageLink = new PageLink(4, 0, title2);
do { do {
@ -244,22 +237,22 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Collections.sort(tenantsTitle2, idComparator); Collections.sort(tenantsTitle2, idComparator);
Collections.sort(loadedTenantsTitle2, idComparator); Collections.sort(loadedTenantsTitle2, idComparator);
Assert.assertEquals(tenantsTitle2, loadedTenantsTitle2); Assert.assertEquals(tenantsTitle2, loadedTenantsTitle2);
for (Tenant tenant : loadedTenantsTitle1) { for (Tenant tenant : loadedTenantsTitle1) {
tenantService.deleteTenant(tenant.getId()); tenantService.deleteTenant(tenant.getId());
} }
pageLink = new PageLink(4, 0, title1); pageLink = new PageLink(4, 0, title1);
pageData = tenantService.findTenants(pageLink); pageData = tenantService.findTenants(pageLink);
Assert.assertFalse(pageData.hasNext()); Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(0, pageData.getData().size()); Assert.assertEquals(0, pageData.getData().size());
for (Tenant tenant : loadedTenantsTitle2) { for (Tenant tenant : loadedTenantsTitle2) {
tenantService.deleteTenant(tenant.getId()); tenantService.deleteTenant(tenant.getId());
} }
pageLink = new PageLink(4, 0, title2); pageLink = new PageLink(4, 0, title2);
pageData = tenantService.findTenants(pageLink); pageData = tenantService.findTenants(pageLink);
Assert.assertFalse(pageData.hasNext()); Assert.assertFalse(pageData.hasNext());
@ -276,9 +269,9 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Assert.assertTrue(pageData.getData().isEmpty()); Assert.assertTrue(pageData.getData().isEmpty());
tenants.addAll(pageData.getData()); tenants.addAll(pageData.getData());
for (int i=0;i<156;i++) { for (int i = 0; i < 156; i++) {
Tenant tenant = new Tenant(); Tenant tenant = new Tenant();
tenant.setTitle("Tenant"+i); tenant.setTitle("Tenant" + i);
tenants.add(new TenantInfo(tenantService.saveTenant(tenant), "Default")); tenants.add(new TenantInfo(tenantService.saveTenant(tenant), "Default"));
} }
@ -338,7 +331,7 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
tenantService.findTenantById(savedTenant.getId()); tenantService.findTenantById(savedTenant.getId());
verify(tenantDao, Mockito.times(1)).findById(eq(savedTenant.getId()), eq(savedTenant.getId().getId())); verify(tenantDao, Mockito.times(1)).findById(eq(savedTenant.getId()), eq(savedTenant.getId().getId()));
var cachedTenant = cache.get(TenantCacheKey.fromId(savedTenant.getId())); var cachedTenant = cache.get(savedTenant.getId());
Assert.assertNotNull("Getting an existing Tenant doesn't add it to the cache!", cachedTenant); Assert.assertNotNull("Getting an existing Tenant doesn't add it to the cache!", cachedTenant);
Assert.assertEquals(savedTenant, cachedTenant.get()); Assert.assertEquals(savedTenant, cachedTenant.get());
@ -358,13 +351,13 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Mockito.reset(tenantDao); Mockito.reset(tenantDao);
//fromIdExists invoked from device profile validator //fromIdExists invoked from device profile validator
existsTenantCache.evict(TenantCacheKey.fromIdExists(savedTenant.getTenantId())); existsTenantCache.evict(savedTenant.getTenantId());
verify(tenantDao, Mockito.times(0)).existsById(any(), any()); verify(tenantDao, Mockito.times(0)).existsById(any(), any());
tenantService.tenantExists(savedTenant.getId()); tenantService.tenantExists(savedTenant.getId());
verify(tenantDao, Mockito.times(1)).existsById(eq(savedTenant.getId()), eq(savedTenant.getId().getId())); verify(tenantDao, Mockito.times(1)).existsById(eq(savedTenant.getId()), eq(savedTenant.getId().getId()));
var isExists = existsTenantCache.get(TenantCacheKey.fromIdExists(savedTenant.getId())); var isExists = existsTenantCache.get(savedTenant.getId());
Assert.assertNotNull("Getting an existing Tenant doesn't add it to the cache!", isExists); Assert.assertNotNull("Getting an existing Tenant doesn't add it to the cache!", isExists);
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
@ -383,7 +376,7 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
tenantService.findTenantById(savedTenant.getId()); tenantService.findTenantById(savedTenant.getId());
var cachedTenant = cache.get(TenantCacheKey.fromId(savedTenant.getId())); var cachedTenant = cache.get(savedTenant.getId());
Assert.assertNotNull("Saving a Tenant doesn't add it to the cache!", cachedTenant); Assert.assertNotNull("Saving a Tenant doesn't add it to the cache!", cachedTenant);
Assert.assertEquals(savedTenant, cachedTenant.get()); Assert.assertEquals(savedTenant, cachedTenant.get());
@ -392,7 +385,7 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
Mockito.reset(tenantDao); Mockito.reset(tenantDao);
cachedTenant = cache.get(TenantCacheKey.fromId(savedTenant.getId())); cachedTenant = cache.get(savedTenant.getId());
Assert.assertNull("Updating a Tenant doesn't evict the cache!", cachedTenant); Assert.assertNull("Updating a Tenant doesn't evict the cache!", cachedTenant);
verify(tenantDao, Mockito.times(0)).findById(any(), any()); verify(tenantDao, Mockito.times(0)).findById(any(), any());
@ -411,18 +404,18 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
tenantService.findTenantById(savedTenant.getId()); tenantService.findTenantById(savedTenant.getId());
tenantService.tenantExists(savedTenant.getId()); tenantService.tenantExists(savedTenant.getId());
var cachedTenant = var cachedTenant =
cache.get(TenantCacheKey.fromId(savedTenant.getId())); cache.get(savedTenant.getId());
var cachedExists = var cachedExists =
existsTenantCache.get(TenantCacheKey.fromIdExists(savedTenant.getId())); existsTenantCache.get(savedTenant.getId());
Assert.assertNotNull("Saving a Tenant doesn't add it to the cache!", cachedTenant); Assert.assertNotNull("Saving a Tenant doesn't add it to the cache!", cachedTenant);
Assert.assertNotNull("Saving a Tenant doesn't add it to the cache!", cachedExists); Assert.assertNotNull("Saving a Tenant doesn't add it to the cache!", cachedExists);
tenantService.deleteTenant(savedTenant.getId()); tenantService.deleteTenant(savedTenant.getId());
cachedTenant = cachedTenant =
cache.get(TenantCacheKey.fromId(savedTenant.getId())); cache.get(savedTenant.getId());
cachedExists = cachedExists =
existsTenantCache.get(TenantCacheKey.fromIdExists(savedTenant.getId())); existsTenantCache.get(savedTenant.getId());
Assert.assertNull("Removing a Tenant doesn't evict the cache!", cachedTenant); Assert.assertNull("Removing a Tenant doesn't evict the cache!", cachedTenant);

3
dao/src/test/resources/application-test.properties

@ -38,6 +38,9 @@ cache.specs.claimDevices.maxSize=100000
cache.specs.tenants.timeToLiveInMinutes=1440 cache.specs.tenants.timeToLiveInMinutes=1440
cache.specs.tenants.maxSize=100000 cache.specs.tenants.maxSize=100000
cache.specs.tenantsExist.timeToLiveInMinutes=1440
cache.specs.tenantsExist.maxSize=100000
cache.specs.securitySettings.timeToLiveInMinutes=1440 cache.specs.securitySettings.timeToLiveInMinutes=1440
cache.specs.securitySettings.maxSize=100000 cache.specs.securitySettings.maxSize=100000

Loading…
Cancel
Save