##### Coverage Report - com.ctrip.framework.apollo.adminservice.aop.NamespaceLockAspect

Classes in this File | Line Coverage | Branch Coverage | Complexity
NamespaceLockAspect |
13% | 6/44
10% | 1/10
| 2.375;2.375

1 |  |
     package com.ctrip.framework.apollo.adminservice.aop;
2 |  |
3 |  |
4 |  |
     import com.ctrip.framework.apollo.biz.entity.Item;
5 |  |
     import com.ctrip.framework.apollo.biz.entity.Namespace;
6 |  |
     import com.ctrip.framework.apollo.biz.entity.NamespaceLock;
7 |  |
     import com.ctrip.framework.apollo.biz.service.ItemService;
8 |  |
     import com.ctrip.framework.apollo.biz.service.NamespaceLockService;
9 |  |
     import com.ctrip.framework.apollo.biz.service.NamespaceService;
10 |  |
     import com.ctrip.framework.apollo.biz.utils.ApolloSwitcher;
11 |  |
     import com.ctrip.framework.apollo.core.dto.ItemChangeSets;
12 |  |
     import com.ctrip.framework.apollo.core.dto.ItemDTO;
13 |  |
     import com.ctrip.framework.apollo.core.exception.BadRequestException;
14 |  |
15 |  |
     import org.aspectj.lang.annotation.Aspect;
16 |  |
     import org.aspectj.lang.annotation.Before;
17 |  |
     import org.slf4j.Logger;
18 |  |
     import org.slf4j.LoggerFactory;
19 |  |
     import org.springframework.beans.factory.annotation.Autowired;
20 |  |
     import org.springframework.dao.DataIntegrityViolationException;
21 |  |
     import org.springframework.stereotype.Component;
22 |  |
23 |  |
24 |  |
     /**
25 |  |
      * 一个namespace在一次发布中只能允许一个人修改配置
26 |  |
      * 通过数据库lock表来实现
27 |  |
      */
28 |  |
     @Aspect
29 |  |
     @Component
30 | 1 |
     public class NamespaceLockAspect {
31 | 1 |
       private static final Logger logger = LoggerFactory.getLogger(NamespaceLockAspect.class);
32 |  |
33 |  |
34 |  |
       @Autowired
35 |  |
       private NamespaceLockService namespaceLockService;
36 |  |
       @Autowired
37 |  |
       private NamespaceService namespaceService;
38 |  |
       @Autowired
39 |  |
       private ItemService itemService;
40 |  |
       @Autowired
41 |  |
       private ApolloSwitcher apolloSwitcher;
42 |  |
43 |  |
44 |  |
       @Before("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, item, ..)")
45 |  |
       public void requireLockAdvice(String appId, String clusterName, String namespaceName, ItemDTO item) {
46 | 0 |
         acquireLock(appId, clusterName, namespaceName, item.getDataChangeLastModifiedBy());
47 | 0 |
       }
48 |  |
49 |  |
       @Before("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, changeSet, ..)")
50 |  |
       public void requireLockAdvice(String appId, String clusterName, String namespaceName,
51 |  |
                                                 ItemChangeSets changeSet) {
52 | 5 |
         acquireLock(appId, clusterName, namespaceName, changeSet.getDataChangeLastModifiedBy());
53 | 5 |
       }
54 |  |
55 |  |
       @Before("@annotation(PreAcquireNamespaceLock) && args(itemId, operator, ..)")
56 |  |
       public void requireLockAdvice(long itemId, String operator) {
57 | 0 |
         Item item = itemService.findOne(itemId);
58 |  |
59 | 0 |
         acquireLock(item.getNamespaceId(), operator);
60 | 0 |
       }
61 |  |
62 |  |
       private void acquireLock(String appId, String clusterName, String namespaceName, String currentUser) {
63 | 5 |
         if (apolloSwitcher.isNamespaceLockSwitchOff()) {
64 | 5 |
           return;
65 |  |
         }
66 |  |
67 | 0 |
         Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);
68 |  |
69 | 0 |
         acquireLock(namespace, currentUser);
70 | 0 |
       }
71 |  |
72 |  |
       private void acquireLock(long namespaceId, String currentUser) {
73 | 0 |
         Namespace namespace = namespaceService.findOne(namespaceId);
74 |  |
75 | 0 |
         acquireLock(namespace, currentUser);
76 |  |
77 | 0 |
       }
78 |  |
79 |  |
       private void acquireLock(Namespace namespace, String currentUser) {
80 | 0 |
         if (namespace == null) {
81 | 0 |
           throw new BadRequestException("namespace not exist.");
82 |  |
         }
83 |  |
84 | 0 |
         long namespaceId = namespace.getId();
85 |  |
86 | 0 |
         NamespaceLock namespaceLock = namespaceLockService.findLock(namespaceId);
87 | 0 |
         if (namespaceLock == null) {
88 |  |
           try {
89 | 0 |
             tryLock(namespaceId, currentUser);
90 |  |
             //lock success
91 | 0 |
           } catch (DataIntegrityViolationException e) {
92 |  |
             //lock fail
93 | 0 |
             acquireLockFail(namespace, currentUser);
94 | 0 |
           } catch (Exception e){
95 | 0 |
             logger.error("try lock error", e);
96 | 0 |
             throw e;
97 | 0 |
           }
98 |  |
         } else {
99 |  |
           //check lock owner is current user
100 | 0 |
           String lockOwner = namespaceLock.getDataChangeCreatedBy();
101 | 0 |
           if (!lockOwner.equals(currentUser)) {
102 | 0 |
             acquireLockFail(namespace, currentUser);
103 |  |
           }
104 |  |
         }
105 | 0 |
       }
106 |  |
107 |  |
       private void tryLock(long namespaceId, String user) {
108 | 0 |
         NamespaceLock lock = new NamespaceLock();
109 | 0 |
         lock.setNamespaceId(namespaceId);
110 | 0 |
         lock.setDataChangeCreatedBy(user);
111 | 0 |
         lock.setDataChangeLastModifiedBy(user);
112 | 0 |
         namespaceLockService.tryLock(lock);
113 | 0 |
       }
114 |  |
115 |  |
       private void acquireLockFail(Namespace namespace, String currentUser){
116 | 0 |
         NamespaceLock namespaceLock = namespaceLockService.findLock(namespace.getId());
117 | 0 |
         if (namespaceLock == null){
118 | 0 |
           acquireLock(namespace, currentUser);
119 |  |
         }
120 | 0 |
         String lockOwner = namespaceLock.getDataChangeCreatedBy();
121 | 0 |
         throw new BadRequestException("namespace:" + namespace.getNamespaceName() + " is modifying by " + lockOwner);
122 |  |
       }
123 |  |
124 |  |
125 |  |
126 |  |
     }