Commit 8b653d7065271c2392a7a5fcd648fc9be06064ae

Authored by Sergey Matvienko
Committed by Andrew Shvayka
1 parent 27788790

rule chain. implemented save/update/delete @Transactional. Added sync DAO method…

…s to run in transaction. Moved loadRuleChainMetaData outside of saveRuleChainMetaData transaction
... ... @@ -244,7 +244,8 @@ public class RuleChainController extends BaseController {
244 244 }
245 245
246 246 RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE);
247   - RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData));
  247 + checkNotNull(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData) ? true : null);
  248 + RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId()));
248 249
249 250 if (RuleChainType.CORE.equals(ruleChain.getType())) {
250 251 tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED);
... ...
... ... @@ -43,7 +43,7 @@ public interface RuleChainService {
43 43
44 44 boolean setRootRuleChain(TenantId tenantId, RuleChainId ruleChainId);
45 45
46   - RuleChainMetaData saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData);
  46 + boolean saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData);
47 47
48 48 RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId);
49 49
... ...
... ... @@ -179,11 +179,28 @@ public class BaseRelationService implements RelationService {
179 179
180 180 @Override
181 181 public void deleteEntityRelations(TenantId tenantId, EntityId entityId) {
182   - try {
183   - deleteEntityRelationsAsync(tenantId, entityId).get();
184   - } catch (InterruptedException | ExecutionException e) {
185   - throw new RuntimeException(e);
  182 + log.trace("Executing deleteEntityRelations [{}]", entityId);
  183 + validate(entityId);
  184 + final Cache cache = cacheManager.getCache(RELATIONS_CACHE);
  185 + List<EntityRelation> inboundRelations = new ArrayList<>();
  186 + for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
  187 + inboundRelations.addAll(relationDao.findAllByTo(tenantId, entityId, typeGroup));
  188 + }
  189 +
  190 + List<EntityRelation> outboundRelations = new ArrayList<>();
  191 + for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
  192 + outboundRelations.addAll(relationDao.findAllByFrom(tenantId, entityId, typeGroup));
  193 + }
  194 +
  195 + for (EntityRelation relation : inboundRelations){
  196 + delete(tenantId, cache, relation, true);
186 197 }
  198 +
  199 + for (EntityRelation relation : outboundRelations){
  200 + delete(tenantId, cache, relation, false);
  201 + }
  202 +
  203 + relationDao.deleteOutboundRelations(tenantId, entityId);
187 204 }
188 205
189 206 @Override
... ... @@ -193,14 +210,14 @@ public class BaseRelationService implements RelationService {
193 210 validate(entityId);
194 211 List<ListenableFuture<List<EntityRelation>>> inboundRelationsList = new ArrayList<>();
195 212 for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
196   - inboundRelationsList.add(relationDao.findAllByTo(tenantId, entityId, typeGroup));
  213 + inboundRelationsList.add(relationDao.findAllByToAsync(tenantId, entityId, typeGroup));
197 214 }
198 215
199 216 ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
200 217
201 218 List<ListenableFuture<List<EntityRelation>>> outboundRelationsList = new ArrayList<>();
202 219 for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
203   - outboundRelationsList.add(relationDao.findAllByFrom(tenantId, entityId, typeGroup));
  220 + outboundRelationsList.add(relationDao.findAllByFromAsync(tenantId, entityId, typeGroup));
204 221 }
205 222
206 223 ListenableFuture<List<List<EntityRelation>>> outboundRelations = Futures.allAsList(outboundRelationsList);
... ... @@ -242,6 +259,15 @@ public class BaseRelationService implements RelationService {
242 259 }
243 260 }
244 261
  262 + boolean delete(TenantId tenantId, Cache cache, EntityRelation relation, boolean deleteFromDb) {
  263 + cacheEviction(relation, cache);
  264 + if (deleteFromDb) {
  265 + return relationDao.deleteRelation(tenantId, relation);
  266 + } else {
  267 + return false;
  268 + }
  269 + }
  270 +
