|
23 | 23 | import org.dromara.hmily.annotation.TransTypeEnum; |
24 | 24 | import org.dromara.hmily.common.enums.HmilyActionEnum; |
25 | 25 | import org.dromara.hmily.common.utils.IdWorkerUtils; |
| 26 | +import org.dromara.hmily.config.api.ConfigEnv; |
| 27 | +import org.dromara.hmily.config.api.entity.HmilyConfig; |
26 | 28 | import org.dromara.hmily.core.context.HmilyContextHolder; |
27 | 29 | import org.dromara.hmily.core.context.HmilyTransactionContext; |
28 | 30 | import org.dromara.hmily.core.repository.HmilyRepositoryStorage; |
|
36 | 38 | import org.dromara.hmily.tac.core.cache.HmilyUndoContextCacheManager; |
37 | 39 | import org.dromara.hmily.tac.core.context.HmilyUndoContext; |
38 | 40 | import org.dromara.hmily.tac.core.lock.HmilyLockManager; |
39 | | -import org.dromara.hmily.tac.core.lock.LockRetryController; |
| 41 | +import org.dromara.hmily.tac.core.lock.HmilyLockRetryHandler; |
40 | 42 | import org.dromara.hmily.tac.p6spy.threadlocal.AutoCommitThreadLocal; |
41 | 43 | import org.dromara.hmily.tac.sqlcompute.HmilySQLComputeEngine; |
42 | 44 | import org.dromara.hmily.tac.sqlcompute.HmilySQLComputeEngineFactory; |
@@ -102,40 +104,38 @@ public void execute(final String sql, final List<Object> parameters, final Conne |
102 | 104 | } |
103 | 105 | String resourceId = ResourceIdUtils.INSTANCE.getResourceId(connectionInformation.getUrl()); |
104 | 106 | HmilySQLComputeEngine sqlComputeEngine = HmilySQLComputeEngineFactory.newInstance(statement); |
105 | | - // select SQL |
106 | 107 | HmilyTransactionContext transactionContext = HmilyContextHolder.get(); |
| 108 | + int lockRetryInterval = transactionContext.getLockRetryInterval(); |
| 109 | + int lockRetryTimes = transactionContext.getLockRetryTimes(); |
| 110 | + // select SQL |
107 | 111 | if (statement instanceof HmilySelectStatement) { |
108 | 112 | if (IsolationLevelEnum.READ_COMMITTED.getValue() == transactionContext.getIsolationLevel()) { |
109 | 113 | // read committed level need check locks |
110 | | - executeSelect(sql, parameters, connectionInformation, sqlComputeEngine, resourceId); |
| 114 | + executeSelect(sql, parameters, connectionInformation, sqlComputeEngine, resourceId, lockRetryInterval, lockRetryTimes); |
111 | 115 | } |
112 | 116 | return; |
113 | 117 | } |
114 | | - HmilyDataSnapshot snapshot = sqlComputeEngine.execute(sql, parameters, connectionInformation.getConnection(), resourceId); |
115 | | - log.debug("TAC-compute-sql ::: {}", snapshot); |
116 | | - HmilyUndoContext undoContext = buildUndoContext(HmilyContextHolder.get(), snapshot, resourceId); |
117 | | - HmilyLockManager.INSTANCE.tryAcquireLocks(undoContext.getHmilyLocks()); |
118 | | - log.debug("TAC-try-lock ::: {}", undoContext.getHmilyLocks()); |
119 | | - HmilyUndoContextCacheManager.INSTANCE.set(undoContext); |
| 118 | + // update delete insert SQL |
| 119 | + new HmilyLockRetryPolicy(lockRetryInterval, lockRetryTimes).execute(() -> { |
| 120 | + HmilyDataSnapshot snapshot = sqlComputeEngine.execute(sql, parameters, connectionInformation.getConnection(), resourceId); |
| 121 | + log.debug("TAC-compute-sql ::: {}", snapshot); |
| 122 | + HmilyUndoContext undoContext = buildUndoContext(HmilyContextHolder.get(), snapshot, resourceId); |
| 123 | + HmilyLockManager.INSTANCE.tryAcquireLocks(undoContext.getHmilyLocks()); |
| 124 | + log.debug("TAC-try-lock ::: {}", undoContext.getHmilyLocks()); |
| 125 | + HmilyUndoContextCacheManager.INSTANCE.set(undoContext); |
| 126 | + }); |
120 | 127 | } |
121 | 128 |
|
122 | 129 | private void executeSelect(final String sql, final List<Object> parameters, final ConnectionInformation connectionInformation, |
123 | | - final HmilySQLComputeEngine sqlComputeEngine, final String resourceId) { |
124 | | - LockRetryController lockRetryController = new LockRetryController(); |
125 | | - while (true) { |
126 | | - try { |
127 | | - HmilyDataSnapshot snapshot = sqlComputeEngine.execute(sql, parameters, connectionInformation.getConnection(), resourceId); |
128 | | - log.debug("TAC-compute-sql ::: {}", snapshot); |
129 | | - HmilyUndoContext undoContext = buildUndoContext(HmilyContextHolder.get(), snapshot, resourceId); |
130 | | - // check the global lock |
131 | | - HmilyLockManager.INSTANCE.checkLocks(undoContext.getHmilyLocks()); |
132 | | - log.debug("TAC-check-lock ::: {}", undoContext.getHmilyLocks()); |
133 | | - break; |
134 | | - } catch (HmilyLockConflictException hlce) { |
135 | | - // trigger retry |
136 | | - lockRetryController.sleep(hlce); |
137 | | - } |
138 | | - } |
| 130 | + final HmilySQLComputeEngine sqlComputeEngine, final String resourceId, final int lockRetryInterval, final int lockRetryTimes) { |
| 131 | + new HmilyLockRetryPolicy(lockRetryInterval, lockRetryTimes).execute(() -> { |
| 132 | + HmilyDataSnapshot snapshot = sqlComputeEngine.execute(sql, parameters, connectionInformation.getConnection(), resourceId); |
| 133 | + log.debug("TAC-compute-sql ::: {}", snapshot); |
| 134 | + HmilyUndoContext undoContext = buildUndoContext(HmilyContextHolder.get(), snapshot, resourceId); |
| 135 | + // check the global lock |
| 136 | + HmilyLockManager.INSTANCE.checkLocks(undoContext.getHmilyLocks()); |
| 137 | + log.debug("TAC-check-lock ::: {}", undoContext.getHmilyLocks()); |
| 138 | + }); |
139 | 139 | } |
140 | 140 |
|
141 | 141 | private HmilyUndoContext buildUndoContext(final HmilyTransactionContext transactionContext, final HmilyDataSnapshot dataSnapshot, final String resourceId) { |
@@ -208,4 +208,35 @@ private boolean check() { |
208 | 208 | HmilyTransactionContext transactionContext = HmilyContextHolder.get(); |
209 | 209 | return Objects.isNull(transactionContext) || !TransTypeEnum.TAC.name().equalsIgnoreCase(transactionContext.getTransType()); |
210 | 210 | } |
| 211 | + |
| 212 | + private static class HmilyLockRetryPolicy { |
| 213 | + protected static final boolean LOCK_RETRY_POLICY = ConfigEnv.getInstance().getConfig(HmilyConfig.class).isLockRetryPolicy(); |
| 214 | + |
| 215 | + private final HmilyLockRetryHandler hmilyLockRetryHandler; |
| 216 | + |
| 217 | + HmilyLockRetryPolicy(final int lockRetryInterval, final int lockRetryTimes) { |
| 218 | + this.hmilyLockRetryHandler = new HmilyLockRetryHandler(lockRetryInterval, lockRetryTimes); |
| 219 | + } |
| 220 | + |
| 221 | + private void execute(final Runnable task) { |
| 222 | + if (!LOCK_RETRY_POLICY) { |
| 223 | + task.run(); |
| 224 | + } else { |
| 225 | + doRetryOnLockConflict(task); |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + private void doRetryOnLockConflict(final Runnable task) { |
| 230 | + while (true) { |
| 231 | + try { |
| 232 | + // execute the task that need to be retried |
| 233 | + task.run(); |
| 234 | + break; |
| 235 | + } catch (HmilyLockConflictException hlce) { |
| 236 | + // trigger retry |
| 237 | + hmilyLockRetryHandler.sleep(hlce); |
| 238 | + } |
| 239 | + } |
| 240 | + } |
| 241 | + } |
211 | 242 | } |
0 commit comments