added tenant cache
This commit is contained in:
parent
e61bfea55e
commit
2b18b44a52
@ -15,7 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.dao.service.validator;
|
package org.thingsboard.server.dao.service.validator;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.thingsboard.server.common.data.ApiUsageState;
|
import org.thingsboard.server.common.data.ApiUsageState;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
@ -25,10 +26,11 @@ import org.thingsboard.server.dao.service.DataValidator;
|
|||||||
import org.thingsboard.server.dao.tenant.TenantService;
|
import org.thingsboard.server.dao.tenant.TenantService;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@AllArgsConstructor
|
|
||||||
public class ApiUsageDataValidator extends DataValidator<ApiUsageState> {
|
public class ApiUsageDataValidator extends DataValidator<ApiUsageState> {
|
||||||
|
|
||||||
private final TenantService tenantService;
|
@Lazy
|
||||||
|
@Autowired
|
||||||
|
private TenantService tenantService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void validateDataImpl(TenantId requestTenantId, ApiUsageState apiUsageState) {
|
protected void validateDataImpl(TenantId requestTenantId, ApiUsageState apiUsageState) {
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.thingsboard.server.common.data.Customer;
|
import org.thingsboard.server.common.data.Customer;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
|
||||||
import org.thingsboard.server.common.data.User;
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.id.CustomerId;
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
@ -32,7 +31,6 @@ import org.thingsboard.server.dao.exception.DataValidationException;
|
|||||||
import org.thingsboard.server.dao.model.ModelConstants;
|
import org.thingsboard.server.dao.model.ModelConstants;
|
||||||
import org.thingsboard.server.dao.service.DataValidator;
|
import org.thingsboard.server.dao.service.DataValidator;
|
||||||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
||||||
import org.thingsboard.server.dao.tenant.TenantDao;
|
|
||||||
import org.thingsboard.server.dao.tenant.TenantService;
|
import org.thingsboard.server.dao.tenant.TenantService;
|
||||||
import org.thingsboard.server.dao.user.UserDao;
|
import org.thingsboard.server.dao.user.UserDao;
|
||||||
import org.thingsboard.server.dao.user.UserService;
|
import org.thingsboard.server.dao.user.UserService;
|
||||||
@ -55,6 +53,7 @@ public class UserDataValidator extends DataValidator<User> {
|
|||||||
private TbTenantProfileCache tenantProfileCache;
|
private TbTenantProfileCache tenantProfileCache;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Lazy
|
||||||
private TenantService tenantService;
|
private TenantService tenantService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.tenant;
|
||||||
|
|
||||||
|
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.Tenant;
|
||||||
|
|
||||||
|
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
|
||||||
|
@Service("TenantCache")
|
||||||
|
public class TenantCaffeineCache extends CaffeineTbTransactionalCache<TenantCacheKey, Tenant> {
|
||||||
|
|
||||||
|
public TenantCaffeineCache(CacheManager cacheManager) {
|
||||||
|
super(cacheManager, CacheConstants.TENANTS_CACHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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.Data;
|
||||||
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TenantEvictEvent {
|
||||||
|
private final TenantId tenantId;
|
||||||
|
// for exists tenant cache
|
||||||
|
private final boolean isExistsTenant;
|
||||||
|
}
|
||||||
@ -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.tenant;
|
||||||
|
|
||||||
|
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.Tenant;
|
||||||
|
|
||||||
|
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
|
||||||
|
@Service("TenantExistsCache")
|
||||||
|
public class TenantExistsCaffeineCache extends CaffeineTbTransactionalCache<TenantCacheKey, Boolean> {
|
||||||
|
|
||||||
|
public TenantExistsCaffeineCache(CacheManager cacheManager) {
|
||||||
|
super(cacheManager, CacheConstants.TENANTS_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.tenant;
|
||||||
|
|
||||||
|
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.Tenant;
|
||||||
|
|
||||||
|
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
|
||||||
|
@Service("TenantExistsCache")
|
||||||
|
public class TenantExistsRedisCache extends RedisTbTransactionalCache<TenantCacheKey, Boolean> {
|
||||||
|
|
||||||
|
public TenantExistsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
|
||||||
|
super(CacheConstants.TENANTS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.tenant;
|
||||||
|
|
||||||
|
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.Tenant;
|
||||||
|
|
||||||
|
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
|
||||||
|
@Service("TenantCache")
|
||||||
|
public class TenantRedisCache extends RedisTbTransactionalCache<TenantCacheKey, Tenant> {
|
||||||
|
|
||||||
|
public TenantRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
|
||||||
|
super(CacheConstants.TENANTS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,12 +18,11 @@ package org.thingsboard.server.dao.tenant;
|
|||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.cache.annotation.Caching;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
|
import org.thingsboard.server.cache.TbTransactionalCache;
|
||||||
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.TenantInfo;
|
||||||
import org.thingsboard.server.common.data.TenantProfile;
|
import org.thingsboard.server.common.data.TenantProfile;
|
||||||
@ -36,7 +35,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
|
|||||||
import org.thingsboard.server.dao.dashboard.DashboardService;
|
import org.thingsboard.server.dao.dashboard.DashboardService;
|
||||||
import org.thingsboard.server.dao.device.DeviceProfileService;
|
import org.thingsboard.server.dao.device.DeviceProfileService;
|
||||||
import org.thingsboard.server.dao.device.DeviceService;
|
import org.thingsboard.server.dao.device.DeviceService;
|
||||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
|
import org.thingsboard.server.dao.entity.AbstractCachedEntityService;
|
||||||
import org.thingsboard.server.dao.ota.OtaPackageService;
|
import org.thingsboard.server.dao.ota.OtaPackageService;
|
||||||
import org.thingsboard.server.dao.queue.QueueService;
|
import org.thingsboard.server.dao.queue.QueueService;
|
||||||
import org.thingsboard.server.dao.resource.ResourceService;
|
import org.thingsboard.server.dao.resource.ResourceService;
|
||||||
@ -51,12 +50,11 @@ import org.thingsboard.server.dao.widget.WidgetsBundleService;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.thingsboard.server.common.data.CacheConstants.TENANTS_CACHE;
|
|
||||||
import static org.thingsboard.server.dao.service.Validator.validateId;
|
import static org.thingsboard.server.dao.service.Validator.validateId;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class TenantServiceImpl extends AbstractEntityService implements TenantService {
|
public class TenantServiceImpl extends AbstractCachedEntityService<TenantCacheKey, 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 ";
|
||||||
@ -83,6 +81,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeviceProfileService deviceProfileService;
|
private DeviceProfileService deviceProfileService;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApiUsageStateService apiUsageStateService;
|
private ApiUsageStateService apiUsageStateService;
|
||||||
|
|
||||||
@ -110,12 +109,26 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
|
|||||||
@Autowired
|
@Autowired
|
||||||
private QueueService queueService;
|
private QueueService queueService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected TbTransactionalCache<TenantCacheKey, Boolean> existsTenantCache;
|
||||||
|
|
||||||
|
@TransactionalEventListener(classes = TenantEvictEvent.class)
|
||||||
|
@Override
|
||||||
|
public void handleEvictEvent(TenantEvictEvent event) {
|
||||||
|
TenantId tenantId = event.getTenantId();
|
||||||
|
cache.evict(TenantCacheKey.fromId(tenantId));
|
||||||
|
if (event.isExistsTenant()) {
|
||||||
|
existsTenantCache.evict(TenantCacheKey.fromIdExists(tenantId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Cacheable(cacheNames = TENANTS_CACHE, key = "{#tenantId, 'TENANT'}")
|
|
||||||
public Tenant findTenantById(TenantId tenantId) {
|
public Tenant findTenantById(TenantId tenantId) {
|
||||||
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 tenantDao.findById(tenantId, tenantId.getId());
|
|
||||||
|
return cache.getAndPutInTransaction(TenantCacheKey.fromId(tenantId),
|
||||||
|
() -> tenantDao.findById(tenantId, tenantId.getId()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,7 +147,6 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
@CacheEvict(cacheNames = TENANTS_CACHE, key = "{#tenant.id, 'TENANT'}", condition = "#tenant.id!=null")
|
|
||||||
public Tenant saveTenant(Tenant tenant) {
|
public Tenant saveTenant(Tenant tenant) {
|
||||||
log.trace("Executing saveTenant [{}]", tenant);
|
log.trace("Executing saveTenant [{}]", tenant);
|
||||||
tenant.setRegion(DEFAULT_TENANT_REGION);
|
tenant.setRegion(DEFAULT_TENANT_REGION);
|
||||||
@ -144,6 +156,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
|
|||||||
}
|
}
|
||||||
tenantValidator.validate(tenant, Tenant::getId);
|
tenantValidator.validate(tenant, Tenant::getId);
|
||||||
Tenant savedTenant = tenantDao.save(tenant.getId(), tenant);
|
Tenant savedTenant = tenantDao.save(tenant.getId(), tenant);
|
||||||
|
publishEvictEvent(new TenantEvictEvent(savedTenant.getId(), false));
|
||||||
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);
|
||||||
@ -153,10 +166,6 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(timeout = 60 * 60)
|
@Transactional(timeout = 60 * 60)
|
||||||
@Caching(evict = {
|
|
||||||
@CacheEvict(cacheNames = TENANTS_CACHE, key = "{#tenantId, 'TENANT'}"),
|
|
||||||
@CacheEvict(cacheNames = TENANTS_CACHE, key = "{#tenantId, 'EXISTS'}")
|
|
||||||
})
|
|
||||||
public void deleteTenant(TenantId tenantId) {
|
public void deleteTenant(TenantId tenantId) {
|
||||||
log.trace("Executing deleteTenant [{}]", tenantId);
|
log.trace("Executing deleteTenant [{}]", tenantId);
|
||||||
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
|
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
|
||||||
@ -176,6 +185,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
|
|||||||
rpcService.deleteAllRpcByTenantId(tenantId);
|
rpcService.deleteAllRpcByTenantId(tenantId);
|
||||||
queueService.deleteQueuesByTenantId(tenantId);
|
queueService.deleteQueuesByTenantId(tenantId);
|
||||||
tenantDao.removeById(tenantId, tenantId.getId());
|
tenantDao.removeById(tenantId, tenantId.getId());
|
||||||
|
publishEvictEvent(new TenantEvictEvent(tenantId, true));
|
||||||
deleteEntityRelations(tenantId, tenantId);
|
deleteEntityRelations(tenantId, tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,9 +222,10 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
|
|||||||
return tenantDao.findTenantsIds(pageLink);
|
return tenantDao.findTenantsIds(pageLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Cacheable(cacheNames = TENANTS_CACHE, key = "{#tenantId, 'EXISTS'}")
|
@Override
|
||||||
public boolean tenantExists(TenantId tenantId) {
|
public boolean tenantExists(TenantId tenantId) {
|
||||||
return tenantDao.existsById(tenantId, tenantId.getId());
|
return existsTenantCache.getAndPutInTransaction(TenantCacheKey.fromIdExists(tenantId),
|
||||||
|
() -> tenantDao.existsById(tenantId, tenantId.getId()), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PaginatedRemover<TenantId, Tenant> tenantsRemover = new PaginatedRemover<>() {
|
private PaginatedRemover<TenantId, Tenant> tenantsRemover = new PaginatedRemover<>() {
|
||||||
|
|||||||
@ -25,6 +25,8 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
|
|||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.CacheManager;
|
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.common.data.CacheConstants;
|
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;
|
||||||
@ -59,6 +61,7 @@ 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;
|
||||||
@ -80,14 +83,10 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
|
|||||||
protected TenantDao tenantDao;
|
protected TenantDao tenantDao;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
CacheManager cacheManager;
|
protected TbTransactionalCache<TenantCacheKey, Tenant> cache;
|
||||||
|
|
||||||
private Cache tenantCache;
|
@Autowired
|
||||||
|
protected TbTransactionalCache<TenantCacheKey, Boolean> existsTenantCache;
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
tenantCache = cacheManager.getCache(CacheConstants.TENANTS_CACHE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSaveTenant() {
|
public void testSaveTenant() {
|
||||||
@ -155,7 +154,6 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFindTenants() {
|
public void testFindTenants() {
|
||||||
|
|
||||||
List<Tenant> tenants = new ArrayList<>();
|
List<Tenant> tenants = new ArrayList<>();
|
||||||
PageLink pageLink = new PageLink(17);
|
PageLink pageLink = new PageLink(17);
|
||||||
PageData<Tenant> pageData = tenantService.findTenants(pageLink);
|
PageData<Tenant> pageData = tenantService.findTenants(pageLink);
|
||||||
@ -335,15 +333,14 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
|
|||||||
Tenant savedTenant = tenantService.saveTenant(tenant);
|
Tenant savedTenant = tenantService.saveTenant(tenant);
|
||||||
|
|
||||||
Mockito.reset(tenantDao);
|
Mockito.reset(tenantDao);
|
||||||
Objects.requireNonNull(tenantCache, "Tenant cache manager is null").evict(List.of(savedTenant.getId(), "TENANT"));
|
|
||||||
|
|
||||||
verify(tenantDao, Mockito.times(0)).findById(any(), any());
|
verify(tenantDao, Mockito.times(0)).findById(any(), any());
|
||||||
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()));
|
||||||
|
|
||||||
Cache.ValueWrapper cachedTenant =
|
var cachedTenant = cache.get(TenantCacheKey.fromId(savedTenant.getId()));
|
||||||
Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "TENANT"));
|
|
||||||
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());
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
tenantService.findTenantById(savedTenant.getId());
|
tenantService.findTenantById(savedTenant.getId());
|
||||||
@ -360,15 +357,15 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
|
|||||||
Tenant savedTenant = tenantService.saveTenant(tenant);
|
Tenant savedTenant = tenantService.saveTenant(tenant);
|
||||||
|
|
||||||
Mockito.reset(tenantDao);
|
Mockito.reset(tenantDao);
|
||||||
tenantCache.clear();
|
//fromIdExists invoked from device profile validator
|
||||||
|
existsTenantCache.evict(TenantCacheKey.fromIdExists(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()));
|
||||||
|
|
||||||
Cache.ValueWrapper cachedExists =
|
var isExists = existsTenantCache.get(TenantCacheKey.fromIdExists(savedTenant.getId()));
|
||||||
Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "EXISTS"));
|
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!", cachedExists);
|
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
tenantService.tenantExists(savedTenant.getId());
|
tenantService.tenantExists(savedTenant.getId());
|
||||||
@ -384,16 +381,18 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
|
|||||||
tenant.setTitle("My tenant");
|
tenant.setTitle("My tenant");
|
||||||
Tenant savedTenant = tenantService.saveTenant(tenant);
|
Tenant savedTenant = tenantService.saveTenant(tenant);
|
||||||
|
|
||||||
Cache.ValueWrapper cachedTenant =
|
tenantService.findTenantById(savedTenant.getId());
|
||||||
Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "TENANT"));
|
|
||||||
|
var cachedTenant = cache.get(TenantCacheKey.fromId(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());
|
||||||
|
|
||||||
savedTenant.setTitle("My new tenant");
|
savedTenant.setTitle("My new tenant");
|
||||||
savedTenant = tenantService.saveTenant(savedTenant);
|
savedTenant = tenantService.saveTenant(savedTenant);
|
||||||
|
|
||||||
Mockito.reset(tenantDao);
|
Mockito.reset(tenantDao);
|
||||||
|
|
||||||
cachedTenant = Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "TENANT"));
|
cachedTenant = cache.get(TenantCacheKey.fromId(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());
|
||||||
@ -409,20 +408,21 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
|
|||||||
tenant.setTitle("My tenant");
|
tenant.setTitle("My tenant");
|
||||||
Tenant savedTenant = tenantService.saveTenant(tenant);
|
Tenant savedTenant = tenantService.saveTenant(tenant);
|
||||||
|
|
||||||
|
tenantService.findTenantById(savedTenant.getId());
|
||||||
tenantService.tenantExists(savedTenant.getId());
|
tenantService.tenantExists(savedTenant.getId());
|
||||||
|
|
||||||
Cache.ValueWrapper cachedTenant =
|
var cachedTenant =
|
||||||
Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "TENANT"));
|
cache.get(TenantCacheKey.fromId(savedTenant.getId()));
|
||||||
Cache.ValueWrapper cachedExists =
|
var cachedExists =
|
||||||
Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "EXISTS"));
|
existsTenantCache.get(TenantCacheKey.fromIdExists(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 =
|
||||||
Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "TENANT"));
|
cache.get(TenantCacheKey.fromId(savedTenant.getId()));
|
||||||
cachedExists =
|
cachedExists =
|
||||||
Objects.requireNonNull(tenantCache, "Cache manager is null!").get(List.of(savedTenant.getId(), "EXISTS"));
|
existsTenantCache.get(TenantCacheKey.fromIdExists(savedTenant.getId()));
|
||||||
|
|
||||||
|
|
||||||
Assert.assertNull("Removing a Tenant doesn't evict the cache!", cachedTenant);
|
Assert.assertNull("Removing a Tenant doesn't evict the cache!", cachedTenant);
|
||||||
|
|||||||
@ -35,8 +35,8 @@ cache.specs.entityViews.maxSize=100000
|
|||||||
cache.specs.claimDevices.timeToLiveInMinutes=1440
|
cache.specs.claimDevices.timeToLiveInMinutes=1440
|
||||||
cache.specs.claimDevices.maxSize=100000
|
cache.specs.claimDevices.maxSize=100000
|
||||||
|
|
||||||
caffeine.specs.tenants.timeToLiveInMinutes=1440
|
cache.specs.tenants.timeToLiveInMinutes=1440
|
||||||
caffeine.specs.tenants.maxSize=100000
|
cache.specs.tenants.maxSize=100000
|
||||||
|
|
||||||
cache.specs.securitySettings.timeToLiveInMinutes=1440
|
cache.specs.securitySettings.timeToLiveInMinutes=1440
|
||||||
cache.specs.securitySettings.maxSize=100000
|
cache.specs.securitySettings.maxSize=100000
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user