245 271 private void cacheEviction(EntityRelation relation, Cache cache) {
246 272 List<Object> fromToTypeAndTypeGroup = new ArrayList<>();
247 273 fromToTypeAndTypeGroup.add(relation.getFrom());
... ... @@ -283,7 +309,7 @@ public class BaseRelationService implements RelationService {
283 309 validate(from);
284 310 validateTypeGroup(typeGroup);
285 311 try {
286   - return relationDao.findAllByFrom(tenantId, from, typeGroup).get();
  312 + return relationDao.findAllByFromAsync(tenantId, from, typeGroup).get();
287 313 } catch (InterruptedException | ExecutionException e) {
288 314 throw new RuntimeException(e);
289 315 }
... ... @@ -306,7 +332,7 @@ public class BaseRelationService implements RelationService {
306 332 if (fromCache != null) {
307 333 return Futures.immediateFuture(fromCache);
308 334 } else {
309   - ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByFrom(tenantId, from, typeGroup);
  335 + ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByFromAsync(tenantId, from, typeGroup);
310 336 Futures.addCallback(relationsFuture,
311 337 new FutureCallback<List<EntityRelation>>() {
312 338 @Override
... ... @@ -327,7 +353,7 @@ public class BaseRelationService implements RelationService {
327 353 log.trace("Executing findInfoByFrom [{}][{}]", from, typeGroup);
328 354 validate(from);
329 355 validateTypeGroup(typeGroup);
330   - ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByFrom(tenantId, from, typeGroup);
  356 + ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByFromAsync(tenantId, from, typeGroup);
331 357 return Futures.transformAsync(relations,
332 358 relations1 -> {
333 359 List<ListenableFuture<EntityRelationInfo>> futures = new ArrayList<>();
... ... @@ -365,7 +391,7 @@ public class BaseRelationService implements RelationService {
365 391 validate(to);
366 392 validateTypeGroup(typeGroup);
367 393 try {
368   - return relationDao.findAllByTo(tenantId, to, typeGroup).get();
  394 + return relationDao.findAllByToAsync(tenantId, to, typeGroup).get();
369 395 } catch (InterruptedException | ExecutionException e) {
370 396 throw new RuntimeException(e);
371 397 }
... ... @@ -388,7 +414,7 @@ public class BaseRelationService implements RelationService {
388 414 if (fromCache != null) {
389 415 return Futures.immediateFuture(fromCache);
390 416 } else {
391   - ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByTo(tenantId, to, typeGroup);
  417 + ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByToAsync(tenantId, to, typeGroup);
392 418 Futures.addCallback(relationsFuture,
393 419 new FutureCallback<List<EntityRelation>>() {
394 420 @Override
... ... @@ -409,7 +435,7 @@ public class BaseRelationService implements RelationService {
409 435 log.trace("Executing findInfoByTo [{}][{}]", to, typeGroup);
410 436 validate(to);
411 437 validateTypeGroup(typeGroup);
412   - ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByTo(tenantId, to, typeGroup);
  438 + ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAsync(tenantId, to, typeGroup);
413 439 return Futures.transformAsync(relations,
414 440 relations1 -> {
415 441 List<ListenableFuture<EntityRelationInfo>> futures = new ArrayList<>();
... ...
... ... @@ -31,11 +31,15 @@ import java.util.List;
31 31 */
32 32 public interface RelationDao {
33 33
34   - ListenableFuture<List<EntityRelation>> findAllByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup);
  34 + ListenableFuture<List<EntityRelation>> findAllByFromAsync(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup);
  35 +
  36 + List<EntityRelation> findAllByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup);
35 37
36 38 ListenableFuture<List<EntityRelation>> findAllByFromAndType(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup);
37 39
38   - ListenableFuture<List<EntityRelation>> findAllByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup);
  40 + ListenableFuture<List<EntityRelation>> findAllByToAsync(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup);
  41 +
  42 + List<EntityRelation> findAllByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup);
39 43
40 44 ListenableFuture<List<EntityRelation>> findAllByToAndType(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup);
41 45
... ...
... ... @@ -26,6 +26,7 @@ import org.hibernate.exception.ConstraintViolationException;
26 26 import org.springframework.beans.factory.annotation.Autowired;
27 27 import org.springframework.context.annotation.Lazy;
28 28 import org.springframework.stereotype.Service;
  29 +import org.springframework.transaction.annotation.Transactional;
29 30 import org.thingsboard.server.common.data.BaseData;
30 31 import org.thingsboard.server.common.data.EntityType;
31 32 import org.thingsboard.server.common.data.Tenant;
... ... @@ -96,23 +97,19 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
96 97 private TbTenantProfileCache tenantProfileCache;
97 98
98 99 @Override
  100 + @Transactional
99 101 public RuleChain saveRuleChain(RuleChain ruleChain) {
100 102 ruleChainValidator.validate(ruleChain, RuleChain::getTenantId);
101 103 RuleChain savedRuleChain = ruleChainDao.save(ruleChain.getTenantId(), ruleChain);
102 104 if (ruleChain.isRoot() && ruleChain.getId() == null) {
103   - try {
104   - createRelation(ruleChain.getTenantId(), new EntityRelation(savedRuleChain.getTenantId(), savedRuleChain.getId(),
105   - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
106   - } catch (Exception e) {
107   - log.warn("[{}] Failed to create tenant to root rule chain relation. from: [{}], to: [{}]",
108   - savedRuleChain.getTenantId(), savedRuleChain.getTenantId(), savedRuleChain.getId(), e);
109   - throw new RuntimeException(e);
110   - }
  105 + createRelation(ruleChain.getTenantId(), new EntityRelation(savedRuleChain.getTenantId(), savedRuleChain.getId(),
  106 + EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
111 107 }
112 108 return savedRuleChain;
113 109 }
114 110
115 111 @Override
  112 + @Transactional
116 113 public boolean setRootRuleChain(TenantId tenantId, RuleChainId ruleChainId) {
117 114 RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId());
118 115 if (!ruleChain.isRoot()) {
... ... @@ -145,11 +142,12 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
145 142 }
146 143
147 144 @Override
148   - public RuleChainMetaData saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData) {
  145 + @Transactional
  146 + public boolean saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData) {
149 147 Validator.validateId(ruleChainMetaData.getRuleChainId(), "Incorrect rule chain id.");
150 148 RuleChain ruleChain = findRuleChainById(tenantId, ruleChainMetaData.getRuleChainId());
151 149 if (ruleChain == null) {
152   - return null;
  150 + return false;
153 151 }
154 152
155 153 if (CollectionUtils.isNotEmpty(ruleChainMetaData.getConnections())) {
... ... @@ -184,14 +182,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
184 182 for (RuleNode node : toAddOrUpdate) {
185 183 node.setRuleChainId(ruleChain.getId());
186 184 RuleNode savedNode = ruleNodeDao.save(tenantId, node);
187   - try {
188   - createRelation(tenantId, new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
189   - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
190   - } catch (Exception e) {
191   - log.warn("[{}] Failed to create rule chain to rule node relation. from: [{}], to: [{}]",
192   - ruleChainMetaData.getRuleChainId(), savedNode.getId());
193   - throw new RuntimeException(e);
194   - }
  185 + createRelation(tenantId, new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
  186 + EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
195 187 int index = nodes.indexOf(node);
196 188 nodes.set(index, savedNode);
197 189 ruleNodeIndexMap.put(savedNode.getId(), index);
... ... @@ -213,12 +205,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
213 205 EntityId from = nodes.get(nodeConnection.getFromIndex()).getId();
214 206 EntityId to = nodes.get(nodeConnection.getToIndex()).getId();
215 207 String type = nodeConnection.getType();
216   - try {
217   - createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
218   - } catch (Exception e) {
219   - log.warn("[{}] Failed to create rule node relation. from: [{}], to: [{}]", from, to);
220   - throw new RuntimeException(e);
221   - }
  208 + createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
222 209 }
223 210 }
224 211 if (ruleChainMetaData.getRuleChainConnections() != null) {
... ... @@ -226,16 +213,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
226 213 EntityId from = nodes.get(nodeToRuleChainConnection.getFromIndex()).getId();
227 214 EntityId to = nodeToRuleChainConnection.getTargetRuleChainId();
228 215 String type = nodeToRuleChainConnection.getType();
229   - try {
230   - createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE, nodeToRuleChainConnection.getAdditionalInfo()));
231   - } catch (Exception e) {
232   - log.warn("[{}] Failed to create rule node to rule chain relation. from: [{}], to: [{}]", from, to);
233   - throw new RuntimeException(e);
234   - }
  216 + createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE, nodeToRuleChainConnection.getAdditionalInfo()));
235 217 }
236 218 }
237 219
238   - return loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId());
  220 + return true;
239 221 }
240 222
241 223 private void validateCircles(List<NodeConnectionInfo> connectionInfos) {
... ... @@ -410,6 +392,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
410 392 }
411 393
412 394 @Override
  395 + @Transactional
413 396 public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) {
414 397 Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request.");
415 398 RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId());
... ... @@ -716,6 +699,15 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
716 699 ruleNodeDao.removeById(tenantId, entityId.getId());
717 700 }
718 701
  702 + private void createRelation(TenantId tenantId, EntityRelation relation) {
  703 + log.debug("Creating relation: {}", relation);
  704 + relationService.saveRelation(tenantId, relation);
  705 + }
  706 +
  707 + private void deleteRelation(TenantId tenantId, EntityRelation relation) {
  708 + log.debug("Deleting relation: {}", relation);
  709 + relationService.deleteRelation(tenantId, relation);
  710 + }
719 711
720 712 private DataValidator<RuleChain> ruleChainValidator =
721 713 new DataValidator<RuleChain>() {
... ...
... ... @@ -49,12 +49,17 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple
49 49 private RelationInsertRepository relationInsertRepository;
50 50
51 51 @Override
52   - public ListenableFuture<List<EntityRelation>> findAllByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) {
53   - return service.submit(() -> DaoUtil.convertDataList(
  52 + public ListenableFuture<List<EntityRelation>> findAllByFromAsync(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) {
  53 + return service.submit(() -> findAllByFrom(tenantId, from, typeGroup));
  54 + }
  55 +
  56 + @Override
  57 + public List<EntityRelation> findAllByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) {
  58 + return DaoUtil.convertDataList(
54 59 relationRepository.findAllByFromIdAndFromTypeAndRelationTypeGroup(
55 60 from.getId(),
56 61 from.getEntityType().name(),
57   - typeGroup.name())));
  62 + typeGroup.name()));
58 63 }
59 64
60 65 @Override
... ... @@ -68,12 +73,17 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple
68 73 }
69 74
70 75 @Override
71   - public ListenableFuture<List<EntityRelation>> findAllByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) {
72   - return service.submit(() -> DaoUtil.convertDataList(
  76 + public ListenableFuture<List<EntityRelation>> findAllByToAsync(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) {
  77 + return service.submit(() -> findAllByTo(tenantId, to, typeGroup));
  78 + }
  79 +
  80 + @Override
  81 + public List<EntityRelation> findAllByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) {
  82 + return DaoUtil.convertDataList(
73 83 relationRepository.findAllByToIdAndToTypeAndRelationTypeGroup(
74 84 to.getId(),
75 85 to.getEntityType().name(),
76   - typeGroup.name())));
  86 + typeGroup.name()));
77 87 }
78 88
79 89 @Override
... ...
... ... @@ -292,7 +292,8 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
292 292
293 293 ruleNodes.set(name3Index, ruleNode4);
294 294
295   - RuleChainMetaData updatedRuleChainMetaData = ruleChainService.saveRuleChainMetaData(tenantId, savedRuleChainMetaData);
  295 + Assert.assertTrue(ruleChainService.saveRuleChainMetaData(tenantId, savedRuleChainMetaData));
  296 + RuleChainMetaData updatedRuleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, savedRuleChainMetaData.getRuleChainId());
296 297
297 298 Assert.assertEquals(3, updatedRuleChainMetaData.getNodes().size());
298 299 Assert.assertEquals(3, updatedRuleChainMetaData.getConnections().size());
... ... @@ -404,7 +405,8 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
404 405 ruleChainMetaData.addConnectionInfo(0,2,"fail");
405 406 ruleChainMetaData.addConnectionInfo(1,2,"success");
406 407
407   - return ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData);
  408 + Assert.assertTrue(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData));
  409 + return ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId());
408 410 }
409 411
410 412 private RuleChainMetaData createRuleChainMetadataWithCirclingRelation() throws Exception {
... ...