Browse Source

OTA Package cache

pull/6536/head
Andrii Shvaika 4 years ago
parent
commit
ffe5b5ee91
  1. 2
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
  2. 1
      dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java
  3. 45
      dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java
  4. 29
      dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCacheEvictEvent.java
  5. 41
      dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCacheKey.java
  6. 35
      dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCaffeineCache.java
  7. 37
      dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageRedisCache.java

2
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -292,7 +292,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
} }
private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover = private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover =
new PaginatedRemover<TenantId, DeviceProfile>() { new PaginatedRemover<>() {
@Override @Override
protected PageData<DeviceProfile> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) { protected PageData<DeviceProfile> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {

1
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java

@ -133,7 +133,6 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
return edgeDao.findByIdAsync(tenantId, edgeId.getId()); return edgeDao.findByIdAsync(tenantId, edgeId.getId());
} }
@Cacheable(cacheNames = EDGE_CACHE, key = "{#tenantId, #name}")
@Override @Override
public Edge findEdgeByTenantIdAndName(TenantId tenantId, String name) { public Edge findEdgeByTenantIdAndName(TenantId tenantId, String name) {
log.trace("Executing findEdgeByTenantIdAndName [{}][{}]", tenantId, name); log.trace("Executing findEdgeByTenantIdAndName [{}][{}]", tenantId, name);

45
dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java

@ -21,10 +21,10 @@ import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.server.cache.ota.OtaPackageDataCache; import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.OtaPackage; import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo; import org.thingsboard.server.common.data.OtaPackageInfo;
@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.entity.AbstractCachedEntityService;
import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.service.PaginatedRemover;
@ -45,39 +46,44 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_CACHE;
import static org.thingsboard.server.dao.service.Validator.validateId; import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validatePageLink; import static org.thingsboard.server.dao.service.Validator.validatePageLink;
@Service @Service
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
public class BaseOtaPackageService implements OtaPackageService { public class BaseOtaPackageService extends AbstractCachedEntityService<OtaPackageCacheKey, OtaPackageInfo, OtaPackageCacheEvictEvent> implements OtaPackageService {
public static final String INCORRECT_OTA_PACKAGE_ID = "Incorrect otaPackageId "; public static final String INCORRECT_OTA_PACKAGE_ID = "Incorrect otaPackageId ";
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
private final OtaPackageDao otaPackageDao; private final OtaPackageDao otaPackageDao;
private final OtaPackageInfoDao otaPackageInfoDao; private final OtaPackageInfoDao otaPackageInfoDao;
private final CacheManager cacheManager;
private final OtaPackageDataCache otaPackageDataCache; private final OtaPackageDataCache otaPackageDataCache;
private final DataValidator<OtaPackageInfo> otaPackageInfoValidator; private final DataValidator<OtaPackageInfo> otaPackageInfoValidator;
private final DataValidator<OtaPackage> otaPackageValidator; private final DataValidator<OtaPackage> otaPackageValidator;
@TransactionalEventListener(classes = OtaPackageCacheEvictEvent.class)
@Override
public void handleEvictEvent(OtaPackageCacheEvictEvent event) {
cache.evict(new OtaPackageCacheKey(event.getId()));
otaPackageDataCache.evict(event.getId().toString());
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override @Override
public OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo, boolean isUrl) { public OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo, boolean isUrl) {
log.trace("Executing saveOtaPackageInfo [{}]", otaPackageInfo); log.trace("Executing saveOtaPackageInfo [{}]", otaPackageInfo);
if(isUrl && (StringUtils.isEmpty(otaPackageInfo.getUrl()) || otaPackageInfo.getUrl().trim().length() == 0)) { if (isUrl && (StringUtils.isEmpty(otaPackageInfo.getUrl()) || otaPackageInfo.getUrl().trim().length() == 0)) {
throw new DataValidationException("Ota package URL should be specified!"); throw new DataValidationException("Ota package URL should be specified!");
} }
otaPackageInfoValidator.validate(otaPackageInfo, OtaPackageInfo::getTenantId); otaPackageInfoValidator.validate(otaPackageInfo, OtaPackageInfo::getTenantId);
try { try {
OtaPackageId otaPackageId = otaPackageInfo.getId(); OtaPackageId otaPackageId = otaPackageInfo.getId();
var result = otaPackageInfoDao.save(otaPackageInfo.getTenantId(), otaPackageInfo);
if (otaPackageId != null) { if (otaPackageId != null) {
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE); publishEvictEvent(new OtaPackageCacheEvictEvent(otaPackageId));
cache.evict(toOtaPackageInfoKey(otaPackageId));
otaPackageDataCache.evict(otaPackageId.toString());
} }
return otaPackageInfoDao.save(otaPackageInfo.getTenantId(), otaPackageInfo); return result;
} catch (Exception t) { } catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) { if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) {
@ -88,18 +94,18 @@ public class BaseOtaPackageService implements OtaPackageService {
} }
} }
@Transactional(propagation = Propagation.SUPPORTS)
@Override @Override
public OtaPackage saveOtaPackage(OtaPackage otaPackage) { public OtaPackage saveOtaPackage(OtaPackage otaPackage) {
log.trace("Executing saveOtaPackage [{}]", otaPackage); log.trace("Executing saveOtaPackage [{}]", otaPackage);
otaPackageValidator.validate(otaPackage, OtaPackageInfo::getTenantId); otaPackageValidator.validate(otaPackage, OtaPackageInfo::getTenantId);
try { try {
OtaPackageId otaPackageId = otaPackage.getId(); OtaPackageId otaPackageId = otaPackage.getId();
var result = otaPackageDao.save(otaPackage.getTenantId(), otaPackage);
if (otaPackageId != null) { if (otaPackageId != null) {
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE); publishEvictEvent(new OtaPackageCacheEvictEvent(otaPackageId));
cache.evict(toOtaPackageInfoKey(otaPackageId));
otaPackageDataCache.evict(otaPackageId.toString());
} }
return otaPackageDao.save(otaPackage.getTenantId(), otaPackage); return result;
} catch (Exception t) { } catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) { if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) {
@ -149,11 +155,11 @@ public class BaseOtaPackageService implements OtaPackageService {
} }
@Override @Override
@Cacheable(cacheNames = OTA_PACKAGE_CACHE, key = "{#otaPackageId}")
public OtaPackageInfo findOtaPackageInfoById(TenantId tenantId, OtaPackageId otaPackageId) { public OtaPackageInfo findOtaPackageInfoById(TenantId tenantId, OtaPackageId otaPackageId) {
log.trace("Executing findOtaPackageInfoById [{}]", otaPackageId); log.trace("Executing findOtaPackageInfoById [{}]", otaPackageId);
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId); validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId);
return otaPackageInfoDao.findById(tenantId, otaPackageId.getId()); return cache.getAndPutInTransaction(new OtaPackageCacheKey(otaPackageId),
() -> otaPackageInfoDao.findById(tenantId, otaPackageId.getId()), true);
} }
@Override @Override
@ -179,15 +185,14 @@ public class BaseOtaPackageService implements OtaPackageService {
return otaPackageInfoDao.findOtaPackageInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, otaPackageType, pageLink); return otaPackageInfoDao.findOtaPackageInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, otaPackageType, pageLink);
} }
@Transactional(propagation = Propagation.SUPPORTS)
@Override @Override
public void deleteOtaPackage(TenantId tenantId, OtaPackageId otaPackageId) { public void deleteOtaPackage(TenantId tenantId, OtaPackageId otaPackageId) {
log.trace("Executing deleteOtaPackage [{}]", otaPackageId); log.trace("Executing deleteOtaPackage [{}]", otaPackageId);
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId); validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId);
try { try {
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE);
cache.evict(toOtaPackageInfoKey(otaPackageId));
otaPackageDataCache.evict(otaPackageId.toString());
otaPackageDao.removeById(tenantId, otaPackageId.getId()); otaPackageDao.removeById(tenantId, otaPackageId.getId());
publishEvictEvent(new OtaPackageCacheEvictEvent(otaPackageId));
} catch (Exception t) { } catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device")) { if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device")) {

29
dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCacheEvictEvent.java

@ -0,0 +1,29 @@
/**
* 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.ota;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
@Data
@RequiredArgsConstructor
class OtaPackageCacheEvictEvent {
private final OtaPackageId id;
}

41
dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCacheKey.java

@ -0,0 +1,41 @@
/**
* 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.ota;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serializable;
@Getter
@EqualsAndHashCode
@RequiredArgsConstructor
@Builder
public class OtaPackageCacheKey implements Serializable {
private final OtaPackageId id;
@Override
public String toString() {
return id.getId().toString();
}
}

35
dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCaffeineCache.java

@ -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.ota;
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.OtaPackageInfo;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.dao.asset.AssetCacheKey;
import org.thingsboard.server.dao.cache.CaffeineTbTransactionalCache;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@Service("OtaPackageCache")
public class OtaPackageCaffeineCache extends CaffeineTbTransactionalCache<OtaPackageCacheKey, OtaPackageInfo> {
public OtaPackageCaffeineCache(CacheManager cacheManager) {
super(cacheManager, CacheConstants.OTA_PACKAGE_CACHE);
}
}

37
dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageRedisCache.java

@ -0,0 +1,37 @@
/**
* 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.ota;
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.OtaPackageInfo;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.dao.asset.AssetCacheKey;
import org.thingsboard.server.dao.cache.RedisTbTransactionalCache;
import org.thingsboard.server.dao.cache.TbRedisSerializer;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@Service("OtaPackageCache")
public class OtaPackageRedisCache extends RedisTbTransactionalCache<OtaPackageCacheKey, OtaPackageInfo> {
public OtaPackageRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.OTA_PACKAGE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>());
}
}
Loading…
Cancel
Save