diff --git a/nop-api-core/src/main/java/io/nop/api/core/ApiConfigs.java b/nop-api-core/src/main/java/io/nop/api/core/ApiConfigs.java index ab9604d77..cceb7f8bd 100644 --- a/nop-api-core/src/main/java/io/nop/api/core/ApiConfigs.java +++ b/nop-api-core/src/main/java/io/nop/api/core/ApiConfigs.java @@ -35,6 +35,10 @@ public interface ApiConfigs { IConfigReference CFG_DEBUG = varRef("nop.debug", Boolean.class, false); + @Description("每次应用启动都会被分配唯一ID") + IConfigReference CFG_HOST_ID = + varRef("nop.server.host-id", String.class, null); + @Description("每一个启动的Nop应用程序应该指定一个唯一名称用于区分") IConfigReference CFG_APPLICATION_NAME = varRef("nop.application.name", String.class, "nop-app"); diff --git a/nop-api-core/src/main/java/io/nop/api/core/config/AppConfig.java b/nop-api-core/src/main/java/io/nop/api/core/config/AppConfig.java index fb8a0dad5..a841241d5 100644 --- a/nop-api-core/src/main/java/io/nop/api/core/config/AppConfig.java +++ b/nop-api-core/src/main/java/io/nop/api/core/config/AppConfig.java @@ -8,12 +8,16 @@ package io.nop.api.core.config; import io.nop.api.core.annotations.core.GlobalInstance; +import io.nop.api.core.util.ApiStringHelper; + +import java.util.UUID; import static io.nop.api.core.ApiConfigs.CFG_APPLICATION_LOCALE; import static io.nop.api.core.ApiConfigs.CFG_APPLICATION_NAME; import static io.nop.api.core.ApiConfigs.CFG_APPLICATION_TIMEZONE; import static io.nop.api.core.ApiConfigs.CFG_APPLICATION_VERSION; import static io.nop.api.core.ApiConfigs.CFG_DEBUG; +import static io.nop.api.core.ApiConfigs.CFG_HOST_ID; import static io.nop.api.core.ApiConfigs.CFG_PROFILE; @SuppressWarnings("PMD.TooManyStaticImports") @@ -37,6 +41,19 @@ public static String appVersion() { return CFG_APPLICATION_VERSION.get(); } + public static String hostId() { + String hostId = CFG_HOST_ID.get(); + if (ApiStringHelper.isEmpty(hostId)) { + synchronized (CFG_HOST_ID) { + hostId = CFG_HOST_ID.get(); + if (ApiStringHelper.isEmpty(hostId)) { + hostId = UUID.randomUUID().toString(); + s_provider.updateConfigValue(CFG_HOST_ID, hostId); + } + } + } + return hostId; + } public static String appLocale() { return CFG_APPLICATION_LOCALE.get(); diff --git a/nop-api-core/src/main/java/io/nop/api/core/util/FutureHelper.java b/nop-api-core/src/main/java/io/nop/api/core/util/FutureHelper.java index f4d70fe3c..93508aae9 100644 --- a/nop-api-core/src/main/java/io/nop/api/core/util/FutureHelper.java +++ b/nop-api-core/src/main/java/io/nop/api/core/util/FutureHelper.java @@ -286,9 +286,8 @@ public static void bindResult(CompletionStage promise, CompletableFuture< */ public static void bindCancel(CompletionStage promise, Future future) { promise.whenComplete((value, ex) -> { - if (isCancellationException(ex)) { + if (!future.isDone()) future.cancel(true); - } }); } diff --git a/nop-cluster/nop-cluster-core/src/main/java/io/nop/cluster/elector/AbstractLeaderElector.java b/nop-cluster/nop-cluster-core/src/main/java/io/nop/cluster/elector/AbstractLeaderElector.java new file mode 100644 index 000000000..3aec9839f --- /dev/null +++ b/nop-cluster/nop-cluster-core/src/main/java/io/nop/cluster/elector/AbstractLeaderElector.java @@ -0,0 +1,174 @@ +package io.nop.cluster.elector; + +import io.nop.api.core.annotations.ioc.InjectValue; +import io.nop.api.core.config.AppConfig; +import io.nop.commons.concurrent.executor.GlobalExecutors; +import io.nop.commons.concurrent.executor.IScheduledExecutor; +import io.nop.commons.io.net.IServerAddrFinder; +import io.nop.commons.util.NetHelper; +import io.nop.commons.util.StringHelper; + +import javax.annotation.Nullable; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; + +public abstract class AbstractLeaderElector implements ILeaderElector { + + private String addr; + private int port; + private IServerAddrFinder serverAddrFinder; + + private volatile LeaderEpoch leaderEpoch; + protected volatile CompletableFuture electionPromise = new CompletableFuture<>(); + + protected IScheduledExecutor scheduledExecutor; + + private String clusterId; + + private int leaseMs = 10000; + private int checkIntervalMs = 2000; + + private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + + private volatile boolean active; + + @InjectValue("@cfg:nop.leader.lease-time-ms|10000") + public void setLeaseMs(int leaseMs) { + this.leaseMs = leaseMs; + } + + @InjectValue("@cfg:nop.leader.check-interval-ms|2000") + public void setCheckIntervalMs(int checkIntervalMs) { + this.checkIntervalMs = checkIntervalMs; + } + + public int getCheckIntervalMs() { + return checkIntervalMs; + } + + @InjectValue("@cfg:nop.cluster.id,nop.application.name") + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public String getClusterId() { + return clusterId; + } + + public int getLeaseMs() { + return leaseMs; + } + + public int getPort() { + return port; + } + + public String getAddr() { + return addr; + } + + @InjectValue("@cfg:nop.server.addr|") + public void setAddr(String addr) { + this.addr = addr; + } + + @InjectValue("@cfg:nop.server.port|0") + public void setPort(int port) { + this.port = port; + } + + public IServerAddrFinder getServerAddrFinder() { + return serverAddrFinder; + } + + @Nullable + @Inject + public void setServerAddrFinder(IServerAddrFinder serverAddrFinder) { + this.serverAddrFinder = serverAddrFinder; + } + + public void setScheduledExecutor(IScheduledExecutor scheduledExecutor) { + this.scheduledExecutor = scheduledExecutor; + } + + @PostConstruct + public void init() { + active = true; + if (StringHelper.isEmpty(addr)) { + if (serverAddrFinder != null) { + addr = serverAddrFinder.findAddr(); + } else { + addr = NetHelper.findLocalIp(); + } + } + + if (scheduledExecutor == null) { + scheduledExecutor = GlobalExecutors.globalTimer().executeOn(GlobalExecutors.globalWorker()); + } + + scheduledExecutor.schedule(this::checkLeader, 0, TimeUnit.MILLISECONDS); + } + + public boolean isActive() { + return active; + } + + @PreDestroy + public void destroy() { + active = false; + electionPromise.cancel(false); + } + + protected String getLeaderAddr() { + if (port > 0) + return addr + ':' + port; + return addr; + } + + @Override + public String getHostId() { + return AppConfig.hostId(); + } + + @Override + public LeaderEpoch getLeaderEpoch() { + return leaderEpoch; + } + + @Override + public AutoCloseable addElectionListener(ILeaderElectionListener listener) { + listeners.add(listener); + return () -> { + listeners.remove(listener); + }; + } + + @Override + public boolean isLeader() { + LeaderEpoch leaderEpoch = this.leaderEpoch; + return leaderEpoch == null ? false : leaderEpoch.getLeaderId().equals(getHostId()); + } + + @Override + public CompletionStage whenElectionCompleted() { + return electionPromise; + } + + protected void newElection() { + this.electionPromise = new CompletableFuture<>(); + } + + protected void updateLeader(LeaderEpoch leader) { + LeaderEpoch current = this.leaderEpoch; + if (current == null) { + + } + } + + protected abstract Void checkLeader(); +} diff --git a/nop-commons/src/main/java/io/nop/commons/concurrent/executor/BindScheduledExecutor.java b/nop-commons/src/main/java/io/nop/commons/concurrent/executor/BindScheduledExecutor.java index bfb538864..1f1d2f801 100644 --- a/nop-commons/src/main/java/io/nop/commons/concurrent/executor/BindScheduledExecutor.java +++ b/nop-commons/src/main/java/io/nop/commons/concurrent/executor/BindScheduledExecutor.java @@ -39,6 +39,14 @@ public void refreshConfig() { timer.refreshConfig(); } + @Override + public IScheduledExecutor executeOn(Executor executor) { + if (this.executor == executor) + return this; + + return new BindScheduledExecutor(timer, executor); + } + @Override public CompletableFuture schedule(Callable callable, long delay, TimeUnit unit) { CompletableFuture future = new CompletableFuture<>(); diff --git a/nop-commons/src/main/java/io/nop/commons/concurrent/executor/ExecutorHelper.java b/nop-commons/src/main/java/io/nop/commons/concurrent/executor/ExecutorHelper.java index 1751db716..1c8d1f315 100644 --- a/nop-commons/src/main/java/io/nop/commons/concurrent/executor/ExecutorHelper.java +++ b/nop-commons/src/main/java/io/nop/commons/concurrent/executor/ExecutorHelper.java @@ -12,6 +12,7 @@ import io.nop.api.core.util.FutureHelper; import io.nop.commons.concurrent.thread.NamedThreadFactory; import io.nop.commons.metrics.GlobalMeterRegistry; +import io.nop.commons.util.MathHelper; import io.nop.commons.util.StringHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,6 +30,7 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; public class ExecutorHelper { static Executor SYNC_EXECUTOR = task -> task.run(); @@ -193,4 +195,34 @@ public static void registerMetrics(ExecutorService executor, ThreadPoolConfig co } } } + + public static CompletableFuture scheduleWithRandomDelay( + IScheduledExecutor executor, Runnable task, long initialDelay, + long minDelay, long maxDelay, + TimeUnit timeUnit) { + CompletableFuture future = new CompletableFuture<>(); + + AtomicReference> ref = new AtomicReference<>(); + Callable command = new Callable<>() { + @Override + public Void call() { + try { + task.run(); + ref.set(executor.schedule(this, MathHelper.random().nextLong(minDelay, maxDelay), timeUnit)); + } catch (Throwable e) { + future.completeExceptionally(e); + } + return null; + } + }; + + Future f = executor.schedule(command, initialDelay, timeUnit); + ref.set(f); + + future.exceptionally(ex -> { + ref.get().cancel(false); + return null; + }); + return future; + } } diff --git a/nop-commons/src/main/java/io/nop/commons/concurrent/executor/IScheduledExecutor.java b/nop-commons/src/main/java/io/nop/commons/concurrent/executor/IScheduledExecutor.java index b7013cd99..f441b4f27 100644 --- a/nop-commons/src/main/java/io/nop/commons/concurrent/executor/IScheduledExecutor.java +++ b/nop-commons/src/main/java/io/nop/commons/concurrent/executor/IScheduledExecutor.java @@ -9,14 +9,30 @@ import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; public interface IScheduledExecutor extends IThreadPoolExecutor { + /** + * 返回一个包装后的executor,它再调度任务时投递到Executor上执行 + * + * @param executor 任务执行器 + * @return 一个包装后的Executor + */ + default IScheduledExecutor executeOn(Executor executor) { + return new BindScheduledExecutor(this, executor); + } + CompletableFuture schedule(Callable callable, long delay, TimeUnit unit); Future scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); Future scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); + + default Future scheduleWithRandomDelay(Runnable command, long initialDelay, + long minDelay, long maxDelay, TimeUnit unit) { + return ExecutorHelper.scheduleWithRandomDelay(this, command, initialDelay, minDelay, maxDelay, unit); + } } \ No newline at end of file diff --git a/nop-commons/src/main/java/io/nop/commons/concurrent/lock/impl/LocalResourceLockManager.java b/nop-commons/src/main/java/io/nop/commons/concurrent/lock/impl/LocalResourceLockManager.java index 01795eca3..89f4a059d 100644 --- a/nop-commons/src/main/java/io/nop/commons/concurrent/lock/impl/LocalResourceLockManager.java +++ b/nop-commons/src/main/java/io/nop/commons/concurrent/lock/impl/LocalResourceLockManager.java @@ -9,6 +9,7 @@ import io.nop.api.core.time.CoreMetrics; import io.nop.api.core.util.Guard; +import io.nop.commons.concurrent.executor.GlobalExecutors; import io.nop.commons.concurrent.executor.IScheduledExecutor; import io.nop.commons.concurrent.lock.IResourceLock; import io.nop.commons.concurrent.lock.IResourceLockManager; @@ -19,7 +20,6 @@ import javax.annotation.Nonnull; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import javax.annotation.Resource; import java.sql.Timestamp; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -39,7 +39,6 @@ public class LocalResourceLockManager implements IResourceLockManager, IResource private volatile long lastCleanUpTime; - @Resource(name = "defaultTimer") private IScheduledExecutor timer; Future schedulePromise; @@ -100,6 +99,8 @@ LocalResourceLockState newLock(String resourceId, String lockerId) { @PostConstruct public void init() { Guard.checkArgument(schedulePromise == null, "nop.lock.lock-manager-already-inited"); + if (timer == null) + timer = GlobalExecutors.globalTimer(); schedulePromise = timer.scheduleWithFixedDelay(this::checkTimeout, expireInterval, expireInterval, TimeUnit.MILLISECONDS); } diff --git a/nop-dao/src/main/java/io/nop/dao/api/IEntityDao.java b/nop-dao/src/main/java/io/nop/dao/api/IEntityDao.java index 42f1281cb..d7c2796a8 100644 --- a/nop-dao/src/main/java/io/nop/dao/api/IEntityDao.java +++ b/nop-dao/src/main/java/io/nop/dao/api/IEntityDao.java @@ -11,6 +11,7 @@ import io.nop.api.core.beans.PageBean; import io.nop.api.core.beans.query.OrderFieldBean; import io.nop.api.core.beans.query.QueryBean; +import io.nop.api.core.time.IEstimatedClock; import io.nop.commons.collections.iterator.FindNextPageIterator; import io.nop.commons.collections.iterator.SelectNextIterator; import io.nop.commons.util.StringHelper; @@ -87,6 +88,17 @@ public interface IEntityDao { void updateEntity(T entity); + /** + * 立刻保存到数据库中,不存入session + * + * @param entity + */ + void saveEntityDirectly(T entity); + + void updateEntityDirectly(T entity); + + void deleteEntityDirectly(T entity); + void saveOrUpdateEntity(T entity); void deleteEntity(T entity); @@ -271,4 +283,6 @@ default void forEachEntity(QueryBean query, Consumer consumer) { * 清空本实体类对应的二级缓存 */ void clearEntityGlobalCache(); + + IEstimatedClock getDbEstimatedClock(); } \ No newline at end of file diff --git a/nop-dao/src/main/java/io/nop/dao/txn/impl/DefaultTransactionManager.java b/nop-dao/src/main/java/io/nop/dao/txn/impl/DefaultTransactionManager.java index 92960480c..ab6e693d5 100644 --- a/nop-dao/src/main/java/io/nop/dao/txn/impl/DefaultTransactionManager.java +++ b/nop-dao/src/main/java/io/nop/dao/txn/impl/DefaultTransactionManager.java @@ -9,6 +9,7 @@ import io.nop.api.core.exceptions.NopException; import io.nop.commons.util.StringHelper; +import io.nop.dao.DaoConstants; import io.nop.dao.jdbc.txn.JdbcTransactionFactory; import io.nop.dao.txn.ITransaction; import io.nop.dao.txn.ITransactionFactory; @@ -94,8 +95,13 @@ public void setDefaultListener(ITransactionListener defaultListener) { @Override public String getMainTxnGroup(String querySpace) { if (querySpace == null) - return null; - return txnGroupMap.get(querySpace); + return DaoConstants.DEFAULT_TXN_GROUP; + + // 如果没有明确指定事务分组,则实际上都归于缺省事务组 + String txnGroup = txnGroupMap.get(querySpace); + if (txnGroup == null) + txnGroup = DaoConstants.DEFAULT_TXN_GROUP; + return txnGroup; } public void setTxnGroupMap(Map txnGroupMap) { diff --git a/nop-dao/src/main/java/io/nop/dao/utils/DbEstimatedClock.java b/nop-dao/src/main/java/io/nop/dao/utils/DbEstimatedClock.java index 418cd0cf8..0dad16cbd 100644 --- a/nop-dao/src/main/java/io/nop/dao/utils/DbEstimatedClock.java +++ b/nop-dao/src/main/java/io/nop/dao/utils/DbEstimatedClock.java @@ -25,24 +25,24 @@ public class DbEstimatedClock implements IEstimatedClock { private volatile boolean fetching; static class TimeData { - final long fetchBeginTime; - final long fetchEndTime; + final long fetchBeginNanos; + final long fetchEndNanos; final long dbTime; volatile long elapsedTime; - public TimeData(long fetchBeginTime, long fetchEndTime, long dbTime) { - this.fetchBeginTime = fetchBeginTime; - this.fetchEndTime = fetchEndTime; + public TimeData(long fetchBeginNanos, long fetchEndNanos, long dbTime) { + this.fetchBeginNanos = fetchBeginNanos; + this.fetchEndNanos = fetchEndNanos; this.dbTime = dbTime; } long getMax() { - return dbTime + Math.max(0, CoreMetrics.currentTimeMillis() - fetchBeginTime); + return dbTime + Math.max(0, CoreMetrics.nanoToMillis(CoreMetrics.nanoTime() - fetchBeginNanos)); } long getMin() { - return dbTime + Math.max(0, CoreMetrics.currentTimeMillis() - fetchEndTime); + return dbTime + Math.max(0, CoreMetrics.nanoToMillis(CoreMetrics.nanoTime() - fetchEndNanos)); } } @@ -72,11 +72,11 @@ boolean isExpired(TimeData data) { if (data == null) return true; // 如果获取数据库耗费的时间过长,则认为它已经超时,重新获取 - if (data.fetchEndTime - data.fetchBeginTime > 200) + if (CoreMetrics.nanoToMillis(data.fetchEndNanos - data.fetchBeginNanos) > 200) return true; // 如果出现时钟回拨,或者超过允许的最大缓存时间,则重新获取 - long diff = CoreMetrics.currentTimeMillis() - data.fetchBeginTime; + long diff = CoreMetrics.nanoToMillis(CoreMetrics.nanoTime() - data.fetchBeginNanos); long elapsed = data.elapsedTime; if (diff < elapsed || diff > cacheTimeout.get()) return true; @@ -109,14 +109,10 @@ private TimeData fetch() { } private TimeData _fetchFromDb() { - long beginTime = CoreMetrics.currentTimeMillis(); + long beginTime = CoreMetrics.nanoTime(); long dbTime = jdbc.getDbCurrentTimestamp(querySpace).getTime(); - long endTime = CoreMetrics.currentTimeMillis(); + long endTime = CoreMetrics.nanoTime(); - // 防止时钟调整导致错误 - if (beginTime > endTime) { - beginTime = endTime; - } return this.timeData = new TimeData(beginTime, endTime, dbTime); } } \ No newline at end of file diff --git a/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json b/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json index c1ccbe53e..147b49843 100644 --- a/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json +++ b/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json @@ -26164,6 +26164,10 @@ "name": "getGeometryDataParameterBinder", "parameterTypes": [] }, + { + "name": "getGeometryTypeHandler", + "parameterTypes": [] + }, { "name": "getHexValueLiteral", "parameterTypes": [ @@ -26526,6 +26530,10 @@ "name": "getGeometryDataParameterBinder", "parameterTypes": [] }, + { + "name": "getGeometryTypeHandler", + "parameterTypes": [] + }, { "name": "getHexValueLiteral", "parameterTypes": [ @@ -27378,6 +27386,10 @@ "name": "getGeometryParameterBinder", "parameterTypes": [] }, + { + "name": "getGeometryTypeHandler", + "parameterTypes": [] + }, { "name": "getJdbcUrlPattern", "parameterTypes": [] @@ -27544,6 +27556,12 @@ "java.lang.String" ] }, + { + "name": "setGeometryTypeHandler", + "parameterTypes": [ + "java.lang.String" + ] + }, { "name": "setJdbcUrlPattern", "parameterTypes": [ diff --git a/nop-orm/src/main/java/io/nop/orm/IOrmSession.java b/nop-orm/src/main/java/io/nop/orm/IOrmSession.java index ba678a324..7f89f3484 100644 --- a/nop-orm/src/main/java/io/nop/orm/IOrmSession.java +++ b/nop-orm/src/main/java/io/nop/orm/IOrmSession.java @@ -139,6 +139,12 @@ default void forceLoad(IOrmEntity entity, FieldSelectionBean selection) { */ Object save(IOrmEntity entity); + Object saveDirectly(IOrmEntity entity); + + void updateDirectly(IOrmEntity entity); + + void deleteDirectly(IOrmEntity entity); + /** * 重新从数据库中加载数据,放弃当前对象上的修改 * diff --git a/nop-orm/src/main/java/io/nop/orm/IOrmSessionFactory.java b/nop-orm/src/main/java/io/nop/orm/IOrmSessionFactory.java index 86659a502..e88942350 100644 --- a/nop-orm/src/main/java/io/nop/orm/IOrmSessionFactory.java +++ b/nop-orm/src/main/java/io/nop/orm/IOrmSessionFactory.java @@ -11,6 +11,7 @@ import io.nop.commons.cache.ICacheProvider; import io.nop.dao.dialect.IDialect; import io.nop.dao.dialect.IDialectProvider; +import io.nop.dao.jdbc.IJdbcTemplate; import io.nop.dao.shard.IShardSelector; import io.nop.orm.eql.ICompiledSql; import io.nop.orm.model.IOrmModel; @@ -31,6 +32,8 @@ public interface IOrmSessionFactory extends AutoCloseable, IDialectProvider { void evictQueryCache(String cacheName, Serializable cacheKey); + IJdbcTemplate getJdbcTemplate(); + IOrmSession openSession(boolean stateless); ICache getQueryPlanCache(); diff --git a/nop-orm/src/main/java/io/nop/orm/IOrmTemplate.java b/nop-orm/src/main/java/io/nop/orm/IOrmTemplate.java index 063210f15..73175fd7e 100644 --- a/nop-orm/src/main/java/io/nop/orm/IOrmTemplate.java +++ b/nop-orm/src/main/java/io/nop/orm/IOrmTemplate.java @@ -10,6 +10,7 @@ import io.nop.api.core.annotations.core.Internal; import io.nop.api.core.beans.FieldSelectionBean; import io.nop.api.core.beans.query.QueryBean; +import io.nop.api.core.time.IEstimatedClock; import io.nop.commons.cache.ICache; import io.nop.dao.api.ISqlExecutor; import io.nop.dataset.IRowMapper; @@ -116,6 +117,12 @@ public interface IOrmTemplate extends ISqlExecutor { */ Object save(IOrmEntity entity); + Object saveDirectly(IOrmEntity entity); + + void updateDirectly(IOrmEntity entity); + + void deleteDirectly(IOrmEntity entity); + /** * 如果session已存在,则更新,否则新建 * @@ -259,4 +266,6 @@ public interface IOrmTemplate extends ISqlExecutor { * @param referenceName 对应entityName或collectionRole */ void clearGlobalCacheFor(String referenceName); + + IEstimatedClock getDbEstimatedClock(String querySpace); } \ No newline at end of file diff --git a/nop-orm/src/main/java/io/nop/orm/dao/OrmEntityDao.java b/nop-orm/src/main/java/io/nop/orm/dao/OrmEntityDao.java index 462e98b22..56058809b 100644 --- a/nop-orm/src/main/java/io/nop/orm/dao/OrmEntityDao.java +++ b/nop-orm/src/main/java/io/nop/orm/dao/OrmEntityDao.java @@ -13,6 +13,7 @@ import io.nop.api.core.beans.query.QueryBean; import io.nop.api.core.exceptions.ErrorCode; import io.nop.api.core.exceptions.NopException; +import io.nop.api.core.time.IEstimatedClock; import io.nop.api.core.util.Guard; import io.nop.commons.collections.ListFunctions; import io.nop.commons.util.StringHelper; @@ -211,6 +212,24 @@ public void deleteEntity(T entity) { orm().delete(entity); } + @Override + public void saveEntityDirectly(T entity) { + checkEntityNameMatch(entity); + orm().saveDirectly(entity); + } + + @Override + public void updateEntityDirectly(T entity) { + checkEntityNameMatch(entity); + orm().updateDirectly(entity); + } + + @Override + public void deleteEntityDirectly(T entity) { + checkEntityNameMatch(entity); + orm().deleteDirectly(entity); + } + @Override public T loadEntityById(Object id) { if (StringHelper.isEmptyObject(id)) @@ -660,4 +679,9 @@ public void clearEntitySessionCache() { public void clearEntityGlobalCache() { orm().clearGlobalCacheFor(getEntityName()); } + + @Override + public IEstimatedClock getDbEstimatedClock() { + return orm().getDbEstimatedClock(getEntityModel().getQuerySpace()); + } } \ No newline at end of file diff --git a/nop-orm/src/main/java/io/nop/orm/impl/OrmTemplateImpl.java b/nop-orm/src/main/java/io/nop/orm/impl/OrmTemplateImpl.java index c80d6afee..2faf419f8 100644 --- a/nop-orm/src/main/java/io/nop/orm/impl/OrmTemplateImpl.java +++ b/nop-orm/src/main/java/io/nop/orm/impl/OrmTemplateImpl.java @@ -11,17 +11,18 @@ import io.nop.api.core.beans.LongRangeBean; import io.nop.api.core.beans.query.QueryBean; import io.nop.api.core.context.ContextProvider; +import io.nop.api.core.time.IEstimatedClock; import io.nop.api.core.util.FutureHelper; import io.nop.api.core.util.ICancelToken; import io.nop.commons.cache.ICache; import io.nop.commons.cache.ICacheProvider; import io.nop.core.lang.sql.SQL; import io.nop.dao.api.AbstractSqlExecutor; +import io.nop.dao.dialect.IDialect; import io.nop.dataset.IComplexDataSet; import io.nop.dataset.IDataSet; import io.nop.dataset.IRowMapper; import io.nop.dataset.rowmapper.SmartRowMapper; -import io.nop.dao.dialect.IDialect; import io.nop.orm.IOrmBatchLoadQueue; import io.nop.orm.IOrmEntity; import io.nop.orm.IOrmSession; @@ -293,6 +294,27 @@ public Object save(IOrmEntity entity) { return runInSession(session -> session.save(entity)); } + @Override + public Object saveDirectly(IOrmEntity entity) { + return runInSession(session -> session.saveDirectly(entity)); + } + + @Override + public void updateDirectly(IOrmEntity entity) { + runInSession(session -> { + session.updateDirectly(entity); + return null; + }); + } + + @Override + public void deleteDirectly(IOrmEntity entity) { + runInSession(session -> { + session.deleteDirectly(entity); + return null; + }); + } + @Override public void saveOrUpdate(IOrmEntity entity) { runInSession(session -> { @@ -483,4 +505,9 @@ public void cacheRemove(Object key) { public void cachePut(Object key, Object value) { requireSession().getSessionCache().put(key, value); } + + @Override + public IEstimatedClock getDbEstimatedClock(String querySpace) { + return sessionFactory.getJdbcTemplate().getDbEstimatedClock(querySpace); + } } diff --git a/nop-orm/src/main/java/io/nop/orm/session/OrmSessionImpl.java b/nop-orm/src/main/java/io/nop/orm/session/OrmSessionImpl.java index 6d4f98f57..0ff6d2637 100644 --- a/nop-orm/src/main/java/io/nop/orm/session/OrmSessionImpl.java +++ b/nop-orm/src/main/java/io/nop/orm/session/OrmSessionImpl.java @@ -433,6 +433,58 @@ public Object save(IOrmEntity entity) { return entity.get_id(); } + @Override + public Object saveDirectly(IOrmEntity entity) { + checkValid(); + checkNotReadOnly(); + + OrmEntityState state = entity.orm_state(); + LOG.debug("session.internalSave:{}", entity); + + if (!state.isTransient()) + throw newError(ERR_ORM_SAVE_ENTITY_NOT_TRANSIENT, entity).param(ARG_STATUS, state); + + IEntityPersister persister = this.requireEntityPersister(entity.orm_entityName()); + entity.orm_state(OrmEntityState.SAVING); + entity.orm_entityModel(persister.getEntityModel()); + + initEntityId(persister, entity); + + // 新建实体不会有延迟加载属性 + entity.orm_markFullyLoaded(); + + flushSave(entity); + + return entity.get_id(); + } + + @Override + public void updateDirectly(IOrmEntity entity) { + checkValid(); + checkNotReadOnly(); + + OrmEntityState state = entity.orm_state(); + if (!state.isManaged()) + throw newError(ERR_ORM_UPDATE_ENTITY_NOT_MANAGED, entity); + + if (!entity.orm_dirty()) + return; + + flushUpdate(entity); + } + + @Override + public void deleteDirectly(IOrmEntity entity) { + checkValid(); + checkNotReadOnly(); + + OrmEntityState state = entity.orm_state(); + if (!state.isManaged()) + throw newError(ERR_ORM_UPDATE_ENTITY_NOT_MANAGED, entity); + + flushDelete(entity); + } + private void update(IOrmEntity entity) { checkValid(); checkNotReadOnly(); diff --git a/nop-sys/deploy/sql/mysql/_create_nop-sys.sql b/nop-sys/deploy/sql/mysql/_create_nop-sys.sql index c4a183d32..1acf86785 100644 --- a/nop-sys/deploy/sql/mysql/_create_nop-sys.sql +++ b/nop-sys/deploy/sql/mysql/_create_nop-sys.sql @@ -156,6 +156,29 @@ CREATE TABLE nop_sys_ext_field( constraint PK_nop_sys_ext_field primary key (ENTITY_NAME,ENTITY_ID,FIELD_NAME) ); +CREATE TABLE nop_sys_lock( + LOCK_GROUP VARCHAR(200) NOT NULL COMMENT '分组', + LOCK_NAME VARCHAR(200) NOT NULL COMMENT '锁名称', + LOCK_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '锁定时间', + EXPIRE_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '过期时间', + LOCK_REASON VARCHAR(200) NULL COMMENT '锁定原因', + HOLDER_ID VARCHAR(100) NOT NULL COMMENT '锁的持有者', + HOLDER_ADDER VARCHAR(100) NOT NULL COMMENT '持有者地址', + APP_ID VARCHAR(100) NOT NULL COMMENT '应用ID', + constraint PK_nop_sys_lock primary key (LOCK_GROUP,LOCK_NAME) +); + +CREATE TABLE nop_sys_cluster_leader( + CLUSTER_ID VARCHAR(200) NOT NULL COMMENT '集群ID', + LEADER_ID VARCHAR(100) NOT NULL COMMENT '主服务器ID', + LEADER_ADDER VARCHAR(100) NOT NULL COMMENT '主服务器地址', + LEADER_EPOCH BIGINT NOT NULL COMMENT '选举世代', + ELECT_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '选举时间', + EXPIRE_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '过期时间', + APP_ID VARCHAR(100) NOT NULL COMMENT '应用ID', + constraint PK_nop_sys_cluster_leader primary key (CLUSTER_ID) +); + CREATE TABLE nop_sys_dict( SID VARCHAR(32) NOT NULL COMMENT '主键', DICT_NAME VARCHAR(150) NOT NULL COMMENT '字典名', @@ -189,5 +212,9 @@ CREATE TABLE nop_sys_dict( ALTER TABLE nop_sys_ext_field COMMENT '扩展字段'; + ALTER TABLE nop_sys_lock COMMENT '资源锁'; + + ALTER TABLE nop_sys_cluster_leader COMMENT '集群选举'; + ALTER TABLE nop_sys_dict COMMENT '字典表'; diff --git a/nop-sys/deploy/sql/mysql/_drop_nop-sys.sql b/nop-sys/deploy/sql/mysql/_drop_nop-sys.sql index a8e051def..5177c21fd 100644 --- a/nop-sys/deploy/sql/mysql/_drop_nop-sys.sql +++ b/nop-sys/deploy/sql/mysql/_drop_nop-sys.sql @@ -8,5 +8,7 @@ drop table if exists nop_sys_notice_template; drop table if exists nop_sys_user_variable; drop table if exists nop_sys_variable; drop table if exists nop_sys_ext_field; +drop table if exists nop_sys_lock; +drop table if exists nop_sys_cluster_leader; drop table if exists nop_sys_dict; diff --git a/nop-sys/deploy/sql/oracle/_create_nop-sys.sql b/nop-sys/deploy/sql/oracle/_create_nop-sys.sql index e3c623211..f9b054e87 100644 --- a/nop-sys/deploy/sql/oracle/_create_nop-sys.sql +++ b/nop-sys/deploy/sql/oracle/_create_nop-sys.sql @@ -156,6 +156,29 @@ CREATE TABLE nop_sys_ext_field( constraint PK_nop_sys_ext_field primary key (ENTITY_NAME,ENTITY_ID,FIELD_NAME) ); +CREATE TABLE nop_sys_lock( + LOCK_GROUP VARCHAR2(200) NOT NULL , + LOCK_NAME VARCHAR2(200) NOT NULL , + LOCK_TIME TIMESTAMP NOT NULL , + EXPIRE_AT TIMESTAMP NOT NULL , + LOCK_REASON VARCHAR2(200) , + HOLDER_ID VARCHAR2(100) NOT NULL , + HOLDER_ADDER VARCHAR2(100) NOT NULL , + APP_ID VARCHAR2(100) NOT NULL , + constraint PK_nop_sys_lock primary key (LOCK_GROUP,LOCK_NAME) +); + +CREATE TABLE nop_sys_cluster_leader( + CLUSTER_ID VARCHAR2(200) NOT NULL , + LEADER_ID VARCHAR2(100) NOT NULL , + LEADER_ADDER VARCHAR2(100) NOT NULL , + LEADER_EPOCH NUMBER(20) NOT NULL , + ELECT_TIME TIMESTAMP NOT NULL , + EXPIRE_AT TIMESTAMP NOT NULL , + APP_ID VARCHAR2(100) NOT NULL , + constraint PK_nop_sys_cluster_leader primary key (CLUSTER_ID) +); + CREATE TABLE nop_sys_dict( SID VARCHAR2(32) NOT NULL , DICT_NAME VARCHAR2(150) NOT NULL , @@ -431,6 +454,40 @@ CREATE TABLE nop_sys_dict( COMMENT ON COLUMN nop_sys_ext_field.REMARK IS '备注'; + COMMENT ON TABLE nop_sys_lock IS '资源锁'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_GROUP IS '分组'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_NAME IS '锁名称'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_TIME IS '锁定时间'; + + COMMENT ON COLUMN nop_sys_lock.EXPIRE_AT IS '过期时间'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_REASON IS '锁定原因'; + + COMMENT ON COLUMN nop_sys_lock.HOLDER_ID IS '锁的持有者'; + + COMMENT ON COLUMN nop_sys_lock.HOLDER_ADDER IS '持有者地址'; + + COMMENT ON COLUMN nop_sys_lock.APP_ID IS '应用ID'; + + COMMENT ON TABLE nop_sys_cluster_leader IS '集群选举'; + + COMMENT ON COLUMN nop_sys_cluster_leader.CLUSTER_ID IS '集群ID'; + + COMMENT ON COLUMN nop_sys_cluster_leader.LEADER_ID IS '主服务器ID'; + + COMMENT ON COLUMN nop_sys_cluster_leader.LEADER_ADDER IS '主服务器地址'; + + COMMENT ON COLUMN nop_sys_cluster_leader.LEADER_EPOCH IS '选举世代'; + + COMMENT ON COLUMN nop_sys_cluster_leader.ELECT_TIME IS '选举时间'; + + COMMENT ON COLUMN nop_sys_cluster_leader.EXPIRE_AT IS '过期时间'; + + COMMENT ON COLUMN nop_sys_cluster_leader.APP_ID IS '应用ID'; + COMMENT ON TABLE nop_sys_dict IS '字典表'; COMMENT ON COLUMN nop_sys_dict.SID IS '主键'; diff --git a/nop-sys/deploy/sql/oracle/_drop_nop-sys.sql b/nop-sys/deploy/sql/oracle/_drop_nop-sys.sql index 5d83f1eae..9b8ef36dd 100644 --- a/nop-sys/deploy/sql/oracle/_drop_nop-sys.sql +++ b/nop-sys/deploy/sql/oracle/_drop_nop-sys.sql @@ -8,5 +8,7 @@ drop table nop_sys_notice_template; drop table nop_sys_user_variable; drop table nop_sys_variable; drop table nop_sys_ext_field; +drop table nop_sys_lock; +drop table nop_sys_cluster_leader; drop table nop_sys_dict; diff --git a/nop-sys/deploy/sql/postgresql/_create_nop-sys.sql b/nop-sys/deploy/sql/postgresql/_create_nop-sys.sql index c6d7f8fc5..ee3f1a4b9 100644 --- a/nop-sys/deploy/sql/postgresql/_create_nop-sys.sql +++ b/nop-sys/deploy/sql/postgresql/_create_nop-sys.sql @@ -156,6 +156,29 @@ CREATE TABLE nop_sys_ext_field( constraint PK_nop_sys_ext_field primary key (ENTITY_NAME,ENTITY_ID,FIELD_NAME) ); +CREATE TABLE nop_sys_lock( + LOCK_GROUP VARCHAR(200) NOT NULL , + LOCK_NAME VARCHAR(200) NOT NULL , + LOCK_TIME TIMESTAMP NOT NULL , + EXPIRE_AT TIMESTAMP NOT NULL , + LOCK_REASON VARCHAR(200) , + HOLDER_ID VARCHAR(100) NOT NULL , + HOLDER_ADDER VARCHAR(100) NOT NULL , + APP_ID VARCHAR(100) NOT NULL , + constraint PK_nop_sys_lock primary key (LOCK_GROUP,LOCK_NAME) +); + +CREATE TABLE nop_sys_cluster_leader( + CLUSTER_ID VARCHAR(200) NOT NULL , + LEADER_ID VARCHAR(100) NOT NULL , + LEADER_ADDER VARCHAR(100) NOT NULL , + LEADER_EPOCH INT8 NOT NULL , + ELECT_TIME TIMESTAMP NOT NULL , + EXPIRE_AT TIMESTAMP NOT NULL , + APP_ID VARCHAR(100) NOT NULL , + constraint PK_nop_sys_cluster_leader primary key (CLUSTER_ID) +); + CREATE TABLE nop_sys_dict( SID VARCHAR(32) NOT NULL , DICT_NAME VARCHAR(150) NOT NULL , @@ -431,6 +454,40 @@ CREATE TABLE nop_sys_dict( COMMENT ON COLUMN nop_sys_ext_field.REMARK IS '备注'; + COMMENT ON TABLE nop_sys_lock IS '资源锁'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_GROUP IS '分组'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_NAME IS '锁名称'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_TIME IS '锁定时间'; + + COMMENT ON COLUMN nop_sys_lock.EXPIRE_AT IS '过期时间'; + + COMMENT ON COLUMN nop_sys_lock.LOCK_REASON IS '锁定原因'; + + COMMENT ON COLUMN nop_sys_lock.HOLDER_ID IS '锁的持有者'; + + COMMENT ON COLUMN nop_sys_lock.HOLDER_ADDER IS '持有者地址'; + + COMMENT ON COLUMN nop_sys_lock.APP_ID IS '应用ID'; + + COMMENT ON TABLE nop_sys_cluster_leader IS '集群选举'; + + COMMENT ON COLUMN nop_sys_cluster_leader.CLUSTER_ID IS '集群ID'; + + COMMENT ON COLUMN nop_sys_cluster_leader.LEADER_ID IS '主服务器ID'; + + COMMENT ON COLUMN nop_sys_cluster_leader.LEADER_ADDER IS '主服务器地址'; + + COMMENT ON COLUMN nop_sys_cluster_leader.LEADER_EPOCH IS '选举世代'; + + COMMENT ON COLUMN nop_sys_cluster_leader.ELECT_TIME IS '选举时间'; + + COMMENT ON COLUMN nop_sys_cluster_leader.EXPIRE_AT IS '过期时间'; + + COMMENT ON COLUMN nop_sys_cluster_leader.APP_ID IS '应用ID'; + COMMENT ON TABLE nop_sys_dict IS '字典表'; COMMENT ON COLUMN nop_sys_dict.SID IS '主键'; diff --git a/nop-sys/deploy/sql/postgresql/_drop_nop-sys.sql b/nop-sys/deploy/sql/postgresql/_drop_nop-sys.sql index a8e051def..5177c21fd 100644 --- a/nop-sys/deploy/sql/postgresql/_drop_nop-sys.sql +++ b/nop-sys/deploy/sql/postgresql/_drop_nop-sys.sql @@ -8,5 +8,7 @@ drop table if exists nop_sys_notice_template; drop table if exists nop_sys_user_variable; drop table if exists nop_sys_variable; drop table if exists nop_sys_ext_field; +drop table if exists nop_sys_lock; +drop table if exists nop_sys_cluster_leader; drop table if exists nop_sys_dict; diff --git a/nop-sys/model/nop-sys.orm.xlsx b/nop-sys/model/nop-sys.orm.xlsx index 57593827a..845a00065 100644 Binary files a/nop-sys/model/nop-sys.orm.xlsx and b/nop-sys/model/nop-sys.orm.xlsx differ diff --git a/nop-sys/nop-sys-dao/pom.xml b/nop-sys/nop-sys-dao/pom.xml index 885459ad1..db2111c7f 100644 --- a/nop-sys/nop-sys-dao/pom.xml +++ b/nop-sys/nop-sys-dao/pom.xml @@ -17,10 +17,17 @@ io.github.entropy-cloud nop-api-core + io.github.entropy-cloud nop-orm + + + io.github.entropy-cloud + nop-cluster-core + + nop-sys-codegen io.github.entropy-cloud diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/elector/SysDaoLeaderElector.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/elector/SysDaoLeaderElector.java new file mode 100644 index 000000000..de2215d29 --- /dev/null +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/elector/SysDaoLeaderElector.java @@ -0,0 +1,87 @@ +package io.nop.sys.dao.elector; + +import io.nop.api.core.time.IEstimatedClock; +import io.nop.cluster.elector.AbstractLeaderElector; +import io.nop.cluster.elector.LeaderEpoch; +import io.nop.commons.util.MathHelper; +import io.nop.dao.api.IDaoProvider; +import io.nop.dao.api.IEntityDao; +import io.nop.sys.dao.entity.NopSysClusterLeader; + +import javax.inject.Inject; +import java.util.concurrent.TimeUnit; + +public class SysDaoLeaderElector extends AbstractLeaderElector { + private IDaoProvider daoProvider; + + @Inject + public void setDaoProvider(IDaoProvider daoProvider) { + this.daoProvider = daoProvider; + } + + private IEntityDao dao() { + return daoProvider.daoFor(NopSysClusterLeader.class); + } + + @Override + public void restartElection(String preferredLeaderId) { + IEntityDao dao = dao(); + NopSysClusterLeader leader = dao.getEntityById(getClusterId()); + if (leader != null) { + removeEpoch(leader); + } + tryBecomeLeader(); + } + + protected Void checkLeader() { + try { + do { + IEntityDao dao = dao(); + NopSysClusterLeader leader = dao.getEntityById(getClusterId()); + if (leader == null) { + scheduledExecutor.schedule(this::tryBecomeLeader, randomDelay(), TimeUnit.MICROSECONDS); + } else { + IEstimatedClock clock = dao.getDbEstimatedClock(); + // leader expired + if (leader.getExpireAt().getTime() < clock.getMaxCurrentTimeMillis()) { + if (removeEpoch(leader)) { + // 删除已过期的记录之后,尝试成为leader + return tryBecomeLeader(); + } else { + // epoch已经被更新,重新检查 + continue; + } + } else { + // leader处于有效租期内 + updateLeader(new LeaderEpoch(leader.getLeaderId(), leader.getLeaderEpoch())); + scheduleCheck(); + } + } + break; + } while (true); + } catch (Exception e) { + scheduleCheck(); + } + return null; + } + + private void scheduleCheck() { + scheduledExecutor.schedule(this::checkLeader, getCheckIntervalMs(), TimeUnit.MICROSECONDS); + } + + private boolean removeEpoch(NopSysClusterLeader leader) { + NopSysClusterLeader example = new NopSysClusterLeader(); + example.setClusterId(leader.getClusterId()); + example.setLeaderEpoch(leader.getLeaderEpoch()); + return dao().deleteByExample(example) > 0; + } + + private long randomDelay() { + return MathHelper.random().nextLong(0, 500); + } + + protected Void tryBecomeLeader() { + newElection(); + return null; + } +} diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/NopSysClusterLeader.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/NopSysClusterLeader.java new file mode 100644 index 000000000..5b044bc9f --- /dev/null +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/NopSysClusterLeader.java @@ -0,0 +1,13 @@ +package io.nop.sys.dao.entity; + +import io.nop.api.core.annotations.biz.BizObjName; +import io.nop.sys.dao.entity._gen._NopSysClusterLeader; + + +@BizObjName("NopSysClusterLeader") +public class NopSysClusterLeader extends _NopSysClusterLeader{ + public NopSysClusterLeader(){ + } + + +} diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/NopSysLock.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/NopSysLock.java new file mode 100644 index 000000000..23fe1412b --- /dev/null +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/NopSysLock.java @@ -0,0 +1,19 @@ +package io.nop.sys.dao.entity; + +import io.nop.api.core.annotations.biz.BizObjName; +import io.nop.sys.dao.entity._gen._NopSysLock; + +import io.nop.sys.dao.entity._gen.NopSysLockPkBuilder; + + +@BizObjName("NopSysLock") +public class NopSysLock extends _NopSysLock{ + public NopSysLock(){ + } + + + public static NopSysLockPkBuilder newPk(){ + return new NopSysLockPkBuilder(); + } + +} diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/NopSysLockPkBuilder.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/NopSysLockPkBuilder.java new file mode 100644 index 000000000..cf17cf360 --- /dev/null +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/NopSysLockPkBuilder.java @@ -0,0 +1,28 @@ +package io.nop.sys.dao.entity._gen; + +import io.nop.orm.support.OrmCompositePk; +import io.nop.sys.dao.entity.NopSysLock; + +/** + * 用于生成复合主键的帮助类 + */ +@SuppressWarnings({"PMD.UnnecessaryFullyQualifiedName"}) +public class NopSysLockPkBuilder{ + private Object[] values = new Object[2]; + + + public NopSysLockPkBuilder setLockGroup(java.lang.String value){ + this.values[0] = value; + return this; + } + + public NopSysLockPkBuilder setLockName(java.lang.String value){ + this.values[1] = value; + return this; + } + + + public OrmCompositePk build(){ + return OrmCompositePk.buildNotNull(NopSysLock.PK_PROP_NAMES,values); + } +} diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/_NopSysClusterLeader.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/_NopSysClusterLeader.java new file mode 100644 index 000000000..9b0416aed --- /dev/null +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/_NopSysClusterLeader.java @@ -0,0 +1,478 @@ +package io.nop.sys.dao.entity._gen; + +import io.nop.orm.model.IEntityModel; +import io.nop.orm.support.DynamicOrmEntity; +import io.nop.orm.support.OrmEntitySet; //NOPMD - suppressed UnusedImports - Auto Gen Code +import io.nop.orm.IOrmEntitySet; //NOPMD - suppressed UnusedImports - Auto Gen Code +import io.nop.api.core.convert.ConvertHelper; +import java.util.Map; +import java.util.HashMap; +import java.util.Arrays; +import java.util.List; + +import io.nop.sys.dao.entity.NopSysClusterLeader; + +// tell cpd to start ignoring code - CPD-OFF +/** + * 集群选举: nop_sys_cluster_leader + */ +@SuppressWarnings({"PMD.UselessOverridingMethod","PMD.UnusedLocalVariable", + "PMD.UnnecessaryFullyQualifiedName","PMD.EmptyControlStatement"}) +public class _NopSysClusterLeader extends DynamicOrmEntity{ + + /* 集群ID: CLUSTER_ID VARCHAR */ + public static final String PROP_NAME_clusterId = "clusterId"; + public static final int PROP_ID_clusterId = 1; + + /* 主服务器ID: LEADER_ID VARCHAR */ + public static final String PROP_NAME_leaderId = "leaderId"; + public static final int PROP_ID_leaderId = 2; + + /* 主服务器地址: LEADER_ADDER VARCHAR */ + public static final String PROP_NAME_leaderAdder = "leaderAdder"; + public static final int PROP_ID_leaderAdder = 3; + + /* 选举世代: LEADER_EPOCH BIGINT */ + public static final String PROP_NAME_leaderEpoch = "leaderEpoch"; + public static final int PROP_ID_leaderEpoch = 4; + + /* 选举时间: ELECT_TIME TIMESTAMP */ + public static final String PROP_NAME_electTime = "electTime"; + public static final int PROP_ID_electTime = 5; + + /* 过期时间: EXPIRE_AT TIMESTAMP */ + public static final String PROP_NAME_expireAt = "expireAt"; + public static final int PROP_ID_expireAt = 6; + + /* 应用ID: APP_ID VARCHAR */ + public static final String PROP_NAME_appId = "appId"; + public static final int PROP_ID_appId = 7; + + + private static int _PROP_ID_BOUND = 8; + + + + public static final List PK_PROP_NAMES = Arrays.asList(PROP_NAME_clusterId); + public static final int[] PK_PROP_IDS = new int[]{PROP_ID_clusterId}; + + private static final String[] PROP_ID_TO_NAME = new String[8]; + private static final Map PROP_NAME_TO_ID = new HashMap<>(); + static{ + + PROP_ID_TO_NAME[PROP_ID_clusterId] = PROP_NAME_clusterId; + PROP_NAME_TO_ID.put(PROP_NAME_clusterId, PROP_ID_clusterId); + + PROP_ID_TO_NAME[PROP_ID_leaderId] = PROP_NAME_leaderId; + PROP_NAME_TO_ID.put(PROP_NAME_leaderId, PROP_ID_leaderId); + + PROP_ID_TO_NAME[PROP_ID_leaderAdder] = PROP_NAME_leaderAdder; + PROP_NAME_TO_ID.put(PROP_NAME_leaderAdder, PROP_ID_leaderAdder); + + PROP_ID_TO_NAME[PROP_ID_leaderEpoch] = PROP_NAME_leaderEpoch; + PROP_NAME_TO_ID.put(PROP_NAME_leaderEpoch, PROP_ID_leaderEpoch); + + PROP_ID_TO_NAME[PROP_ID_electTime] = PROP_NAME_electTime; + PROP_NAME_TO_ID.put(PROP_NAME_electTime, PROP_ID_electTime); + + PROP_ID_TO_NAME[PROP_ID_expireAt] = PROP_NAME_expireAt; + PROP_NAME_TO_ID.put(PROP_NAME_expireAt, PROP_ID_expireAt); + + PROP_ID_TO_NAME[PROP_ID_appId] = PROP_NAME_appId; + PROP_NAME_TO_ID.put(PROP_NAME_appId, PROP_ID_appId); + + } + + + /* 集群ID: CLUSTER_ID */ + private java.lang.String _clusterId; + + /* 主服务器ID: LEADER_ID */ + private java.lang.String _leaderId; + + /* 主服务器地址: LEADER_ADDER */ + private java.lang.String _leaderAdder; + + /* 选举世代: LEADER_EPOCH */ + private java.lang.Long _leaderEpoch; + + /* 选举时间: ELECT_TIME */ + private java.sql.Timestamp _electTime; + + /* 过期时间: EXPIRE_AT */ + private java.sql.Timestamp _expireAt; + + /* 应用ID: APP_ID */ + private java.lang.String _appId; + + + public _NopSysClusterLeader(){ + } + + protected NopSysClusterLeader newInstance(){ + return new NopSysClusterLeader(); + } + + @Override + public NopSysClusterLeader cloneInstance() { + NopSysClusterLeader entity = newInstance(); + orm_forEachInitedProp((value, propId) -> { + entity.onInitProp(propId); + }); + return entity; + } + + @Override + public String orm_entityName() { + // 如果存在实体模型对象,则以模型对象上的设置为准 + IEntityModel entityModel = orm_entityModel(); + if(entityModel != null) + return entityModel.getName(); + return "io.nop.sys.dao.entity.NopSysClusterLeader"; + } + + @Override + public int orm_propIdBound(){ + IEntityModel entityModel = orm_entityModel(); + if(entityModel != null) + return entityModel.getPropIdBound(); + return _PROP_ID_BOUND; + } + + @Override + public Object orm_id() { + + return buildSimpleId(PROP_ID_clusterId); + + } + + @Override + public boolean orm_isPrimary(int propId) { + + return propId == PROP_ID_clusterId; + + } + + @Override + public String orm_propName(int propId) { + if(propId >= PROP_ID_TO_NAME.length) + return super.orm_propName(propId); + String propName = PROP_ID_TO_NAME[propId]; + if(propName == null) + return super.orm_propName(propId); + return propName; + } + + @Override + public int orm_propId(String propName) { + Integer propId = PROP_NAME_TO_ID.get(propName); + if(propId == null) + return super.orm_propId(propName); + return propId; + } + + @Override + public Object orm_propValue(int propId) { + switch(propId){ + + case PROP_ID_clusterId: + return getClusterId(); + + case PROP_ID_leaderId: + return getLeaderId(); + + case PROP_ID_leaderAdder: + return getLeaderAdder(); + + case PROP_ID_leaderEpoch: + return getLeaderEpoch(); + + case PROP_ID_electTime: + return getElectTime(); + + case PROP_ID_expireAt: + return getExpireAt(); + + case PROP_ID_appId: + return getAppId(); + + default: + return super.orm_propValue(propId); + } + } + + + + @Override + public void orm_propValue(int propId, Object value){ + switch(propId){ + + case PROP_ID_clusterId:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_clusterId)); + } + setClusterId(typedValue); + break; + } + + case PROP_ID_leaderId:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_leaderId)); + } + setLeaderId(typedValue); + break; + } + + case PROP_ID_leaderAdder:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_leaderAdder)); + } + setLeaderAdder(typedValue); + break; + } + + case PROP_ID_leaderEpoch:{ + java.lang.Long typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toLong(value, + err-> newTypeConversionError(PROP_NAME_leaderEpoch)); + } + setLeaderEpoch(typedValue); + break; + } + + case PROP_ID_electTime:{ + java.sql.Timestamp typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toTimestamp(value, + err-> newTypeConversionError(PROP_NAME_electTime)); + } + setElectTime(typedValue); + break; + } + + case PROP_ID_expireAt:{ + java.sql.Timestamp typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toTimestamp(value, + err-> newTypeConversionError(PROP_NAME_expireAt)); + } + setExpireAt(typedValue); + break; + } + + case PROP_ID_appId:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_appId)); + } + setAppId(typedValue); + break; + } + + default: + super.orm_propValue(propId,value); + } + } + + @Override + public void orm_internalSet(int propId, Object value) { + switch(propId){ + + case PROP_ID_clusterId:{ + onInitProp(propId); + this._clusterId = (java.lang.String)value; + orm_id(); // 如果是设置主键字段,则触发watcher + break; + } + + case PROP_ID_leaderId:{ + onInitProp(propId); + this._leaderId = (java.lang.String)value; + + break; + } + + case PROP_ID_leaderAdder:{ + onInitProp(propId); + this._leaderAdder = (java.lang.String)value; + + break; + } + + case PROP_ID_leaderEpoch:{ + onInitProp(propId); + this._leaderEpoch = (java.lang.Long)value; + + break; + } + + case PROP_ID_electTime:{ + onInitProp(propId); + this._electTime = (java.sql.Timestamp)value; + + break; + } + + case PROP_ID_expireAt:{ + onInitProp(propId); + this._expireAt = (java.sql.Timestamp)value; + + break; + } + + case PROP_ID_appId:{ + onInitProp(propId); + this._appId = (java.lang.String)value; + + break; + } + + default: + super.orm_internalSet(propId,value); + } + } + + + /** + * 集群ID: CLUSTER_ID + */ + public java.lang.String getClusterId(){ + onPropGet(PROP_ID_clusterId); + return _clusterId; + } + + /** + * 集群ID: CLUSTER_ID + */ + public void setClusterId(java.lang.String value){ + if(onPropSet(PROP_ID_clusterId,value)){ + this._clusterId = value; + internalClearRefs(PROP_ID_clusterId); + orm_id(); + } + } + + /** + * 主服务器ID: LEADER_ID + */ + public java.lang.String getLeaderId(){ + onPropGet(PROP_ID_leaderId); + return _leaderId; + } + + /** + * 主服务器ID: LEADER_ID + */ + public void setLeaderId(java.lang.String value){ + if(onPropSet(PROP_ID_leaderId,value)){ + this._leaderId = value; + internalClearRefs(PROP_ID_leaderId); + + } + } + + /** + * 主服务器地址: LEADER_ADDER + */ + public java.lang.String getLeaderAdder(){ + onPropGet(PROP_ID_leaderAdder); + return _leaderAdder; + } + + /** + * 主服务器地址: LEADER_ADDER + */ + public void setLeaderAdder(java.lang.String value){ + if(onPropSet(PROP_ID_leaderAdder,value)){ + this._leaderAdder = value; + internalClearRefs(PROP_ID_leaderAdder); + + } + } + + /** + * 选举世代: LEADER_EPOCH + */ + public java.lang.Long getLeaderEpoch(){ + onPropGet(PROP_ID_leaderEpoch); + return _leaderEpoch; + } + + /** + * 选举世代: LEADER_EPOCH + */ + public void setLeaderEpoch(java.lang.Long value){ + if(onPropSet(PROP_ID_leaderEpoch,value)){ + this._leaderEpoch = value; + internalClearRefs(PROP_ID_leaderEpoch); + + } + } + + /** + * 选举时间: ELECT_TIME + */ + public java.sql.Timestamp getElectTime(){ + onPropGet(PROP_ID_electTime); + return _electTime; + } + + /** + * 选举时间: ELECT_TIME + */ + public void setElectTime(java.sql.Timestamp value){ + if(onPropSet(PROP_ID_electTime,value)){ + this._electTime = value; + internalClearRefs(PROP_ID_electTime); + + } + } + + /** + * 过期时间: EXPIRE_AT + */ + public java.sql.Timestamp getExpireAt(){ + onPropGet(PROP_ID_expireAt); + return _expireAt; + } + + /** + * 过期时间: EXPIRE_AT + */ + public void setExpireAt(java.sql.Timestamp value){ + if(onPropSet(PROP_ID_expireAt,value)){ + this._expireAt = value; + internalClearRefs(PROP_ID_expireAt); + + } + } + + /** + * 应用ID: APP_ID + */ + public java.lang.String getAppId(){ + onPropGet(PROP_ID_appId); + return _appId; + } + + /** + * 应用ID: APP_ID + */ + public void setAppId(java.lang.String value){ + if(onPropSet(PROP_ID_appId,value)){ + this._appId = value; + internalClearRefs(PROP_ID_appId); + + } + } + +} +// resume CPD analysis - CPD-ON diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/_NopSysLock.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/_NopSysLock.java new file mode 100644 index 000000000..48e3e4cdb --- /dev/null +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/entity/_gen/_NopSysLock.java @@ -0,0 +1,527 @@ +package io.nop.sys.dao.entity._gen; + +import io.nop.orm.model.IEntityModel; +import io.nop.orm.support.DynamicOrmEntity; +import io.nop.orm.support.OrmEntitySet; //NOPMD - suppressed UnusedImports - Auto Gen Code +import io.nop.orm.IOrmEntitySet; //NOPMD - suppressed UnusedImports - Auto Gen Code +import io.nop.api.core.convert.ConvertHelper; +import java.util.Map; +import java.util.HashMap; +import java.util.Arrays; +import java.util.List; + +import io.nop.sys.dao.entity.NopSysLock; + +// tell cpd to start ignoring code - CPD-OFF +/** + * 资源锁: nop_sys_lock + */ +@SuppressWarnings({"PMD.UselessOverridingMethod","PMD.UnusedLocalVariable", + "PMD.UnnecessaryFullyQualifiedName","PMD.EmptyControlStatement"}) +public class _NopSysLock extends DynamicOrmEntity{ + + /* 分组: LOCK_GROUP VARCHAR */ + public static final String PROP_NAME_lockGroup = "lockGroup"; + public static final int PROP_ID_lockGroup = 1; + + /* 锁名称: LOCK_NAME VARCHAR */ + public static final String PROP_NAME_lockName = "lockName"; + public static final int PROP_ID_lockName = 2; + + /* 锁定时间: LOCK_TIME TIMESTAMP */ + public static final String PROP_NAME_lockTime = "lockTime"; + public static final int PROP_ID_lockTime = 3; + + /* 过期时间: EXPIRE_AT TIMESTAMP */ + public static final String PROP_NAME_expireAt = "expireAt"; + public static final int PROP_ID_expireAt = 4; + + /* 锁定原因: LOCK_REASON VARCHAR */ + public static final String PROP_NAME_lockReason = "lockReason"; + public static final int PROP_ID_lockReason = 5; + + /* 锁的持有者: HOLDER_ID VARCHAR */ + public static final String PROP_NAME_holderId = "holderId"; + public static final int PROP_ID_holderId = 6; + + /* 持有者地址: HOLDER_ADDER VARCHAR */ + public static final String PROP_NAME_holderAdder = "holderAdder"; + public static final int PROP_ID_holderAdder = 7; + + /* 应用ID: APP_ID VARCHAR */ + public static final String PROP_NAME_appId = "appId"; + public static final int PROP_ID_appId = 8; + + + private static int _PROP_ID_BOUND = 9; + + + + public static final List PK_PROP_NAMES = Arrays.asList(PROP_NAME_lockGroup,PROP_NAME_lockName); + public static final int[] PK_PROP_IDS = new int[]{PROP_ID_lockGroup,PROP_ID_lockName}; + + private static final String[] PROP_ID_TO_NAME = new String[9]; + private static final Map PROP_NAME_TO_ID = new HashMap<>(); + static{ + + PROP_ID_TO_NAME[PROP_ID_lockGroup] = PROP_NAME_lockGroup; + PROP_NAME_TO_ID.put(PROP_NAME_lockGroup, PROP_ID_lockGroup); + + PROP_ID_TO_NAME[PROP_ID_lockName] = PROP_NAME_lockName; + PROP_NAME_TO_ID.put(PROP_NAME_lockName, PROP_ID_lockName); + + PROP_ID_TO_NAME[PROP_ID_lockTime] = PROP_NAME_lockTime; + PROP_NAME_TO_ID.put(PROP_NAME_lockTime, PROP_ID_lockTime); + + PROP_ID_TO_NAME[PROP_ID_expireAt] = PROP_NAME_expireAt; + PROP_NAME_TO_ID.put(PROP_NAME_expireAt, PROP_ID_expireAt); + + PROP_ID_TO_NAME[PROP_ID_lockReason] = PROP_NAME_lockReason; + PROP_NAME_TO_ID.put(PROP_NAME_lockReason, PROP_ID_lockReason); + + PROP_ID_TO_NAME[PROP_ID_holderId] = PROP_NAME_holderId; + PROP_NAME_TO_ID.put(PROP_NAME_holderId, PROP_ID_holderId); + + PROP_ID_TO_NAME[PROP_ID_holderAdder] = PROP_NAME_holderAdder; + PROP_NAME_TO_ID.put(PROP_NAME_holderAdder, PROP_ID_holderAdder); + + PROP_ID_TO_NAME[PROP_ID_appId] = PROP_NAME_appId; + PROP_NAME_TO_ID.put(PROP_NAME_appId, PROP_ID_appId); + + } + + + /* 分组: LOCK_GROUP */ + private java.lang.String _lockGroup; + + /* 锁名称: LOCK_NAME */ + private java.lang.String _lockName; + + /* 锁定时间: LOCK_TIME */ + private java.sql.Timestamp _lockTime; + + /* 过期时间: EXPIRE_AT */ + private java.sql.Timestamp _expireAt; + + /* 锁定原因: LOCK_REASON */ + private java.lang.String _lockReason; + + /* 锁的持有者: HOLDER_ID */ + private java.lang.String _holderId; + + /* 持有者地址: HOLDER_ADDER */ + private java.lang.String _holderAdder; + + /* 应用ID: APP_ID */ + private java.lang.String _appId; + + + public _NopSysLock(){ + } + + protected NopSysLock newInstance(){ + return new NopSysLock(); + } + + @Override + public NopSysLock cloneInstance() { + NopSysLock entity = newInstance(); + orm_forEachInitedProp((value, propId) -> { + entity.onInitProp(propId); + }); + return entity; + } + + @Override + public String orm_entityName() { + // 如果存在实体模型对象,则以模型对象上的设置为准 + IEntityModel entityModel = orm_entityModel(); + if(entityModel != null) + return entityModel.getName(); + return "io.nop.sys.dao.entity.NopSysLock"; + } + + @Override + public int orm_propIdBound(){ + IEntityModel entityModel = orm_entityModel(); + if(entityModel != null) + return entityModel.getPropIdBound(); + return _PROP_ID_BOUND; + } + + @Override + public Object orm_id() { + + return buildCompositeId(PK_PROP_NAMES,PK_PROP_IDS); + + } + + @Override + public boolean orm_isPrimary(int propId) { + + return propId == PROP_ID_lockGroup || propId == PROP_ID_lockName; + + } + + @Override + public String orm_propName(int propId) { + if(propId >= PROP_ID_TO_NAME.length) + return super.orm_propName(propId); + String propName = PROP_ID_TO_NAME[propId]; + if(propName == null) + return super.orm_propName(propId); + return propName; + } + + @Override + public int orm_propId(String propName) { + Integer propId = PROP_NAME_TO_ID.get(propName); + if(propId == null) + return super.orm_propId(propName); + return propId; + } + + @Override + public Object orm_propValue(int propId) { + switch(propId){ + + case PROP_ID_lockGroup: + return getLockGroup(); + + case PROP_ID_lockName: + return getLockName(); + + case PROP_ID_lockTime: + return getLockTime(); + + case PROP_ID_expireAt: + return getExpireAt(); + + case PROP_ID_lockReason: + return getLockReason(); + + case PROP_ID_holderId: + return getHolderId(); + + case PROP_ID_holderAdder: + return getHolderAdder(); + + case PROP_ID_appId: + return getAppId(); + + default: + return super.orm_propValue(propId); + } + } + + + + @Override + public void orm_propValue(int propId, Object value){ + switch(propId){ + + case PROP_ID_lockGroup:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_lockGroup)); + } + setLockGroup(typedValue); + break; + } + + case PROP_ID_lockName:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_lockName)); + } + setLockName(typedValue); + break; + } + + case PROP_ID_lockTime:{ + java.sql.Timestamp typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toTimestamp(value, + err-> newTypeConversionError(PROP_NAME_lockTime)); + } + setLockTime(typedValue); + break; + } + + case PROP_ID_expireAt:{ + java.sql.Timestamp typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toTimestamp(value, + err-> newTypeConversionError(PROP_NAME_expireAt)); + } + setExpireAt(typedValue); + break; + } + + case PROP_ID_lockReason:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_lockReason)); + } + setLockReason(typedValue); + break; + } + + case PROP_ID_holderId:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_holderId)); + } + setHolderId(typedValue); + break; + } + + case PROP_ID_holderAdder:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_holderAdder)); + } + setHolderAdder(typedValue); + break; + } + + case PROP_ID_appId:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_appId)); + } + setAppId(typedValue); + break; + } + + default: + super.orm_propValue(propId,value); + } + } + + @Override + public void orm_internalSet(int propId, Object value) { + switch(propId){ + + case PROP_ID_lockGroup:{ + onInitProp(propId); + this._lockGroup = (java.lang.String)value; + orm_id(); // 如果是设置主键字段,则触发watcher + break; + } + + case PROP_ID_lockName:{ + onInitProp(propId); + this._lockName = (java.lang.String)value; + orm_id(); // 如果是设置主键字段,则触发watcher + break; + } + + case PROP_ID_lockTime:{ + onInitProp(propId); + this._lockTime = (java.sql.Timestamp)value; + + break; + } + + case PROP_ID_expireAt:{ + onInitProp(propId); + this._expireAt = (java.sql.Timestamp)value; + + break; + } + + case PROP_ID_lockReason:{ + onInitProp(propId); + this._lockReason = (java.lang.String)value; + + break; + } + + case PROP_ID_holderId:{ + onInitProp(propId); + this._holderId = (java.lang.String)value; + + break; + } + + case PROP_ID_holderAdder:{ + onInitProp(propId); + this._holderAdder = (java.lang.String)value; + + break; + } + + case PROP_ID_appId:{ + onInitProp(propId); + this._appId = (java.lang.String)value; + + break; + } + + default: + super.orm_internalSet(propId,value); + } + } + + + /** + * 分组: LOCK_GROUP + */ + public java.lang.String getLockGroup(){ + onPropGet(PROP_ID_lockGroup); + return _lockGroup; + } + + /** + * 分组: LOCK_GROUP + */ + public void setLockGroup(java.lang.String value){ + if(onPropSet(PROP_ID_lockGroup,value)){ + this._lockGroup = value; + internalClearRefs(PROP_ID_lockGroup); + orm_id(); + } + } + + /** + * 锁名称: LOCK_NAME + */ + public java.lang.String getLockName(){ + onPropGet(PROP_ID_lockName); + return _lockName; + } + + /** + * 锁名称: LOCK_NAME + */ + public void setLockName(java.lang.String value){ + if(onPropSet(PROP_ID_lockName,value)){ + this._lockName = value; + internalClearRefs(PROP_ID_lockName); + orm_id(); + } + } + + /** + * 锁定时间: LOCK_TIME + */ + public java.sql.Timestamp getLockTime(){ + onPropGet(PROP_ID_lockTime); + return _lockTime; + } + + /** + * 锁定时间: LOCK_TIME + */ + public void setLockTime(java.sql.Timestamp value){ + if(onPropSet(PROP_ID_lockTime,value)){ + this._lockTime = value; + internalClearRefs(PROP_ID_lockTime); + + } + } + + /** + * 过期时间: EXPIRE_AT + */ + public java.sql.Timestamp getExpireAt(){ + onPropGet(PROP_ID_expireAt); + return _expireAt; + } + + /** + * 过期时间: EXPIRE_AT + */ + public void setExpireAt(java.sql.Timestamp value){ + if(onPropSet(PROP_ID_expireAt,value)){ + this._expireAt = value; + internalClearRefs(PROP_ID_expireAt); + + } + } + + /** + * 锁定原因: LOCK_REASON + */ + public java.lang.String getLockReason(){ + onPropGet(PROP_ID_lockReason); + return _lockReason; + } + + /** + * 锁定原因: LOCK_REASON + */ + public void setLockReason(java.lang.String value){ + if(onPropSet(PROP_ID_lockReason,value)){ + this._lockReason = value; + internalClearRefs(PROP_ID_lockReason); + + } + } + + /** + * 锁的持有者: HOLDER_ID + */ + public java.lang.String getHolderId(){ + onPropGet(PROP_ID_holderId); + return _holderId; + } + + /** + * 锁的持有者: HOLDER_ID + */ + public void setHolderId(java.lang.String value){ + if(onPropSet(PROP_ID_holderId,value)){ + this._holderId = value; + internalClearRefs(PROP_ID_holderId); + + } + } + + /** + * 持有者地址: HOLDER_ADDER + */ + public java.lang.String getHolderAdder(){ + onPropGet(PROP_ID_holderAdder); + return _holderAdder; + } + + /** + * 持有者地址: HOLDER_ADDER + */ + public void setHolderAdder(java.lang.String value){ + if(onPropSet(PROP_ID_holderAdder,value)){ + this._holderAdder = value; + internalClearRefs(PROP_ID_holderAdder); + + } + } + + /** + * 应用ID: APP_ID + */ + public java.lang.String getAppId(){ + onPropGet(PROP_ID_appId); + return _appId; + } + + /** + * 应用ID: APP_ID + */ + public void setAppId(java.lang.String value){ + if(onPropSet(PROP_ID_appId,value)){ + this._appId = value; + internalClearRefs(PROP_ID_appId); + + } + } + +} +// resume CPD analysis - CPD-ON diff --git a/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/lock/SysDaoResourceLockManager.java b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/lock/SysDaoResourceLockManager.java new file mode 100644 index 000000000..21c8694e6 --- /dev/null +++ b/nop-sys/nop-sys-dao/src/main/java/io/nop/sys/dao/lock/SysDaoResourceLockManager.java @@ -0,0 +1,66 @@ +package io.nop.sys.dao.lock; + +import io.nop.commons.concurrent.lock.IResourceLock; +import io.nop.commons.concurrent.lock.IResourceLockManager; +import io.nop.commons.concurrent.lock.IResourceLockState; +import io.nop.commons.concurrent.lock.impl.IResourceLockManagerImplementor; + +import javax.annotation.Nonnull; + +public class SysDaoResourceLockManager implements IResourceLockManager, IResourceLockManagerImplementor { + private long defaultWaitTime = 1000; // 1s + private long defaultLeaseTime = 10000; // 10s + + public void setDefaultWaitTime(long defaultWaitTime) { + this.defaultWaitTime = defaultWaitTime; + } + + public void setDefaultLeaseTime(long defaultLeaseTime) { + this.defaultLeaseTime = defaultLeaseTime; + } + + @Override + public long getDefaultWaitTime() { + return defaultWaitTime; + } + + @Override + public long getDefaultLeaseTime() { + return defaultLeaseTime; + } + + @Override + public IResourceLock getLock(@Nonnull String resourceId, String holderId) { + return null; + } + + @Override + public IResourceLockState getLockState(@Nonnull String resourceId) { + return null; + } + + @Override + public boolean forceUnlock(String resourceId) { + return false; + } + + @Override + public IResourceLockState tryLockWithLease(String resourceId, String lockerId, long waitTime, long leaseTime) { + return null; + } + + @Override + public boolean tryResetLease(IResourceLockState lock, long leaseTime) { + return false; + } + + @Override + public boolean isHoldingLock(IResourceLockState lock) { + return false; + } + + @Override + public void releaseLock(IResourceLockState lock) { + + } +} diff --git a/nop-sys/nop-sys-dao/src/main/resources/_vfs/nop/sys/orm/_app.orm.xml b/nop-sys/nop-sys-dao/src/main/resources/_vfs/nop/sys/orm/_app.orm.xml index b250ea210..f2e3c0472 100644 --- a/nop-sys/nop-sys-dao/src/main/resources/_vfs/nop/sys/orm/_app.orm.xml +++ b/nop-sys/nop-sys-dao/src/main/resources/_vfs/nop/sys/orm/_app.orm.xml @@ -423,5 +423,49 @@ stdSqlType="VARCHAR" i18n-en:displayName="Remark"/> + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/_templates/_NopSysClusterLeader.json b/nop-sys/nop-sys-service/_templates/_NopSysClusterLeader.json new file mode 100644 index 000000000..315cd73e5 --- /dev/null +++ b/nop-sys/nop-sys-service/_templates/_NopSysClusterLeader.json @@ -0,0 +1,9 @@ +{ + "clusterId": "", + "leaderId": "", + "leaderAdder": "", + "leaderEpoch": 0, + "electTime": "2000-01-01 14:00:00", + "expireAt": "2000-01-01 14:00:00", + "appId": "" +} \ No newline at end of file diff --git a/nop-sys/nop-sys-service/_templates/_NopSysLock.json b/nop-sys/nop-sys-service/_templates/_NopSysLock.json new file mode 100644 index 000000000..4df33b5c7 --- /dev/null +++ b/nop-sys/nop-sys-service/_templates/_NopSysLock.json @@ -0,0 +1,10 @@ +{ + "lockGroup": "", + "lockName": "", + "lockTime": "2000-01-01 14:00:00", + "expireAt": "2000-01-01 14:00:00", + "lockReason": "", + "holderId": "", + "holderAdder": "", + "appId": "" +} \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/java/io/nop/sys/service/entity/NopSysClusterLeaderBizModel.java b/nop-sys/nop-sys-service/src/main/java/io/nop/sys/service/entity/NopSysClusterLeaderBizModel.java new file mode 100644 index 000000000..940498410 --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/java/io/nop/sys/service/entity/NopSysClusterLeaderBizModel.java @@ -0,0 +1,14 @@ + +package io.nop.sys.service.entity; + +import io.nop.api.core.annotations.biz.BizModel; +import io.nop.biz.crud.CrudBizModel; + +import io.nop.sys.dao.entity.NopSysClusterLeader; + +@BizModel("NopSysClusterLeader") +public class NopSysClusterLeaderBizModel extends CrudBizModel{ + public NopSysClusterLeaderBizModel(){ + setEntityName(NopSysClusterLeader.class.getName()); + } +} diff --git a/nop-sys/nop-sys-service/src/main/java/io/nop/sys/service/entity/NopSysLockBizModel.java b/nop-sys/nop-sys-service/src/main/java/io/nop/sys/service/entity/NopSysLockBizModel.java new file mode 100644 index 000000000..76cfd470d --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/java/io/nop/sys/service/entity/NopSysLockBizModel.java @@ -0,0 +1,14 @@ + +package io.nop.sys.service.entity; + +import io.nop.api.core.annotations.biz.BizModel; +import io.nop.biz.crud.CrudBizModel; + +import io.nop.sys.dao.entity.NopSysLock; + +@BizModel("NopSysLock") +public class NopSysLockBizModel extends CrudBizModel{ + public NopSysLockBizModel(){ + setEntityName(NopSysLock.class.getName()); + } +} diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/en/_nop-sys.i18n.yaml b/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/en/_nop-sys.i18n.yaml index 3604544fd..298f64c78 100644 --- a/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/en/_nop-sys.i18n.yaml +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/en/_nop-sys.i18n.yaml @@ -1,10 +1,12 @@ entity: label: + NopSysClusterLeader: Cluster Leader NopSysCodeRule: Code Rule NopSysDict: Dictionary NopSysDictOption: Dictionay Item NopSysExtField: Extension Field NopSysI18n: I18n Message + NopSysLock: Lock NopSysMakerCheckerRecord: Maker Checker Record NopSysNoticeTemplate: Notice Template NopSysSequence: Sequence @@ -12,6 +14,14 @@ entity: NopSysVariable: System Variable prop: label: + NopSysClusterLeader: + clusterId: Cluster ID + leaderId: Leader ID + leaderAdder: Leader Addr + leaderEpoch: Leader Epoch + electTime: Elect Time + expireAt: Expire At + appId: App ID NopSysCodeRule: sid: SID name: Name @@ -82,6 +92,15 @@ prop: updatedBy: Updated By updateTime: Update Time remark: Remark + NopSysLock: + lockGroup: Lock Group + lockName: Lock Name + lockTime: Lock Time + expireAt: Expire At + lockReason: Lock Reason + holderId: Holder ID + holderAdder: Holder Addr + appId: App ID NopSysMakerCheckerRecord: sid: SID bizObjName: Biz Object Name diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/zh-CN/_nop-sys.i18n.yaml b/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/zh-CN/_nop-sys.i18n.yaml index 8392c59de..88f6adbed 100644 --- a/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/zh-CN/_nop-sys.i18n.yaml +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/i18n/zh-CN/_nop-sys.i18n.yaml @@ -1,10 +1,12 @@ entity: label: + NopSysClusterLeader: 集群选举 NopSysCodeRule: 编码规则 NopSysDict: 字典表 NopSysDictOption: 字典明细 NopSysExtField: 扩展字段 NopSysI18n: 多语言消息 + NopSysLock: 资源锁 NopSysMakerCheckerRecord: MakerChecker审批记录 NopSysNoticeTemplate: 通知模板 NopSysSequence: 序列号 @@ -12,6 +14,14 @@ entity: NopSysVariable: 系统变量 prop: label: + NopSysClusterLeader: + appId: 应用ID + clusterId: 集群ID + electTime: 选举时间 + expireAt: 过期时间 + leaderAdder: 主服务器地址 + leaderEpoch: 选举世代 + leaderId: 主服务器ID NopSysCodeRule: codePattern: 编码模式 createTime: 创建时间 @@ -82,6 +92,15 @@ prop: updatedBy: 修改人 value: 值 version: 数据版本 + NopSysLock: + appId: 应用ID + expireAt: 过期时间 + holderAdder: 持有者地址 + holderId: 锁的持有者 + lockGroup: 分组 + lockName: 锁名称 + lockReason: 锁定原因 + lockTime: 锁定时间 NopSysMakerCheckerRecord: bizObjId: 业务对象ID bizObjName: 业务对象名 diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/beans/_service.beans.xml b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/beans/_service.beans.xml index 523118346..3ba96dd03 100644 --- a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/beans/_service.beans.xml +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/beans/_service.beans.xml @@ -4,6 +4,8 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + + @@ -14,6 +16,8 @@ + + diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/NopSysClusterLeader.xbiz b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/NopSysClusterLeader.xbiz new file mode 100644 index 000000000..6c62c606e --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/NopSysClusterLeader.xbiz @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/NopSysClusterLeader.xmeta b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/NopSysClusterLeader.xmeta new file mode 100644 index 000000000..47793bef1 --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/NopSysClusterLeader.xmeta @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/_NopSysClusterLeader.xbiz b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/_NopSysClusterLeader.xbiz new file mode 100644 index 000000000..43f2df4a7 --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/_NopSysClusterLeader.xbiz @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/_NopSysClusterLeader.xmeta b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/_NopSysClusterLeader.xmeta new file mode 100644 index 000000000..100423835 --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysClusterLeader/_NopSysClusterLeader.xmeta @@ -0,0 +1,46 @@ + + + + io.nop.sys.dao.entity.NopSysClusterLeader + + clusterId + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/NopSysLock.xbiz b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/NopSysLock.xbiz new file mode 100644 index 000000000..46a15469a --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/NopSysLock.xbiz @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/NopSysLock.xmeta b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/NopSysLock.xmeta new file mode 100644 index 000000000..811016a4b --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/NopSysLock.xmeta @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/_NopSysLock.xbiz b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/_NopSysLock.xbiz new file mode 100644 index 000000000..43f2df4a7 --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/_NopSysLock.xbiz @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/_NopSysLock.xmeta b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/_NopSysLock.xmeta new file mode 100644 index 000000000..b2ebad073 --- /dev/null +++ b/nop-sys/nop-sys-service/src/main/resources/_vfs/nop/sys/model/NopSysLock/_NopSysLock.xmeta @@ -0,0 +1,50 @@ + + + + io.nop.sys.dao.entity.NopSysLock + + lockGroup,lockName + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/auth/_nop-sys.action-auth.xml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/auth/_nop-sys.action-auth.xml index 1aedf1f41..62c050819 100644 --- a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/auth/_nop-sys.action-auth.xml +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/auth/_nop-sys.action-auth.xml @@ -5,137 +5,163 @@ - + + + NopSysClusterLeader:query + + + NopSysClusterLeader:mutation + + + + - NopSysCodeRule:query - NopSysCodeRule:mutation - - + NopSysDict:query - + NopSysDict:mutation - - NopSysDictOption:query - NopSysDictOption:mutation - - NopSysExtField:query - NopSysExtField:mutation - - + NopSysI18n:query - NopSysI18n:mutation - + + + NopSysLock:query + + + NopSysLock:mutation + + + + + orderNo="10023" resourceType="FNPT"> NopSysMakerCheckerRecord:query + orderNo="10024" resourceType="FNPT"> NopSysMakerCheckerRecord:mutation - - NopSysNoticeTemplate:query - NopSysNoticeTemplate:mutation - - + NopSysSequence:query - NopSysSequence:mutation - - NopSysUserVariable:query - NopSysUserVariable:mutation - - NopSysVariable:query - NopSysVariable:mutation diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/NopSysClusterLeader.lib.xjs b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/NopSysClusterLeader.lib.xjs new file mode 100644 index 000000000..6bb977c92 --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/NopSysClusterLeader.lib.xjs @@ -0,0 +1,10 @@ +// x:gen-extends用于动态生成代码 +/* @x:gen-extends: +*/ + +/* +// @action:name 触发这里的函数,options为ajax请求参数 +export function myAction(options, page,scoped){ + return page.env.fetcher(options) +} +*/ \ No newline at end of file diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/NopSysClusterLeader.view.xml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/NopSysClusterLeader.view.xml new file mode 100644 index 000000000..ac1f0daf2 --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/NopSysClusterLeader.view.xml @@ -0,0 +1,20 @@ + + + + + + + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/_gen/_NopSysClusterLeader.view.xml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/_gen/_NopSysClusterLeader.view.xml new file mode 100644 index 000000000..19d22062c --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/_gen/_NopSysClusterLeader.view.xml @@ -0,0 +1,125 @@ + + + + /nop/sys/model/NopSysClusterLeader/NopSysClusterLeader.xmeta + + /nop/web/xlib/control.xlib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + clusterId[集群ID] + leaderId[主服务器ID] + leaderAdder[主服务器地址] + leaderEpoch[选举世代] + electTime[选举时间] + expireAt[过期时间] + appId[应用ID] + + +
+ + + clusterId[集群ID] + leaderId[主服务器ID] + leaderAdder[主服务器地址] + leaderEpoch[选举世代] + electTime[选举时间] + expireAt[过期时间] + appId[应用ID] + +
+
+ + +
+ + +
+ + +
+ + + + + +
+ + + + @i18n:common.confirmBatchDelete + + + + + + + + + + + + + + + @i18n:common.confirmDelete + + + + + + + + @i18n:common.confirmDelete + + + +
+ + + +
+
+ + + + + + + + + + +
+
\ No newline at end of file diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/main.page.yaml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/main.page.yaml new file mode 100644 index 000000000..338e89805 --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/main.page.yaml @@ -0,0 +1,3 @@ + +x:gen-extends: | + diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/picker.page.yaml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/picker.page.yaml new file mode 100644 index 000000000..def77d3fd --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysClusterLeader/picker.page.yaml @@ -0,0 +1,3 @@ + +x:gen-extends: | + diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/NopSysLock.lib.xjs b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/NopSysLock.lib.xjs new file mode 100644 index 000000000..6bb977c92 --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/NopSysLock.lib.xjs @@ -0,0 +1,10 @@ +// x:gen-extends用于动态生成代码 +/* @x:gen-extends: +*/ + +/* +// @action:name 触发这里的函数,options为ajax请求参数 +export function myAction(options, page,scoped){ + return page.env.fetcher(options) +} +*/ \ No newline at end of file diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/NopSysLock.view.xml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/NopSysLock.view.xml new file mode 100644 index 000000000..fbca39907 --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/NopSysLock.view.xml @@ -0,0 +1,19 @@ + + + + + + + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/_gen/_NopSysLock.view.xml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/_gen/_NopSysLock.view.xml new file mode 100644 index 000000000..d4cea4c85 --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/_gen/_NopSysLock.view.xml @@ -0,0 +1,130 @@ + + + + /nop/sys/model/NopSysLock/NopSysLock.xmeta + + /nop/web/xlib/control.xlib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lockGroup[分组] + lockName[锁名称] + lockTime[锁定时间] + expireAt[过期时间] + lockReason[锁定原因] + holderId[锁的持有者] + holderAdder[持有者地址] + appId[应用ID] + + +
+ + + lockGroup[分组] + lockName[锁名称] + lockTime[锁定时间] + expireAt[过期时间] + lockReason[锁定原因] + holderId[锁的持有者] + holderAdder[持有者地址] + appId[应用ID] + +
+
+ + +
+ + +
+ + +
+ + + + + +
+ + + + @i18n:common.confirmBatchDelete + + + + + + + + + + + + + + + @i18n:common.confirmDelete + + + + + + + + @i18n:common.confirmDelete + + + +
+ + + +
+
+ + + + + + + + + + +
+
\ No newline at end of file diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/main.page.yaml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/main.page.yaml new file mode 100644 index 000000000..e93d3a6c9 --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/main.page.yaml @@ -0,0 +1,3 @@ + +x:gen-extends: | + diff --git a/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/picker.page.yaml b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/picker.page.yaml new file mode 100644 index 000000000..7e8109fef --- /dev/null +++ b/nop-sys/nop-sys-web/src/main/resources/_vfs/nop/sys/pages/NopSysLock/picker.page.yaml @@ -0,0 +1,3 @@ + +x:gen-extends: | + diff --git a/nop-tcc/deploy/sql/mysql/_create_nop-tcc.sql b/nop-tcc/deploy/sql/mysql/_create_nop-tcc.sql index 69b173d11..f265d7046 100644 --- a/nop-tcc/deploy/sql/mysql/_create_nop-tcc.sql +++ b/nop-tcc/deploy/sql/mysql/_create_nop-tcc.sql @@ -12,11 +12,16 @@ CREATE TABLE nop_tcc_branch_record( CANCEL_METHOD VARCHAR(200) NULL COMMENT '取消方法', REQUEST_DATA MEDIUMTEXT NULL COMMENT '请求数据', ERROR_CODE VARCHAR(200) NULL COMMENT '错误码', - ERROR_MESSAGE VARCHAR(200) NULL COMMENT '错误消息', + ERROR_MESSAGE VARCHAR(1000) NULL COMMENT '错误消息', + ERROR_STACK VARCHAR(1000) NULL COMMENT '错误堆栈', BEGIN_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '开始时间', END_TIME TIMESTAMP NULL COMMENT '结束时间', COMMIT_ERROR_CODE VARCHAR(200) NULL COMMENT '提交阶段错误码', - COMMIT_ERROR_MESSAGE VARCHAR(200) NULL COMMENT '提交阶段错误消息', + COMMIT_ERROR_MESSAGE VARCHAR(1000) NULL COMMENT '提交阶段错误消息', + COMMIT_ERROR_STACK VARCHAR(1000) NULL COMMENT '提交阶段错误堆栈', + CANCEL_ERROR_CODE VARCHAR(200) NULL COMMENT '取消阶段错误码', + CANCEL_ERROR_MESSAGE VARCHAR(1000) NULL COMMENT '取消阶段错误消息', + CANCEL_ERROR_STACK VARCHAR(1000) NULL COMMENT '取消阶段错误堆栈', RETRY_TIMES INTEGER NULL COMMENT '重试次数', MAX_RETRY_TIMES INTEGER NOT NULL COMMENT '最大重试次数', NEXT_RETRY_TIME TIMESTAMP NULL COMMENT '下次重试时间', @@ -36,6 +41,9 @@ CREATE TABLE nop_tcc_record( APP_DATA VARCHAR(2000) NULL COMMENT '应用数据', BEGIN_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '开始时间', END_TIME TIMESTAMP NULL COMMENT '结束时间', + ERROR_CODE VARCHAR(200) NULL COMMENT '错误码', + ERROR_MESSAGE VARCHAR(1000) NULL COMMENT '错误消息', + ERROR_STACK VARCHAR(1000) NULL COMMENT '错误堆栈', VERSION INTEGER NOT NULL COMMENT '数据版本', CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', UPDATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', diff --git a/nop-tcc/deploy/sql/oracle/_create_nop-tcc.sql b/nop-tcc/deploy/sql/oracle/_create_nop-tcc.sql index b537bd731..6d34b51d4 100644 --- a/nop-tcc/deploy/sql/oracle/_create_nop-tcc.sql +++ b/nop-tcc/deploy/sql/oracle/_create_nop-tcc.sql @@ -12,11 +12,16 @@ CREATE TABLE nop_tcc_branch_record( CANCEL_METHOD VARCHAR2(200) , REQUEST_DATA CLOB , ERROR_CODE VARCHAR2(200) , - ERROR_MESSAGE VARCHAR2(200) , + ERROR_MESSAGE VARCHAR2(1000) , + ERROR_STACK VARCHAR2(1000) , BEGIN_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , COMMIT_ERROR_CODE VARCHAR2(200) , - COMMIT_ERROR_MESSAGE VARCHAR2(200) , + COMMIT_ERROR_MESSAGE VARCHAR2(1000) , + COMMIT_ERROR_STACK VARCHAR2(1000) , + CANCEL_ERROR_CODE VARCHAR2(200) , + CANCEL_ERROR_MESSAGE VARCHAR2(1000) , + CANCEL_ERROR_STACK VARCHAR2(1000) , RETRY_TIMES INTEGER , MAX_RETRY_TIMES INTEGER NOT NULL , NEXT_RETRY_TIME TIMESTAMP , @@ -36,6 +41,9 @@ CREATE TABLE nop_tcc_record( APP_DATA VARCHAR2(2000) , BEGIN_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , + ERROR_CODE VARCHAR2(200) , + ERROR_MESSAGE VARCHAR2(1000) , + ERROR_STACK VARCHAR2(1000) , VERSION INTEGER NOT NULL , CREATE_TIME TIMESTAMP NOT NULL , UPDATE_TIME TIMESTAMP NOT NULL , @@ -71,6 +79,8 @@ CREATE TABLE nop_tcc_record( COMMENT ON COLUMN nop_tcc_branch_record.ERROR_MESSAGE IS '错误消息'; + COMMENT ON COLUMN nop_tcc_branch_record.ERROR_STACK IS '错误堆栈'; + COMMENT ON COLUMN nop_tcc_branch_record.BEGIN_TIME IS '开始时间'; COMMENT ON COLUMN nop_tcc_branch_record.END_TIME IS '结束时间'; @@ -79,6 +89,14 @@ CREATE TABLE nop_tcc_record( COMMENT ON COLUMN nop_tcc_branch_record.COMMIT_ERROR_MESSAGE IS '提交阶段错误消息'; + COMMENT ON COLUMN nop_tcc_branch_record.COMMIT_ERROR_STACK IS '提交阶段错误堆栈'; + + COMMENT ON COLUMN nop_tcc_branch_record.CANCEL_ERROR_CODE IS '取消阶段错误码'; + + COMMENT ON COLUMN nop_tcc_branch_record.CANCEL_ERROR_MESSAGE IS '取消阶段错误消息'; + + COMMENT ON COLUMN nop_tcc_branch_record.CANCEL_ERROR_STACK IS '取消阶段错误堆栈'; + COMMENT ON COLUMN nop_tcc_branch_record.RETRY_TIMES IS '重试次数'; COMMENT ON COLUMN nop_tcc_branch_record.MAX_RETRY_TIMES IS '最大重试次数'; @@ -111,6 +129,12 @@ CREATE TABLE nop_tcc_record( COMMENT ON COLUMN nop_tcc_record.END_TIME IS '结束时间'; + COMMENT ON COLUMN nop_tcc_record.ERROR_CODE IS '错误码'; + + COMMENT ON COLUMN nop_tcc_record.ERROR_MESSAGE IS '错误消息'; + + COMMENT ON COLUMN nop_tcc_record.ERROR_STACK IS '错误堆栈'; + COMMENT ON COLUMN nop_tcc_record.VERSION IS '数据版本'; COMMENT ON COLUMN nop_tcc_record.CREATE_TIME IS '创建时间'; diff --git a/nop-tcc/deploy/sql/postgresql/_create_nop-tcc.sql b/nop-tcc/deploy/sql/postgresql/_create_nop-tcc.sql index be474ba7e..e6779e2c8 100644 --- a/nop-tcc/deploy/sql/postgresql/_create_nop-tcc.sql +++ b/nop-tcc/deploy/sql/postgresql/_create_nop-tcc.sql @@ -12,11 +12,16 @@ CREATE TABLE nop_tcc_branch_record( CANCEL_METHOD VARCHAR(200) , REQUEST_DATA TEXT , ERROR_CODE VARCHAR(200) , - ERROR_MESSAGE VARCHAR(200) , + ERROR_MESSAGE VARCHAR(1000) , + ERROR_STACK VARCHAR(1000) , BEGIN_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , COMMIT_ERROR_CODE VARCHAR(200) , - COMMIT_ERROR_MESSAGE VARCHAR(200) , + COMMIT_ERROR_MESSAGE VARCHAR(1000) , + COMMIT_ERROR_STACK VARCHAR(1000) , + CANCEL_ERROR_CODE VARCHAR(200) , + CANCEL_ERROR_MESSAGE VARCHAR(1000) , + CANCEL_ERROR_STACK VARCHAR(1000) , RETRY_TIMES INT4 , MAX_RETRY_TIMES INT4 NOT NULL , NEXT_RETRY_TIME TIMESTAMP , @@ -36,6 +41,9 @@ CREATE TABLE nop_tcc_record( APP_DATA VARCHAR(2000) , BEGIN_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , + ERROR_CODE VARCHAR(200) , + ERROR_MESSAGE VARCHAR(1000) , + ERROR_STACK VARCHAR(1000) , VERSION INT4 NOT NULL , CREATE_TIME TIMESTAMP NOT NULL , UPDATE_TIME TIMESTAMP NOT NULL , @@ -71,6 +79,8 @@ CREATE TABLE nop_tcc_record( COMMENT ON COLUMN nop_tcc_branch_record.ERROR_MESSAGE IS '错误消息'; + COMMENT ON COLUMN nop_tcc_branch_record.ERROR_STACK IS '错误堆栈'; + COMMENT ON COLUMN nop_tcc_branch_record.BEGIN_TIME IS '开始时间'; COMMENT ON COLUMN nop_tcc_branch_record.END_TIME IS '结束时间'; @@ -79,6 +89,14 @@ CREATE TABLE nop_tcc_record( COMMENT ON COLUMN nop_tcc_branch_record.COMMIT_ERROR_MESSAGE IS '提交阶段错误消息'; + COMMENT ON COLUMN nop_tcc_branch_record.COMMIT_ERROR_STACK IS '提交阶段错误堆栈'; + + COMMENT ON COLUMN nop_tcc_branch_record.CANCEL_ERROR_CODE IS '取消阶段错误码'; + + COMMENT ON COLUMN nop_tcc_branch_record.CANCEL_ERROR_MESSAGE IS '取消阶段错误消息'; + + COMMENT ON COLUMN nop_tcc_branch_record.CANCEL_ERROR_STACK IS '取消阶段错误堆栈'; + COMMENT ON COLUMN nop_tcc_branch_record.RETRY_TIMES IS '重试次数'; COMMENT ON COLUMN nop_tcc_branch_record.MAX_RETRY_TIMES IS '最大重试次数'; @@ -111,6 +129,12 @@ CREATE TABLE nop_tcc_record( COMMENT ON COLUMN nop_tcc_record.END_TIME IS '结束时间'; + COMMENT ON COLUMN nop_tcc_record.ERROR_CODE IS '错误码'; + + COMMENT ON COLUMN nop_tcc_record.ERROR_MESSAGE IS '错误消息'; + + COMMENT ON COLUMN nop_tcc_record.ERROR_STACK IS '错误堆栈'; + COMMENT ON COLUMN nop_tcc_record.VERSION IS '数据版本'; COMMENT ON COLUMN nop_tcc_record.CREATE_TIME IS '创建时间'; diff --git a/nop-tcc/model/nop-tcc.orm.xlsx b/nop-tcc/model/nop-tcc.orm.xlsx index bc444a21d..3aa382cd4 100644 Binary files a/nop-tcc/model/nop-tcc.orm.xlsx and b/nop-tcc/model/nop-tcc.orm.xlsx differ diff --git a/nop-tcc/nop-tcc-api/src/main/java/io/nop/tcc/api/ITccBranchRecord.java b/nop-tcc/nop-tcc-api/src/main/java/io/nop/tcc/api/ITccBranchRecord.java index 7659c5eb7..cad92519e 100644 --- a/nop-tcc/nop-tcc-api/src/main/java/io/nop/tcc/api/ITccBranchRecord.java +++ b/nop-tcc/nop-tcc-api/src/main/java/io/nop/tcc/api/ITccBranchRecord.java @@ -18,7 +18,7 @@ public interface ITccBranchRecord { String getBranchId(); - int getBranchNo(); + Integer getBranchNo(); String getParentBranchId(); @@ -34,9 +34,9 @@ public interface ITccBranchRecord { TccStatus getBranchStatus(); - int getMaxRetry(); + Integer getMaxRetryTimes(); - int getRetry(); + Integer getRetryTimes(); Timestamp getCreateTime(); diff --git a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccBranchRecord.java b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccBranchRecord.java index a46ffb634..0ef668047 100644 --- a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccBranchRecord.java +++ b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccBranchRecord.java @@ -1,13 +1,34 @@ package io.nop.tcc.dao.entity; import io.nop.api.core.annotations.biz.BizObjName; +import io.nop.api.core.beans.ApiRequest; +import io.nop.core.lang.json.JsonTool; +import io.nop.tcc.api.ITccBranchRecord; +import io.nop.tcc.api.TccStatus; import io.nop.tcc.dao.entity._gen._NopTccBranchRecord; @BizObjName("NopTccBranchRecord") -public class NopTccBranchRecord extends _NopTccBranchRecord{ - public NopTccBranchRecord(){ +public class NopTccBranchRecord extends _NopTccBranchRecord implements ITccBranchRecord { + public NopTccBranchRecord() { } + @Override + public String getTxnGroup() { + NopTccRecord record = getTccRecord(); + return record == null ? null : record.getTxnGroup(); + } + + @Override + public ApiRequest getRequest() { + return (ApiRequest) JsonTool.parseBeanFromText(getRequestData(), ApiRequest.class); + } + @Override + public TccStatus getBranchStatus() { + Integer status = getStatus(); + if (status == null) + return null; + return TccStatus.fromCode(status); + } } diff --git a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccRecord.java b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccRecord.java index 0646e42e9..a89ad2d1a 100644 --- a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccRecord.java +++ b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/NopTccRecord.java @@ -1,13 +1,22 @@ package io.nop.tcc.dao.entity; import io.nop.api.core.annotations.biz.BizObjName; +import io.nop.tcc.api.ITccRecord; +import io.nop.tcc.api.TccStatus; import io.nop.tcc.dao.entity._gen._NopTccRecord; @BizObjName("NopTccRecord") -public class NopTccRecord extends _NopTccRecord{ - public NopTccRecord(){ +public class NopTccRecord extends _NopTccRecord implements ITccRecord { + public NopTccRecord() { } + @Override + public TccStatus getTccStatus() { + Integer status = getStatus(); + if (status == null) + return null; + return TccStatus.fromCode(status); + } } diff --git a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccBranchRecord.java b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccBranchRecord.java index 981d42b57..0bba25155 100644 --- a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccBranchRecord.java +++ b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccBranchRecord.java @@ -72,48 +72,68 @@ public class _NopTccBranchRecord extends DynamicOrmEntity{ public static final String PROP_NAME_errorMessage = "errorMessage"; public static final int PROP_ID_errorMessage = 13; + /* 错误堆栈: ERROR_STACK VARCHAR */ + public static final String PROP_NAME_errorStack = "errorStack"; + public static final int PROP_ID_errorStack = 14; + /* 开始时间: BEGIN_TIME TIMESTAMP */ public static final String PROP_NAME_beginTime = "beginTime"; - public static final int PROP_ID_beginTime = 14; + public static final int PROP_ID_beginTime = 15; /* 结束时间: END_TIME TIMESTAMP */ public static final String PROP_NAME_endTime = "endTime"; - public static final int PROP_ID_endTime = 15; + public static final int PROP_ID_endTime = 16; /* 提交阶段错误码: COMMIT_ERROR_CODE VARCHAR */ public static final String PROP_NAME_commitErrorCode = "commitErrorCode"; - public static final int PROP_ID_commitErrorCode = 16; + public static final int PROP_ID_commitErrorCode = 17; /* 提交阶段错误消息: COMMIT_ERROR_MESSAGE VARCHAR */ public static final String PROP_NAME_commitErrorMessage = "commitErrorMessage"; - public static final int PROP_ID_commitErrorMessage = 17; + public static final int PROP_ID_commitErrorMessage = 18; + + /* 提交阶段错误堆栈: COMMIT_ERROR_STACK VARCHAR */ + public static final String PROP_NAME_commitErrorStack = "commitErrorStack"; + public static final int PROP_ID_commitErrorStack = 19; + + /* 取消阶段错误码: CANCEL_ERROR_CODE VARCHAR */ + public static final String PROP_NAME_cancelErrorCode = "cancelErrorCode"; + public static final int PROP_ID_cancelErrorCode = 20; + + /* 取消阶段错误消息: CANCEL_ERROR_MESSAGE VARCHAR */ + public static final String PROP_NAME_cancelErrorMessage = "cancelErrorMessage"; + public static final int PROP_ID_cancelErrorMessage = 21; + + /* 取消阶段错误堆栈: CANCEL_ERROR_STACK VARCHAR */ + public static final String PROP_NAME_cancelErrorStack = "cancelErrorStack"; + public static final int PROP_ID_cancelErrorStack = 22; /* 重试次数: RETRY_TIMES INTEGER */ public static final String PROP_NAME_retryTimes = "retryTimes"; - public static final int PROP_ID_retryTimes = 18; + public static final int PROP_ID_retryTimes = 23; /* 最大重试次数: MAX_RETRY_TIMES INTEGER */ public static final String PROP_NAME_maxRetryTimes = "maxRetryTimes"; - public static final int PROP_ID_maxRetryTimes = 19; + public static final int PROP_ID_maxRetryTimes = 24; /* 下次重试时间: NEXT_RETRY_TIME TIMESTAMP */ public static final String PROP_NAME_nextRetryTime = "nextRetryTime"; - public static final int PROP_ID_nextRetryTime = 20; + public static final int PROP_ID_nextRetryTime = 25; /* 数据版本: VERSION INTEGER */ public static final String PROP_NAME_version = "version"; - public static final int PROP_ID_version = 21; + public static final int PROP_ID_version = 26; /* 创建时间: CREATE_TIME TIMESTAMP */ public static final String PROP_NAME_createTime = "createTime"; - public static final int PROP_ID_createTime = 22; + public static final int PROP_ID_createTime = 27; /* 修改时间: UPDATE_TIME TIMESTAMP */ public static final String PROP_NAME_updateTime = "updateTime"; - public static final int PROP_ID_updateTime = 23; + public static final int PROP_ID_updateTime = 28; - private static int _PROP_ID_BOUND = 24; + private static int _PROP_ID_BOUND = 29; /* relation: 事务记录 */ @@ -123,7 +143,7 @@ public class _NopTccBranchRecord extends DynamicOrmEntity{ public static final List PK_PROP_NAMES = Arrays.asList(PROP_NAME_branchId); public static final int[] PK_PROP_IDS = new int[]{PROP_ID_branchId}; - private static final String[] PROP_ID_TO_NAME = new String[24]; + private static final String[] PROP_ID_TO_NAME = new String[29]; private static final Map PROP_NAME_TO_ID = new HashMap<>(); static{ @@ -166,6 +186,9 @@ public class _NopTccBranchRecord extends DynamicOrmEntity{ PROP_ID_TO_NAME[PROP_ID_errorMessage] = PROP_NAME_errorMessage; PROP_NAME_TO_ID.put(PROP_NAME_errorMessage, PROP_ID_errorMessage); + PROP_ID_TO_NAME[PROP_ID_errorStack] = PROP_NAME_errorStack; + PROP_NAME_TO_ID.put(PROP_NAME_errorStack, PROP_ID_errorStack); + PROP_ID_TO_NAME[PROP_ID_beginTime] = PROP_NAME_beginTime; PROP_NAME_TO_ID.put(PROP_NAME_beginTime, PROP_ID_beginTime); @@ -178,6 +201,18 @@ public class _NopTccBranchRecord extends DynamicOrmEntity{ PROP_ID_TO_NAME[PROP_ID_commitErrorMessage] = PROP_NAME_commitErrorMessage; PROP_NAME_TO_ID.put(PROP_NAME_commitErrorMessage, PROP_ID_commitErrorMessage); + PROP_ID_TO_NAME[PROP_ID_commitErrorStack] = PROP_NAME_commitErrorStack; + PROP_NAME_TO_ID.put(PROP_NAME_commitErrorStack, PROP_ID_commitErrorStack); + + PROP_ID_TO_NAME[PROP_ID_cancelErrorCode] = PROP_NAME_cancelErrorCode; + PROP_NAME_TO_ID.put(PROP_NAME_cancelErrorCode, PROP_ID_cancelErrorCode); + + PROP_ID_TO_NAME[PROP_ID_cancelErrorMessage] = PROP_NAME_cancelErrorMessage; + PROP_NAME_TO_ID.put(PROP_NAME_cancelErrorMessage, PROP_ID_cancelErrorMessage); + + PROP_ID_TO_NAME[PROP_ID_cancelErrorStack] = PROP_NAME_cancelErrorStack; + PROP_NAME_TO_ID.put(PROP_NAME_cancelErrorStack, PROP_ID_cancelErrorStack); + PROP_ID_TO_NAME[PROP_ID_retryTimes] = PROP_NAME_retryTimes; PROP_NAME_TO_ID.put(PROP_NAME_retryTimes, PROP_ID_retryTimes); @@ -238,6 +273,9 @@ public class _NopTccBranchRecord extends DynamicOrmEntity{ /* 错误消息: ERROR_MESSAGE */ private java.lang.String _errorMessage; + /* 错误堆栈: ERROR_STACK */ + private java.lang.String _errorStack; + /* 开始时间: BEGIN_TIME */ private java.sql.Timestamp _beginTime; @@ -250,6 +288,18 @@ public class _NopTccBranchRecord extends DynamicOrmEntity{ /* 提交阶段错误消息: COMMIT_ERROR_MESSAGE */ private java.lang.String _commitErrorMessage; + /* 提交阶段错误堆栈: COMMIT_ERROR_STACK */ + private java.lang.String _commitErrorStack; + + /* 取消阶段错误码: CANCEL_ERROR_CODE */ + private java.lang.String _cancelErrorCode; + + /* 取消阶段错误消息: CANCEL_ERROR_MESSAGE */ + private java.lang.String _cancelErrorMessage; + + /* 取消阶段错误堆栈: CANCEL_ERROR_STACK */ + private java.lang.String _cancelErrorStack; + /* 重试次数: RETRY_TIMES */ private java.lang.Integer _retryTimes; @@ -377,6 +427,9 @@ public Object orm_propValue(int propId) { case PROP_ID_errorMessage: return getErrorMessage(); + case PROP_ID_errorStack: + return getErrorStack(); + case PROP_ID_beginTime: return getBeginTime(); @@ -389,6 +442,18 @@ public Object orm_propValue(int propId) { case PROP_ID_commitErrorMessage: return getCommitErrorMessage(); + case PROP_ID_commitErrorStack: + return getCommitErrorStack(); + + case PROP_ID_cancelErrorCode: + return getCancelErrorCode(); + + case PROP_ID_cancelErrorMessage: + return getCancelErrorMessage(); + + case PROP_ID_cancelErrorStack: + return getCancelErrorStack(); + case PROP_ID_retryTimes: return getRetryTimes(); @@ -548,6 +613,16 @@ public void orm_propValue(int propId, Object value){ break; } + case PROP_ID_errorStack:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_errorStack)); + } + setErrorStack(typedValue); + break; + } + case PROP_ID_beginTime:{ java.sql.Timestamp typedValue = null; if(value != null){ @@ -588,6 +663,46 @@ public void orm_propValue(int propId, Object value){ break; } + case PROP_ID_commitErrorStack:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_commitErrorStack)); + } + setCommitErrorStack(typedValue); + break; + } + + case PROP_ID_cancelErrorCode:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_cancelErrorCode)); + } + setCancelErrorCode(typedValue); + break; + } + + case PROP_ID_cancelErrorMessage:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_cancelErrorMessage)); + } + setCancelErrorMessage(typedValue); + break; + } + + case PROP_ID_cancelErrorStack:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_cancelErrorStack)); + } + setCancelErrorStack(typedValue); + break; + } + case PROP_ID_retryTimes:{ java.lang.Integer typedValue = null; if(value != null){ @@ -748,6 +863,13 @@ public void orm_internalSet(int propId, Object value) { break; } + case PROP_ID_errorStack:{ + onInitProp(propId); + this._errorStack = (java.lang.String)value; + + break; + } + case PROP_ID_beginTime:{ onInitProp(propId); this._beginTime = (java.sql.Timestamp)value; @@ -776,6 +898,34 @@ public void orm_internalSet(int propId, Object value) { break; } + case PROP_ID_commitErrorStack:{ + onInitProp(propId); + this._commitErrorStack = (java.lang.String)value; + + break; + } + + case PROP_ID_cancelErrorCode:{ + onInitProp(propId); + this._cancelErrorCode = (java.lang.String)value; + + break; + } + + case PROP_ID_cancelErrorMessage:{ + onInitProp(propId); + this._cancelErrorMessage = (java.lang.String)value; + + break; + } + + case PROP_ID_cancelErrorStack:{ + onInitProp(propId); + this._cancelErrorStack = (java.lang.String)value; + + break; + } + case PROP_ID_retryTimes:{ onInitProp(propId); this._retryTimes = (java.lang.Integer)value; @@ -1071,6 +1221,25 @@ public void setErrorMessage(java.lang.String value){ } } + /** + * 错误堆栈: ERROR_STACK + */ + public java.lang.String getErrorStack(){ + onPropGet(PROP_ID_errorStack); + return _errorStack; + } + + /** + * 错误堆栈: ERROR_STACK + */ + public void setErrorStack(java.lang.String value){ + if(onPropSet(PROP_ID_errorStack,value)){ + this._errorStack = value; + internalClearRefs(PROP_ID_errorStack); + + } + } + /** * 开始时间: BEGIN_TIME */ @@ -1147,6 +1316,82 @@ public void setCommitErrorMessage(java.lang.String value){ } } + /** + * 提交阶段错误堆栈: COMMIT_ERROR_STACK + */ + public java.lang.String getCommitErrorStack(){ + onPropGet(PROP_ID_commitErrorStack); + return _commitErrorStack; + } + + /** + * 提交阶段错误堆栈: COMMIT_ERROR_STACK + */ + public void setCommitErrorStack(java.lang.String value){ + if(onPropSet(PROP_ID_commitErrorStack,value)){ + this._commitErrorStack = value; + internalClearRefs(PROP_ID_commitErrorStack); + + } + } + + /** + * 取消阶段错误码: CANCEL_ERROR_CODE + */ + public java.lang.String getCancelErrorCode(){ + onPropGet(PROP_ID_cancelErrorCode); + return _cancelErrorCode; + } + + /** + * 取消阶段错误码: CANCEL_ERROR_CODE + */ + public void setCancelErrorCode(java.lang.String value){ + if(onPropSet(PROP_ID_cancelErrorCode,value)){ + this._cancelErrorCode = value; + internalClearRefs(PROP_ID_cancelErrorCode); + + } + } + + /** + * 取消阶段错误消息: CANCEL_ERROR_MESSAGE + */ + public java.lang.String getCancelErrorMessage(){ + onPropGet(PROP_ID_cancelErrorMessage); + return _cancelErrorMessage; + } + + /** + * 取消阶段错误消息: CANCEL_ERROR_MESSAGE + */ + public void setCancelErrorMessage(java.lang.String value){ + if(onPropSet(PROP_ID_cancelErrorMessage,value)){ + this._cancelErrorMessage = value; + internalClearRefs(PROP_ID_cancelErrorMessage); + + } + } + + /** + * 取消阶段错误堆栈: CANCEL_ERROR_STACK + */ + public java.lang.String getCancelErrorStack(){ + onPropGet(PROP_ID_cancelErrorStack); + return _cancelErrorStack; + } + + /** + * 取消阶段错误堆栈: CANCEL_ERROR_STACK + */ + public void setCancelErrorStack(java.lang.String value){ + if(onPropSet(PROP_ID_cancelErrorStack,value)){ + this._cancelErrorStack = value; + internalClearRefs(PROP_ID_cancelErrorStack); + + } + } + /** * 重试次数: RETRY_TIMES */ diff --git a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccRecord.java b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccRecord.java index 6f8f7f9e6..069efa156 100644 --- a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccRecord.java +++ b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/entity/_gen/_NopTccRecord.java @@ -56,20 +56,32 @@ public class _NopTccRecord extends DynamicOrmEntity{ public static final String PROP_NAME_endTime = "endTime"; public static final int PROP_ID_endTime = 9; + /* 错误码: ERROR_CODE VARCHAR */ + public static final String PROP_NAME_errorCode = "errorCode"; + public static final int PROP_ID_errorCode = 10; + + /* 错误消息: ERROR_MESSAGE VARCHAR */ + public static final String PROP_NAME_errorMessage = "errorMessage"; + public static final int PROP_ID_errorMessage = 11; + + /* 错误堆栈: ERROR_STACK VARCHAR */ + public static final String PROP_NAME_errorStack = "errorStack"; + public static final int PROP_ID_errorStack = 12; + /* 数据版本: VERSION INTEGER */ public static final String PROP_NAME_version = "version"; - public static final int PROP_ID_version = 10; + public static final int PROP_ID_version = 13; /* 创建时间: CREATE_TIME TIMESTAMP */ public static final String PROP_NAME_createTime = "createTime"; - public static final int PROP_ID_createTime = 11; + public static final int PROP_ID_createTime = 14; /* 修改时间: UPDATE_TIME TIMESTAMP */ public static final String PROP_NAME_updateTime = "updateTime"; - public static final int PROP_ID_updateTime = 12; + public static final int PROP_ID_updateTime = 15; - private static int _PROP_ID_BOUND = 13; + private static int _PROP_ID_BOUND = 16; /* relation: 分支事务记录 */ @@ -79,7 +91,7 @@ public class _NopTccRecord extends DynamicOrmEntity{ public static final List PK_PROP_NAMES = Arrays.asList(PROP_NAME_txnId); public static final int[] PK_PROP_IDS = new int[]{PROP_ID_txnId}; - private static final String[] PROP_ID_TO_NAME = new String[13]; + private static final String[] PROP_ID_TO_NAME = new String[16]; private static final Map PROP_NAME_TO_ID = new HashMap<>(); static{ @@ -110,6 +122,15 @@ public class _NopTccRecord extends DynamicOrmEntity{ PROP_ID_TO_NAME[PROP_ID_endTime] = PROP_NAME_endTime; PROP_NAME_TO_ID.put(PROP_NAME_endTime, PROP_ID_endTime); + PROP_ID_TO_NAME[PROP_ID_errorCode] = PROP_NAME_errorCode; + PROP_NAME_TO_ID.put(PROP_NAME_errorCode, PROP_ID_errorCode); + + PROP_ID_TO_NAME[PROP_ID_errorMessage] = PROP_NAME_errorMessage; + PROP_NAME_TO_ID.put(PROP_NAME_errorMessage, PROP_ID_errorMessage); + + PROP_ID_TO_NAME[PROP_ID_errorStack] = PROP_NAME_errorStack; + PROP_NAME_TO_ID.put(PROP_NAME_errorStack, PROP_ID_errorStack); + PROP_ID_TO_NAME[PROP_ID_version] = PROP_NAME_version; PROP_NAME_TO_ID.put(PROP_NAME_version, PROP_ID_version); @@ -149,6 +170,15 @@ public class _NopTccRecord extends DynamicOrmEntity{ /* 结束时间: END_TIME */ private java.sql.Timestamp _endTime; + /* 错误码: ERROR_CODE */ + private java.lang.String _errorCode; + + /* 错误消息: ERROR_MESSAGE */ + private java.lang.String _errorMessage; + + /* 错误堆栈: ERROR_STACK */ + private java.lang.String _errorStack; + /* 数据版本: VERSION */ private java.lang.Integer _version; @@ -255,6 +285,15 @@ public Object orm_propValue(int propId) { case PROP_ID_endTime: return getEndTime(); + case PROP_ID_errorCode: + return getErrorCode(); + + case PROP_ID_errorMessage: + return getErrorMessage(); + + case PROP_ID_errorStack: + return getErrorStack(); + case PROP_ID_version: return getVersion(); @@ -365,6 +404,36 @@ public void orm_propValue(int propId, Object value){ break; } + case PROP_ID_errorCode:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_errorCode)); + } + setErrorCode(typedValue); + break; + } + + case PROP_ID_errorMessage:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_errorMessage)); + } + setErrorMessage(typedValue); + break; + } + + case PROP_ID_errorStack:{ + java.lang.String typedValue = null; + if(value != null){ + typedValue = ConvertHelper.toString(value, + err-> newTypeConversionError(PROP_NAME_errorStack)); + } + setErrorStack(typedValue); + break; + } + case PROP_ID_version:{ java.lang.Integer typedValue = null; if(value != null){ @@ -467,6 +536,27 @@ public void orm_internalSet(int propId, Object value) { break; } + case PROP_ID_errorCode:{ + onInitProp(propId); + this._errorCode = (java.lang.String)value; + + break; + } + + case PROP_ID_errorMessage:{ + onInitProp(propId); + this._errorMessage = (java.lang.String)value; + + break; + } + + case PROP_ID_errorStack:{ + onInitProp(propId); + this._errorStack = (java.lang.String)value; + + break; + } + case PROP_ID_version:{ onInitProp(propId); this._version = (java.lang.Integer)value; @@ -665,6 +755,63 @@ public void setEndTime(java.sql.Timestamp value){ } } + /** + * 错误码: ERROR_CODE + */ + public java.lang.String getErrorCode(){ + onPropGet(PROP_ID_errorCode); + return _errorCode; + } + + /** + * 错误码: ERROR_CODE + */ + public void setErrorCode(java.lang.String value){ + if(onPropSet(PROP_ID_errorCode,value)){ + this._errorCode = value; + internalClearRefs(PROP_ID_errorCode); + + } + } + + /** + * 错误消息: ERROR_MESSAGE + */ + public java.lang.String getErrorMessage(){ + onPropGet(PROP_ID_errorMessage); + return _errorMessage; + } + + /** + * 错误消息: ERROR_MESSAGE + */ + public void setErrorMessage(java.lang.String value){ + if(onPropSet(PROP_ID_errorMessage,value)){ + this._errorMessage = value; + internalClearRefs(PROP_ID_errorMessage); + + } + } + + /** + * 错误堆栈: ERROR_STACK + */ + public java.lang.String getErrorStack(){ + onPropGet(PROP_ID_errorStack); + return _errorStack; + } + + /** + * 错误堆栈: ERROR_STACK + */ + public void setErrorStack(java.lang.String value){ + if(onPropSet(PROP_ID_errorStack,value)){ + this._errorStack = value; + internalClearRefs(PROP_ID_errorStack); + + } + } + /** * 数据版本: VERSION */ diff --git a/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/store/TccRecordRepository.java b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/store/TccRecordRepository.java new file mode 100644 index 000000000..95bc9fa13 --- /dev/null +++ b/nop-tcc/nop-tcc-dao/src/main/java/io/nop/tcc/dao/store/TccRecordRepository.java @@ -0,0 +1,182 @@ +package io.nop.tcc.dao.store; + +import io.nop.api.core.annotations.ioc.InjectValue; +import io.nop.api.core.annotations.txn.TransactionPropagation; +import io.nop.api.core.annotations.txn.Transactional; +import io.nop.api.core.beans.ErrorBean; +import io.nop.api.core.time.CoreMetrics; +import io.nop.api.core.util.FutureHelper; +import io.nop.api.core.util.ICancelToken; +import io.nop.core.exceptions.ErrorMessageManager; +import io.nop.core.lang.json.JsonTool; +import io.nop.dao.api.IDaoProvider; +import io.nop.dao.api.IEntityDao; +import io.nop.tcc.api.ITccBranchRecord; +import io.nop.tcc.api.ITccRecord; +import io.nop.tcc.api.ITccRecordRepository; +import io.nop.tcc.api.TccBranchRequest; +import io.nop.tcc.api.TccStatus; +import io.nop.tcc.dao.entity.NopTccBranchRecord; +import io.nop.tcc.dao.entity.NopTccRecord; + +import javax.inject.Inject; +import java.sql.Timestamp; +import java.util.List; +import java.util.concurrent.CompletionStage; +import java.util.function.Function; + +public class TccRecordRepository implements ITccRecordRepository { + + private IDaoProvider daoProvider; + + private int defaultBranchTimeout; + + @InjectValue("@cfg:nop.tcc.default-branch-timeout-ms:10000") + public void setDefaultBranchTimeout(int defaultBranchTimeoutMs) { + this.defaultBranchTimeout = defaultBranchTimeoutMs; + } + + @Inject + public void setDaoProvider(IDaoProvider daoProvider) { + this.daoProvider = daoProvider; + } + + private IEntityDao recordDao() { + return daoProvider.daoFor(NopTccRecord.class); + } + + private IEntityDao branchDao() { + return daoProvider.daoFor(NopTccBranchRecord.class); + } + + @Override + public ITccRecord newTccRecord(String txnGroup) { + IEntityDao dao = recordDao(); + + NopTccRecord record = new NopTccRecord(); + record.setTxnGroup(txnGroup); + record.setBeginTime(CoreMetrics.currentTimestamp()); + record.setStatus(TccStatus.CREATED.getCode()); + dao.initEntityId(record); + return record; + } + + @Override + public ITccBranchRecord newBranchRecord(ITccRecord record, TccBranchRequest request) { + IEntityDao dao = branchDao(); + + NopTccBranchRecord branchRecord = new NopTccBranchRecord(); + branchRecord.setTxnId(record.getTxnId()); + branchRecord.setBeginTime(CoreMetrics.currentTimestamp()); + branchRecord.setRequestData(JsonTool.stringify(request.getRequest())); + branchRecord.setCancelMethod(request.getCancelMethod()); + branchRecord.setConfirmMethod(request.getConfirmMethod()); + branchRecord.setServiceMethod(request.getServiceMethod()); + branchRecord.setServiceName(request.getServiceName()); + branchRecord.setStatus(TccStatus.CREATED.getCode()); + dao.initEntityId(branchRecord); + + return branchRecord; + } + + @Override + public CompletionStage getTccRecordAsync(String txnGroup, String txnId) { + return FutureHelper.futureCall(() -> { + return recordDao().getEntityById(txnId); + }); + } + + @Override + public CompletionStage> getBranchRecordsAsync(ITccRecord record) { + return FutureHelper.futureCall(() -> { + NopTccBranchRecord example = new NopTccBranchRecord(); + example.setTxnId(record.getTxnId()); + return branchDao().findAllByExample(example); + }); + } + + @Transactional(propagation = TransactionPropagation.REQUIRES_NEW) + @Override + public CompletionStage saveTccRecordAsync(ITccRecord record, TccStatus initStatus) { + return FutureHelper.futureCall(() -> { + NopTccRecord tccRecord = (NopTccRecord) record; + tccRecord.setStatus(initStatus.getCode()); + recordDao().saveEntityDirectly(tccRecord); + return tccRecord; + }); + } + + @Transactional(propagation = TransactionPropagation.REQUIRES_NEW) + @Override + public CompletionStage updateTccStatusAsync(ITccRecord record, TccStatus status, Throwable error) { + return FutureHelper.futureCall(() -> { + NopTccRecord tccRecord = (NopTccRecord) record; + tccRecord.setStatus(status.getCode()); + + if (error != null) { + ErrorBean errorBean = getErrorBean(error); + tccRecord.setErrorStack(errorBean.getErrorStack()); + tccRecord.setErrorCode(errorBean.getErrorCode()); + tccRecord.setErrorMessage(errorBean.getDescription()); + } + recordDao().updateEntityDirectly(tccRecord); + return tccRecord; + }); + } + + @Transactional(propagation = TransactionPropagation.REQUIRES_NEW) + @Override + public CompletionStage saveBranchRecordAsync(ITccBranchRecord branchRecord, TccStatus initStatus) { + return FutureHelper.futureCall(() -> { + NopTccBranchRecord record = (NopTccBranchRecord) branchRecord; + record.setStatus(initStatus.getCode()); + record.setBeginTime(CoreMetrics.currentTimestamp()); + if (record.getExpireTime() == null) + record.setExpireTime(new Timestamp(record.getBeginTime().getTime() + defaultBranchTimeout)); + branchDao().saveEntityDirectly(record); + return record; + }); + } + + @Transactional(propagation = TransactionPropagation.REQUIRES_NEW) + @Override + public CompletionStage updateTccBranchStatusAsync(ITccBranchRecord branchRecord, TccStatus status, Throwable error) { + return FutureHelper.futureCall(() -> { + NopTccBranchRecord record = (NopTccBranchRecord) branchRecord; + record.setStatus(status.getCode()); + + if (error != null) { + ErrorBean errorBean = getErrorBean(error); + if (status == TccStatus.CANCEL_FAILED) { + record.setCancelErrorStack(errorBean.getErrorStack()); + record.setCancelErrorCode(errorBean.getErrorCode()); + record.setCancelErrorMessage(errorBean.getDescription()); + } else if (status == TccStatus.CONFIRM_FAILED) { + record.setCommitErrorStack(errorBean.getErrorStack()); + record.setCommitErrorCode(errorBean.getErrorCode()); + record.setCommitErrorMessage(errorBean.getDescription()); + } else { + record.setErrorStack(errorBean.getErrorStack()); + record.setErrorCode(errorBean.getErrorCode()); + record.setErrorMessage(errorBean.getDescription()); + } + } + branchDao().updateEntityDirectly(record); + return record; + }); + } + + protected ErrorBean getErrorBean(Throwable error) { + return ErrorMessageManager.instance().buildErrorMessage(null, error); + } + + @Override + public void forEachExpiredRecord(Function> consumer, long expireGap, int maxRetryCount, ICancelToken cancelToken) { + + } + + @Override + public void removeCompletedRecords(long retentionTime) { + + } +} diff --git a/nop-tcc/nop-tcc-dao/src/main/resources/_vfs/nop/tcc/beans/app-dao.beans.xml b/nop-tcc/nop-tcc-dao/src/main/resources/_vfs/nop/tcc/beans/app-dao.beans.xml new file mode 100644 index 000000000..1603d5d0a --- /dev/null +++ b/nop-tcc/nop-tcc-dao/src/main/resources/_vfs/nop/tcc/beans/app-dao.beans.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/nop-tcc/nop-tcc-dao/src/main/resources/_vfs/nop/tcc/orm/_app.orm.xml b/nop-tcc/nop-tcc-dao/src/main/resources/_vfs/nop/tcc/orm/_app.orm.xml index 04e418bff..a040cb792 100644 --- a/nop-tcc/nop-tcc-dao/src/main/resources/_vfs/nop/tcc/orm/_app.orm.xml +++ b/nop-tcc/nop-tcc-dao/src/main/resources/_vfs/nop/tcc/orm/_app.orm.xml @@ -52,12 +52,18 @@ stdDataType="timestamp" stdSqlType="TIMESTAMP" i18n-en:displayName="BEGIN Time"/> - + + + + propId="14" stdDataType="timestamp" stdSqlType="TIMESTAMP" i18n-en:displayName="Create Time"/> + propId="15" stdDataType="timestamp" stdSqlType="TIMESTAMP" i18n-en:displayName="Update Time"/> - - + - - - + + + + + + - - - + propId="27" stdDataType="timestamp" stdSqlType="TIMESTAMP" i18n-en:displayName="Create Time"/> + propId="28" stdDataType="timestamp" stdSqlType="TIMESTAMP" i18n-en:displayName="Update Time"/> - + + + + @@ -80,8 +84,24 @@ + + + + + + + + + + + + diff --git a/nop-tcc/nop-tcc-service/src/main/resources/_vfs/nop/tcc/model/NopTccRecord/_NopTccRecord.xmeta b/nop-tcc/nop-tcc-service/src/main/resources/_vfs/nop/tcc/model/NopTccRecord/_NopTccRecord.xmeta index 2f718222c..b03b08c3d 100644 --- a/nop-tcc/nop-tcc-service/src/main/resources/_vfs/nop/tcc/model/NopTccRecord/_NopTccRecord.xmeta +++ b/nop-tcc/nop-tcc-service/src/main/resources/_vfs/nop/tcc/model/NopTccRecord/_NopTccRecord.xmeta @@ -50,6 +50,18 @@ insertable="true" updatable="true"> + + + + + + + + +