diff --git a/pigx-auth/pom.xml b/pigx-auth/pom.xml index 3181b8f46..12d0d69d3 100644 --- a/pigx-auth/pom.xml +++ b/pigx-auth/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx - 3.0.0 + 3.2 pigx-auth diff --git a/pigx-common/pigx-common-bom/pom.xml b/pigx-common/pigx-common-bom/pom.xml index a9616d960..398c4171d 100644 --- a/pigx-common/pigx-common-bom/pom.xml +++ b/pigx-common/pigx-common-bom/pom.xml @@ -6,7 +6,7 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.1.3.RELEASE + 2.1.5.RELEASE @@ -16,7 +16,7 @@ pigx 公共版本控制 - 3.0.0 + 3.2 3.1.0 1.1.16 8.0.16 @@ -66,6 +66,11 @@ pigx-common-security ${pigx.version} + + com.pig4cloud + pigx-common-sequence + ${pigx.version} + com.pig4cloud pigx-common-swagger diff --git a/pigx-common/pigx-common-core/pom.xml b/pigx-common/pigx-common-core/pom.xml index 20bcde7cb..f1f278aed 100644 --- a/pigx-common/pigx-common-core/pom.xml +++ b/pigx-common/pigx-common-core/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-core diff --git a/pigx-common/pigx-common-data/pom.xml b/pigx-common/pigx-common-data/pom.xml index 7681cb3a3..163151b47 100644 --- a/pigx-common/pigx-common-data/pom.xml +++ b/pigx-common/pigx-common-data/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-data diff --git a/pigx-common/pigx-common-datasource/pom.xml b/pigx-common/pigx-common-datasource/pom.xml index 32c4c9c41..fb661eab4 100644 --- a/pigx-common/pigx-common-datasource/pom.xml +++ b/pigx-common/pigx-common-datasource/pom.xml @@ -5,7 +5,7 @@ pigx-common com.pig4cloud - 3.0.0 + 3.2 4.0.0 diff --git a/pigx-common/pigx-common-gateway/pom.xml b/pigx-common/pigx-common-gateway/pom.xml index fb0530b99..e5910a701 100644 --- a/pigx-common/pigx-common-gateway/pom.xml +++ b/pigx-common/pigx-common-gateway/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-gateway diff --git a/pigx-common/pigx-common-job/pom.xml b/pigx-common/pigx-common-job/pom.xml index f76d82892..c6e6085e5 100644 --- a/pigx-common/pigx-common-job/pom.xml +++ b/pigx-common/pigx-common-job/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-job diff --git a/pigx-common/pigx-common-log/pom.xml b/pigx-common/pigx-common-log/pom.xml index 9c47752d2..2c8238f51 100644 --- a/pigx-common/pigx-common-log/pom.xml +++ b/pigx-common/pigx-common-log/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-log diff --git a/pigx-common/pigx-common-minio/pom.xml b/pigx-common/pigx-common-minio/pom.xml index 10db5e14d..1892719e9 100755 --- a/pigx-common/pigx-common-minio/pom.xml +++ b/pigx-common/pigx-common-minio/pom.xml @@ -6,7 +6,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-minio diff --git a/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java b/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java index 35e822eff..7a1a38f64 100755 --- a/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java +++ b/pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java @@ -137,7 +137,7 @@ public class MinioTemplate implements InitializingBean { * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject */ public void putObject(String bucketName, String objectName, InputStream stream) throws Exception { - client.putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream"); + client.putObject(bucketName, objectName, stream, (long) stream.available(), null, null, "application/octet-stream"); } /** @@ -151,7 +151,7 @@ public class MinioTemplate implements InitializingBean { * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject */ public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception { - client.putObject(bucketName, objectName, stream, size, contextType); + client.putObject(bucketName, objectName, stream, size, null, null, contextType); } /** diff --git a/pigx-common/pigx-common-security/pom.xml b/pigx-common/pigx-common-security/pom.xml index 58095bc84..c6fcf6e98 100644 --- a/pigx-common/pigx-common-security/pom.xml +++ b/pigx-common/pigx-common-security/pom.xml @@ -23,7 +23,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-security diff --git a/pigx-common/pigx-common-sequence/pom.xml b/pigx-common/pigx-common-sequence/pom.xml new file mode 100755 index 000000000..460e8ba06 --- /dev/null +++ b/pigx-common/pigx-common-sequence/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + com.pig4cloud + pigx-common + 3.2 + + + pigx-common-sequence + jar + + pigx 分布式发号器 + + + + redis.clients + jedis + + + com.pig4cloud + pigx-common-core + + + \ No newline at end of file diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/SequenceAutoConfiguration.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/SequenceAutoConfiguration.java new file mode 100644 index 000000000..2b10a4dd1 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/SequenceAutoConfiguration.java @@ -0,0 +1,89 @@ +package com.pig4cloud.common.sequence; + +import com.pig4cloud.common.sequence.builder.DbSeqBuilder; +import com.pig4cloud.common.sequence.builder.RedisSeqBuilder; +import com.pig4cloud.common.sequence.builder.SnowflakeSeqBuilder; +import com.pig4cloud.common.sequence.properties.SequenceDbProperties; +import com.pig4cloud.common.sequence.properties.SequenceRedisProperties; +import com.pig4cloud.common.sequence.properties.SequenceSnowflakeProperties; +import com.pig4cloud.common.sequence.range.impl.name.DateBizName; +import com.pig4cloud.common.sequence.range.impl.name.DefaultBizName; +import com.pig4cloud.common.sequence.sequence.Sequence; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +/** + * @author lengleng + * @date 2019-05-26 + */ +@Configuration +@ComponentScan("com.pig4cloud.common.sequence") +@ConditionalOnMissingBean(Sequence.class) +public class SequenceAutoConfiguration { + + /** + * 数据库作为发号器的存储介质 + * + * @param dataSource + * @param properties + * @return + */ + @Bean + @ConditionalOnBean(DataSource.class) + @ConditionalOnProperty("xsequence.db") + public Sequence dbSequence(DataSource dataSource, + SequenceDbProperties properties) { + return DbSeqBuilder + .create() + .bizName(new DefaultBizName(properties.getBizName())) + .dataSource(dataSource) + .step(properties.getStep()) + .retryTimes(properties.getRetryTimes()) + .tableName(properties.getTableName()) + .build(); + } + + /** + * Redis 作为发号器的存储介质 + * + * @param redisProperties + * @param properties + * @return + */ + @Bean + @ConditionalOnProperty("xsequence.redis") + public Sequence redisSequence(RedisProperties redisProperties, + SequenceRedisProperties properties) { + return RedisSeqBuilder + .create() + .bizName(new DateBizName(properties.getBizName())) + .ip(redisProperties.getHost()) + .port(redisProperties.getPort()) + .auth(redisProperties.getPassword()) + .step(properties.getStep()) + .build(); + } + + /** + * snowflak 算法作为发号器实现 + * + * @param properties + * @return + */ + @Bean + @ConditionalOnProperty("xsequence.snowflak") + public Sequence snowflakeSequence(SequenceSnowflakeProperties properties) { + return SnowflakeSeqBuilder + .create() + .datacenterId(properties.getDatacenterId()) + .workerId(properties.getWorkerId()) + .build(); + } +} \ No newline at end of file diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/DbSeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/DbSeqBuilder.java new file mode 100755 index 000000000..9b8f97aa2 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/DbSeqBuilder.java @@ -0,0 +1,97 @@ +package com.pig4cloud.common.sequence.builder; + + +import com.pig4cloud.common.sequence.range.BizName; +import com.pig4cloud.common.sequence.range.impl.db.DbSeqRangeMgr; +import com.pig4cloud.common.sequence.sequence.Sequence; +import com.pig4cloud.common.sequence.sequence.impl.DefaultRangeSequence; + +import javax.sql.DataSource; + +/** + * 基于DB取步长,序列号生成器构建者 + * Created by xuan on 2018/5/30. + */ +public class DbSeqBuilder implements SeqBuilder { + + /** + * 数据库数据源[必选] + */ + private DataSource dataSource; + + /** + * 业务名称[必选] + */ + private BizName bizName; + /** + * 存放序列号步长的表[可选:默认:sequence] + */ + private String tableName = "sequence"; + /** + * 并发是数据使用了乐观策略,这个是失败重试的次数[可选:默认:100] + */ + private int retryTimes = 100; + /** + * 获取range步长[可选:默认:1000] + */ + private int step = 1000; + + /** + * 序列号分配起始值[可选:默认:0] + */ + private long stepStart = 0; + + public static DbSeqBuilder create() { + DbSeqBuilder builder = new DbSeqBuilder(); + return builder; + } + + @Override + public Sequence build() { + //利用DB获取区间管理器 + DbSeqRangeMgr dbSeqRangeMgr = new DbSeqRangeMgr(); + dbSeqRangeMgr.setDataSource(this.dataSource); + dbSeqRangeMgr.setTableName(this.tableName); + dbSeqRangeMgr.setRetryTimes(this.retryTimes); + dbSeqRangeMgr.setStep(this.step); + dbSeqRangeMgr.setStepStart(stepStart); + dbSeqRangeMgr.init(); + //构建序列号生成器 + DefaultRangeSequence sequence = new DefaultRangeSequence(); + sequence.setName(this.bizName); + sequence.setSeqRangeMgr(dbSeqRangeMgr); + return sequence; + } + + public DbSeqBuilder dataSource(DataSource dataSource) { + this.dataSource = dataSource; + return this; + } + + public DbSeqBuilder tableName(String tableName) { + this.tableName = tableName; + return this; + } + + public DbSeqBuilder retryTimes(int retryTimes) { + this.retryTimes = retryTimes; + return this; + } + + public DbSeqBuilder step(int step) { + this.step = step; + return this; + } + + public DbSeqBuilder bizName(BizName bizName) { + this.bizName = bizName; + return this; + } + + public DbSeqBuilder stepStart(long stepStart) { + this.stepStart = stepStart; + return this; + } + + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/RedisSeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/RedisSeqBuilder.java new file mode 100755 index 000000000..fd34d04cb --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/RedisSeqBuilder.java @@ -0,0 +1,94 @@ +package com.pig4cloud.common.sequence.builder; + + +import com.pig4cloud.common.sequence.range.BizName; +import com.pig4cloud.common.sequence.range.impl.redis.RedisSeqRangeMgr; +import com.pig4cloud.common.sequence.sequence.Sequence; +import com.pig4cloud.common.sequence.sequence.impl.DefaultRangeSequence; + +/** + * 基于redis取步长,序列号生成器构建者 + * + * @author xuan on 2018/5/30. + */ +public class RedisSeqBuilder implements SeqBuilder { + + /** + * 连接redis的IP[必选] + */ + private String ip; + /** + * 连接redis的port[必选] + */ + private int port; + /** + * 业务名称[必选] + */ + private BizName bizName; + /** + * 认证权限,看redis是否配置了需要密码auth[可选] + */ + private String auth; + /** + * 获取range步长[可选,默认:1000] + */ + private int step = 1000; + + /** + * 序列号分配起始值[可选:默认:0] + */ + private long stepStart = 0; + + public static RedisSeqBuilder create() { + RedisSeqBuilder builder = new RedisSeqBuilder(); + return builder; + } + + @Override + public Sequence build() { + //利用Redis获取区间管理器 + RedisSeqRangeMgr redisSeqRangeMgr = new RedisSeqRangeMgr(); + redisSeqRangeMgr.setIp(this.ip); + redisSeqRangeMgr.setPort(this.port); + redisSeqRangeMgr.setAuth(this.auth); + redisSeqRangeMgr.setStep(this.step); + redisSeqRangeMgr.setStepStart(stepStart); + redisSeqRangeMgr.init(); + //构建序列号生成器 + DefaultRangeSequence sequence = new DefaultRangeSequence(); + sequence.setName(this.bizName); + sequence.setSeqRangeMgr(redisSeqRangeMgr); + return sequence; + } + + public RedisSeqBuilder ip(String ip) { + this.ip = ip; + return this; + } + + public RedisSeqBuilder port(int port) { + this.port = port; + return this; + } + + public RedisSeqBuilder auth(String auth) { + this.auth = auth; + return this; + } + + public RedisSeqBuilder step(int step) { + this.step = step; + return this; + } + + public RedisSeqBuilder bizName(BizName bizName) { + this.bizName = bizName; + return this; + } + + public RedisSeqBuilder stepStart(long stepStart) { + this.stepStart = stepStart; + return this; + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SeqBuilder.java new file mode 100755 index 000000000..364287e87 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SeqBuilder.java @@ -0,0 +1,19 @@ +package com.pig4cloud.common.sequence.builder; + + +import com.pig4cloud.common.sequence.sequence.Sequence; + +/** + * 序列号生成器构建者 + * @author xuan on 2018/5/30. + */ +public interface SeqBuilder { + + /** + * 构建一个序列号生成器 + * + * @return 序列号生成器 + */ + Sequence build(); + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SnowflakeSeqBuilder.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SnowflakeSeqBuilder.java new file mode 100755 index 000000000..12cd8f49a --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/builder/SnowflakeSeqBuilder.java @@ -0,0 +1,45 @@ +package com.pig4cloud.common.sequence.builder; + + +import com.pig4cloud.common.sequence.sequence.Sequence; +import com.pig4cloud.common.sequence.sequence.impl.SnowflakeSequence; + +/** + * 基于雪花算法,序列号生成器构建者 + * @author xuan on 2018/5/30. + */ +public class SnowflakeSeqBuilder implements SeqBuilder { + + /** + * 数据中心ID,值的范围在[0,31]之间,一般可以设置机房的IDC[必选] + */ + private long datacenterId; + /** + * 工作机器ID,值的范围在[0,31]之间,一般可以设置机器编号[必选] + */ + private long workerId; + + public static SnowflakeSeqBuilder create() { + SnowflakeSeqBuilder builder = new SnowflakeSeqBuilder(); + return builder; + } + + @Override + public Sequence build() { + SnowflakeSequence sequence = new SnowflakeSequence(); + sequence.setDatacenterId(this.datacenterId); + sequence.setWorkerId(this.workerId); + return sequence; + } + + public SnowflakeSeqBuilder datacenterId(long datacenterId) { + this.datacenterId = datacenterId; + return this; + } + + public SnowflakeSeqBuilder workerId(long workerId) { + this.workerId = workerId; + return this; + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/exception/SeqException.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/exception/SeqException.java new file mode 100755 index 000000000..e5b5720fb --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/exception/SeqException.java @@ -0,0 +1,19 @@ +package com.pig4cloud.common.sequence.exception; + +/** + * 序列号生成异常 + * @author xuan on 2018/1/10. + */ +public class SeqException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public SeqException(String message) { + super(message); + } + + public SeqException(Throwable cause) { + super(cause); + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/BaseSequenceProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/BaseSequenceProperties.java new file mode 100644 index 000000000..425736fae --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/BaseSequenceProperties.java @@ -0,0 +1,27 @@ +package com.pig4cloud.common.sequence.properties; + +import lombok.Data; + +/** + * @author lengleng + * @date 2019-05-26 + *

+ * 发号器通用属性 + */ +@Data +class BaseSequenceProperties { + /** + * 获取range步长[可选,默认:1000] + */ + private int step = 1000; + + /** + * 序列号分配起始值[可选:默认:0] + */ + private long stepStart = 0; + + /** + * 业务名称 + */ + private String bizName = "pigx"; +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceDbProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceDbProperties.java new file mode 100644 index 000000000..016314f1f --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceDbProperties.java @@ -0,0 +1,31 @@ +package com.pig4cloud.common.sequence.properties; + +/** + * @author lengleng + * @date 2019-05-26 + */ + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author lengleng + * @date 2019/5/26 + *

+ * 发号器DB配置属性 + */ +@Data +@Component +@ConfigurationProperties(prefix = "xsequence.db") +public class SequenceDbProperties extends BaseSequenceProperties { + /** + * 表名称 + */ + private String tableName; + /** + * 重试次数 + */ + private int retryTimes; + +} \ No newline at end of file diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceRedisProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceRedisProperties.java new file mode 100644 index 000000000..d6e0473f9 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceRedisProperties.java @@ -0,0 +1,23 @@ +package com.pig4cloud.common.sequence.properties; + +/** + * @author lengleng + * @date 2019-05-26 + */ + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author lengleng + * @date 2019/5/26 + *

+ * 发号器Redis配置属性 + */ +@Data +@Component +@ConfigurationProperties(prefix = "xsequence.redis") +public class SequenceRedisProperties extends BaseSequenceProperties { + +} \ No newline at end of file diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceSnowflakeProperties.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceSnowflakeProperties.java new file mode 100644 index 000000000..f7927cb36 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/properties/SequenceSnowflakeProperties.java @@ -0,0 +1,26 @@ +package com.pig4cloud.common.sequence.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author lengleng + * @date 2019-05-26 + *

+ * Snowflake 发号器属性 + */ +@Data +@Component +@ConfigurationProperties(prefix = "xsequence.snowflake") +public class SequenceSnowflakeProperties extends BaseSequenceProperties { + + /** + * 数据中心ID,值的范围在[0,31]之间,一般可以设置机房的IDC[必选] + */ + private long datacenterId; + /** + * 工作机器ID,值的范围在[0,31]之间,一般可以设置机器编号[必选] + */ + private long workerId; +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/BizName.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/BizName.java new file mode 100644 index 000000000..813fa7883 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/BizName.java @@ -0,0 +1,15 @@ +package com.pig4cloud.common.sequence.range; + +/** + * @author lengleng + * @date 2019-05-26 + *

+ * 名称生成器 + */ +public interface BizName { + /** + * 生成名称 + */ + String create(); + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRange.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRange.java new file mode 100755 index 000000000..ce0979df0 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRange.java @@ -0,0 +1,70 @@ +package com.pig4cloud.common.sequence.range; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * 序列号区间对象模型 + * @author xuan on 2018/1/10. + */ +public class SeqRange { + + /** + * 区间的序列号开始值 + */ + private final long min; + /** + * 区间的序列号结束值 + */ + private final long max; + /** + * 区间的序列号当前值 + */ + private final AtomicLong value; + /** + * 区间的序列号是否分配完毕,每次分配完毕就会去重新获取一个新的区间 + */ + private volatile boolean over = false; + + public SeqRange(long min, long max) { + this.min = min; + this.max = max; + this.value = new AtomicLong(min); + } + + /** + * 返回并递增下一个序列号 + * + * @return 下一个序列号,如果返回-1表示序列号分配完毕 + */ + public long getAndIncrement() { + long currentValue = value.getAndIncrement(); + if (currentValue > max) { + over = true; + return -1; + } + + return currentValue; + } + + public long getMin() { + return min; + } + + public long getMax() { + return max; + } + + public boolean isOver() { + return over; + } + + public void setOver(boolean over) { + this.over = over; + } + + @Override + public String toString() { + return "max: " + max + ", min: " + min + ", value: " + value; + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRangeMgr.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRangeMgr.java new file mode 100755 index 000000000..9dfd974ab --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/SeqRangeMgr.java @@ -0,0 +1,25 @@ +package com.pig4cloud.common.sequence.range; + + +import com.pig4cloud.common.sequence.exception.SeqException; + +/** + * 区间管理器 + * @author xuan on 2018/1/10. + */ +public interface SeqRangeMgr { + + /** + * 获取指定区间名的下一个区间 + * + * @param name 区间名 + * @return 返回区间 + * @throws SeqException 异常 + */ + SeqRange nextRange(String name) throws SeqException; + + /** + * 初始化 + */ + void init(); +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/BaseDbHelper.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/BaseDbHelper.java new file mode 100755 index 000000000..0442d7bd4 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/BaseDbHelper.java @@ -0,0 +1,172 @@ +package com.pig4cloud.common.sequence.range.impl.db; + + +import com.pig4cloud.common.sequence.exception.SeqException; + +import javax.sql.DataSource; +import java.sql.*; + +/** + * 操作DB帮助类 + * @author xuan on 2018/4/29. + */ +abstract class BaseDbHelper { + + private static final long DELTA = 100000000L; + + private final static String SQL_CREATE_TABLE = + "CREATE TABLE IF NOT EXISTS #tableName(" + "id bigint(20) NOT NULL AUTO_INCREMENT," + + "value bigint(20) NOT NULL," + "name varchar(32) NOT NULL," + "gmt_create DATETIME NOT NULL," + + "gmt_modified DATETIME NOT NULL," + "PRIMARY KEY (`id`),UNIQUE uk_name (`name`)" + ")"; + private final static String SQL_INSERT_RANGE = + "INSERT IGNORE INTO #tableName(name,value,gmt_create,gmt_modified)" + " VALUE(?,?,?,?)"; + private final static String SQL_UPDATE_RANGE = + "UPDATE #tableName SET value=?,gmt_modified=? WHERE name=? AND " + "value=?"; + private final static String SQL_SELECT_RANGE = "SELECT value FROM #tableName WHERE name=?"; + + /** + * 创建表 + * + * @param dataSource DB来源 + * @param tableName 表名 + */ + static void createTable(DataSource dataSource, String tableName) { + + Connection conn = null; + Statement stmt = null; + + try { + conn = dataSource.getConnection(); + stmt = conn.createStatement(); + stmt.executeUpdate(SQL_CREATE_TABLE.replace("#tableName", tableName)); + } catch (SQLException e) { + throw new SeqException(e); + } finally { + closeQuietly(stmt); + closeQuietly(conn); + } + } + + /** + * 插入数据区间 + * + * @param dataSource DB来源 + * @param tableName 表名 + * @param name 区间名称 + * @param stepStart 初始位置 + */ + private static void insertRange(DataSource dataSource, String tableName, String name, long stepStart) { + + Connection conn = null; + PreparedStatement stmt = null; + + try { + conn = dataSource.getConnection(); + stmt = conn.prepareStatement(SQL_INSERT_RANGE.replace("#tableName", tableName)); + stmt.setString(1, name); + stmt.setLong(2, stepStart); + stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis())); + stmt.setTimestamp(4, new Timestamp(System.currentTimeMillis())); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new SeqException(e); + } finally { + closeQuietly(stmt); + closeQuietly(conn); + } + } + + /** + * 更新区间,乐观策略 + * + * @param dataSource DB来源 + * @param tableName 表名 + * @param newValue 更新新数据 + * @param oldValue 更新旧数据 + * @param name 区间名称 + * @return 成功/失败 + */ + static boolean updateRange(DataSource dataSource, String tableName, Long newValue, Long oldValue, String name) { + + Connection conn = null; + PreparedStatement stmt = null; + + try { + conn = dataSource.getConnection(); + stmt = conn.prepareStatement(SQL_UPDATE_RANGE.replace("#tableName", tableName)); + stmt.setLong(1, newValue); + stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis())); + stmt.setString(3, name); + stmt.setLong(4, oldValue); + int affectedRows = stmt.executeUpdate(); + return affectedRows > 0; + } catch (SQLException e) { + throw new SeqException(e); + } finally { + closeQuietly(stmt); + closeQuietly(conn); + } + } + + /** + * 查询区间,如果区间不存在,会新增一个区间,并返回null,由上层重新执行 + * + * @param dataSource DB来源 + * @param tableName 来源 + * @param name 区间名称 + * @param stepStart 初始位置 + * @return 区间值 + */ + static Long selectRange(DataSource dataSource, String tableName, String name, long stepStart) { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + long oldValue; + + try { + conn = dataSource.getConnection(); + stmt = conn.prepareStatement(SQL_SELECT_RANGE.replace("#tableName", tableName)); + stmt.setString(1, name); + + rs = stmt.executeQuery(); + if (!rs.next()) { + //没有此类型数据,需要初始化 + insertRange(dataSource, tableName, name, stepStart); + return null; + } + oldValue = rs.getLong(1); + + if (oldValue < 0) { + String msg = + "Sequence value cannot be less than zero, value = " + oldValue + ", please check table sequence" + + tableName; + throw new SeqException(msg); + } + + if (oldValue > Long.MAX_VALUE - DELTA) { + String msg = + "Sequence value overflow, value = " + oldValue + ", please check table sequence" + tableName; + throw new SeqException(msg); + } + + return oldValue; + } catch (SQLException e) { + throw new SeqException(e); + } finally { + closeQuietly(rs); + closeQuietly(stmt); + closeQuietly(conn); + } + } + + private static void closeQuietly(AutoCloseable closeable) { + if (null != closeable) { + try { + closeable.close(); + } catch (Throwable e) { + //Ignore + } + } + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/DbSeqRangeMgr.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/DbSeqRangeMgr.java new file mode 100755 index 000000000..b34008d85 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/db/DbSeqRangeMgr.java @@ -0,0 +1,139 @@ +package com.pig4cloud.common.sequence.range.impl.db; + + +import com.pig4cloud.common.sequence.exception.SeqException; +import com.pig4cloud.common.sequence.range.SeqRange; +import com.pig4cloud.common.sequence.range.SeqRangeMgr; + +import javax.sql.DataSource; + +/** + * DB区间管理器 + * @author xuan on 2018/4/29. + */ +public class DbSeqRangeMgr implements SeqRangeMgr { + + /** + * 区间步长 + */ + private int step = 1000; + /** + * 区间起始位置,真实从stepStart+1开始 + */ + private long stepStart = 0; + /** + * 获取区间失败重试次数 + */ + private int retryTimes = 100; + /** + * DB来源 + */ + private DataSource dataSource; + /** + * 表名,默认range + */ + private String tableName = "range"; + + @Override + public SeqRange nextRange(String name) throws SeqException { + if (isEmpty(name)) { + throw new SecurityException("[DbSeqRangeMgr-nextRange] name is empty."); + } + + Long oldValue; + Long newValue; + + for (int i = 0; i < getRetryTimes(); i++) { + oldValue = BaseDbHelper.selectRange(getDataSource(), getRealTableName(), name, getStepStart()); + + if (null == oldValue) { + //区间不存在,重试 + continue; + } + + newValue = oldValue + getStep(); + + if (BaseDbHelper.updateRange(getDataSource(), getRealTableName(), newValue, oldValue, name)) { + return new SeqRange(oldValue + 1, newValue); + } + //else 失败重试 + } + + throw new SeqException("Retried too many times, retryTimes = " + getRetryTimes()); + } + + @Override + public void init() { + checkParam(); + BaseDbHelper.createTable(getDataSource(), getRealTableName()); + } + + private boolean isEmpty(String str) { + return null == str || str.trim().length() == 0; + } + + private String getRealTableName() { + return getTableName(); + } + + private void checkParam() { + if (step <= 0) { + throw new SecurityException("[DbSeqRangeMgr-checkParam] step must greater than 0."); + } + if (stepStart < 0) { + throw new SecurityException("[DbSeqRangeMgr-setStepStart] stepStart < 0."); + } + if (retryTimes <= 0) { + throw new SecurityException("[DbSeqRangeMgr-setRetryTimes] retryTimes must greater than 0."); + } + if (null == dataSource) { + throw new SecurityException("[DbSeqRangeMgr-setDataSource] dataSource is null."); + } + if (isEmpty(tableName)) { + throw new SecurityException("[DbSeqRangeMgr-setTableName] tableName is empty."); + } + } + + ////////getter and setter + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public long getStepStart() { + return stepStart; + } + + public void setStepStart(long stepStart) { + this.stepStart = stepStart; + } + + public int getRetryTimes() { + return retryTimes; + } + + public void setRetryTimes(int retryTimes) { + this.retryTimes = retryTimes; + } + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DateBizName.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DateBizName.java new file mode 100644 index 000000000..f44817098 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DateBizName.java @@ -0,0 +1,26 @@ +package com.pig4cloud.common.sequence.range.impl.name; + +import cn.hutool.core.date.DateUtil; +import com.pig4cloud.common.sequence.range.BizName; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +/** + * @author lengleng + * @date 2019-05-26 + *

+ * 根据时间重置bizname + */ +@NoArgsConstructor +@AllArgsConstructor +public class DateBizName implements BizName { + private String bizName; + + /** + * 生成空间名称 + */ + @Override + public String create() { + return bizName + DateUtil.today(); + } +} \ No newline at end of file diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DefaultBizName.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DefaultBizName.java new file mode 100644 index 000000000..c77b11555 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/name/DefaultBizName.java @@ -0,0 +1,24 @@ +package com.pig4cloud.common.sequence.range.impl.name; + +import com.pig4cloud.common.sequence.range.BizName; +import lombok.AllArgsConstructor; + +/** + * @author lengleng + * @date 2019-05-26 + * 根据传入返回bizname + */ +@AllArgsConstructor +public class DefaultBizName implements BizName { + + private String bizName; + + /** + * 生成空间名称 + */ + @Override + public String create() { + return bizName; + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/redis/RedisSeqRangeMgr.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/redis/RedisSeqRangeMgr.java new file mode 100755 index 000000000..e69cbe262 --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/range/impl/redis/RedisSeqRangeMgr.java @@ -0,0 +1,137 @@ +package com.pig4cloud.common.sequence.range.impl.redis; + +import cn.hutool.core.util.StrUtil; +import com.pig4cloud.common.sequence.exception.SeqException; +import com.pig4cloud.common.sequence.range.SeqRange; +import com.pig4cloud.common.sequence.range.SeqRangeMgr; +import redis.clients.jedis.Jedis; + +/** + * Redis区间管理器 + * + * @author xuan on 2018/5/8. + */ +public class RedisSeqRangeMgr implements SeqRangeMgr { + + /** + * 前缀防止key重复 + */ + private final static String KEY_PREFIX = "x_sequence_"; + + /** + * redis客户端 + */ + private Jedis jedis; + + /** + * IP + */ + private String ip; + /** + * PORT + */ + private Integer port; + + /** + * 验证权限 + */ + private String auth; + + /** + * 区间步长 + */ + private int step = 1000; + + /** + * 区间起始位置,真实从stepStart+1开始 + */ + private long stepStart = 0; + + /** + * 标记业务key是否存在,如果false,在取nextRange时,会取check一把 + * 这个boolean只为提高性能,不用每次都取redis check + */ + private volatile boolean keyAlreadyExist; + + @Override + public SeqRange nextRange(String name) throws SeqException { + if (!keyAlreadyExist) { + Boolean isExists = jedis.exists(getRealKey(name)); + if (!isExists) { + //第一次不存在,进行初始化,setnx不存在就set,存在就忽略 + jedis.setnx(getRealKey(name), String.valueOf(stepStart)); + } + keyAlreadyExist = true; + } + + Long max = jedis.incrBy(getRealKey(name), step); + Long min = max - step + 1; + return new SeqRange(min, max); + } + + @Override + public void init() { + checkParam(); + jedis = new Jedis(ip, port); + if (StrUtil.isNotBlank(auth)) { + jedis.auth(auth); + } + } + + private void checkParam() { + if (isEmpty(ip)) { + throw new SecurityException("[RedisSeqRangeMgr-checkParam] ip is empty."); + } + if (null == port) { + throw new SecurityException("[RedisSeqRangeMgr-checkParam] port is null."); + } + } + + private String getRealKey(String name) { + return KEY_PREFIX + name; + } + + private boolean isEmpty(String str) { + return null == str || str.trim().length() == 0; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } + + public long getStepStart() { + return stepStart; + } + + public void setStepStart(long stepStart) { + this.stepStart = stepStart; + } +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/RangeSequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/RangeSequence.java new file mode 100755 index 000000000..7eaa28d6f --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/RangeSequence.java @@ -0,0 +1,26 @@ +package com.pig4cloud.common.sequence.sequence; + + +import com.pig4cloud.common.sequence.range.BizName; +import com.pig4cloud.common.sequence.range.SeqRangeMgr; + +/** + * 序列号区间生成器接口 + * @author xuan on 2018/5/6. + */ +public interface RangeSequence extends Sequence { + + /** + * 设置区间管理器 + * + * @param seqRangeMgr 区间管理器 + */ + void setSeqRangeMgr(SeqRangeMgr seqRangeMgr); + + /** + * 设置获取序列号名称 + * + * @param name 名称 + */ + void setName(BizName name); +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/Sequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/Sequence.java new file mode 100755 index 000000000..6dc7a8b1e --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/Sequence.java @@ -0,0 +1,28 @@ +package com.pig4cloud.common.sequence.sequence; + + +import com.pig4cloud.common.sequence.exception.SeqException; + +/** + * 序列号生成器接口 + * + * @author xuan on 2018/1/10. + */ +public interface Sequence { + + /** + * 生成下一个序列号 + * + * @return 序列号 + * @throws SeqException 序列号异常 + */ + long nextValue() throws SeqException; + + /** + * 下一个生成序号(带格式) + * + * @return + * @throws SeqException + */ + String nextNo() throws SeqException; +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/DefaultRangeSequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/DefaultRangeSequence.java new file mode 100755 index 000000000..7ef109b5e --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/DefaultRangeSequence.java @@ -0,0 +1,111 @@ +package com.pig4cloud.common.sequence.sequence.impl; + + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import com.pig4cloud.common.sequence.exception.SeqException; +import com.pig4cloud.common.sequence.range.BizName; +import com.pig4cloud.common.sequence.range.SeqRange; +import com.pig4cloud.common.sequence.range.SeqRangeMgr; +import com.pig4cloud.common.sequence.sequence.RangeSequence; + +import java.util.Date; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * 序列号区间生成器接口默认实现 + * + * @author xuan on 2018/1/10. + *

+ * 根据biz name 自增 + */ +public class DefaultRangeSequence implements RangeSequence { + + /** + * 获取区间是加一把独占锁防止资源冲突 + */ + private final Lock lock = new ReentrantLock(); + + /** + * 序列号区间管理器 + */ + private SeqRangeMgr seqRangeMgr; + + /** + * 当前序列号区间 + */ + private volatile SeqRange currentRange; + + /** + * 需要获取区间的业务名称 + */ + private BizName bizName; + + @Override + public long nextValue() throws SeqException { + String name = bizName.create(); + + //当前区间不存在,重新获取一个区间 + if (null == currentRange) { + lock.lock(); + try { + if (null == currentRange) { + currentRange = seqRangeMgr.nextRange(name); + } + } finally { + lock.unlock(); + } + } + + //当value值为-1时,表明区间的序列号已经分配完,需要重新获取区间 + long value = currentRange.getAndIncrement(); + if (value == -1) { + lock.lock(); + try { + for (; ; ) { + if (currentRange.isOver()) { + currentRange = seqRangeMgr.nextRange(name); + } + + value = currentRange.getAndIncrement(); + if (value == -1) { + continue; + } + + break; + } + } finally { + lock.unlock(); + } + } + + if (value < 0) { + throw new SeqException("Sequence value overflow, value = " + value); + } + + return value; + } + + /** + * 下一个生成序号(带格式) + * + * @return + * @throws SeqException + */ + @Override + public String nextNo() throws SeqException { + return String.format("%s%05d", DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT), nextValue()); + } + + @Override + public void setSeqRangeMgr(SeqRangeMgr seqRangeMgr) { + this.seqRangeMgr = seqRangeMgr; + } + + @Override + public void setName(BizName name) { + this.bizName = name; + } + +} diff --git a/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/SnowflakeSequence.java b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/SnowflakeSequence.java new file mode 100755 index 000000000..9aedfbecc --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/java/com/pig4cloud/common/sequence/sequence/impl/SnowflakeSequence.java @@ -0,0 +1,177 @@ +package com.pig4cloud.common.sequence.sequence.impl; + + +import com.pig4cloud.common.sequence.exception.SeqException; +import com.pig4cloud.common.sequence.sequence.Sequence; + +/** + * 使用雪花算法 + * 一个long类型的数据,64位。以下是每位的具体含义。 + *
+ * snowflake的结构如下(每部分用-分开): + *
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 + *
+ * (1)第一位为未使用 + * (2)接下来的41位为毫秒级时间(41位的长度可以使用69年) + * (3)然后是5位datacenterId + * (4)5位workerId + * (5)最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号) + *
+ * 一共加起来刚好64位,为一个Long型。(转换成字符串长度为18) + * @author xuan on 2018/5/9. + */ +public class SnowflakeSequence implements Sequence { + + /** + * 开始时间截 (2018-01-01) + */ + private final long twepoch = 1514736000000L; + + /** + * 机器id所占的位数 + */ + private final long workerIdBits = 5L; + + /** + * 数据标识id所占的位数 + */ + private final long datacenterIdBits = 5L; + + /** + * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) + */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** + * 支持的最大数据标识id,结果是31 + */ + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + /** + * 序列在id中占的位数 + */ + private final long sequenceBits = 12L; + + /** + * 机器ID向左移12位 + */ + private final long workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位(12+5) + */ + private final long datacenterIdShift = sequenceBits + workerIdBits; + + /** + * 时间截向左移22位(5+5+12) + */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + /** + * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) + */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** + * 工作机器ID(0~31) + */ + private long workerId; + + /** + * 数据中心ID(0~31) + */ + private long datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + private long sequence = 0L; + + /** + * 上次生成ID的时间截 + */ + private long lastTimestamp = -1L; + + @Override + public synchronized long nextValue() throws SeqException { + long timestamp = timeGen(); + + //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + throw new SeqException("[SnowflakeSequence-nextValue] 当前时间小于上次生成序列号的时间,时间被回退了,请确认服务器时间的设置."); + } + + //如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + //毫秒内序列溢出 + if (sequence == 0) { + //阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + //时间戳改变,毫秒内序列重置 + sequence = 0L; + } + + //上次生成ID的时间截 + lastTimestamp = timestamp; + + //移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + private long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + private long timeGen() { + return System.currentTimeMillis(); + } + + public void setWorkerId(long workerId) { + if (workerId > maxWorkerId) { + throw new SeqException("[SnowflakeSequence-setWorkerId] workerId 不能大于31."); + } + + this.workerId = workerId; + } + + public void setDatacenterId(long datacenterId) { + if (datacenterId > maxDatacenterId) { + throw new SeqException("[SnowflakeSequence-setDatacenterId] datacenterId 不能大于31."); + } + + this.datacenterId = datacenterId; + } + + /** + * 下一个生成序号(带格式) + * + * @return + * @throws SeqException + */ + @Override + public String nextNo() throws SeqException { + return String.valueOf(nextValue()); + } +} diff --git a/pigx-common/pigx-common-sequence/src/main/resources/META-INF/spring.factories b/pigx-common/pigx-common-sequence/src/main/resources/META-INF/spring.factories new file mode 100755 index 000000000..80446dc9b --- /dev/null +++ b/pigx-common/pigx-common-sequence/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.pig4cloud.common.sequence.SequenceAutoConfiguration \ No newline at end of file diff --git a/pigx-common/pigx-common-swagger/pom.xml b/pigx-common/pigx-common-swagger/pom.xml index b59063b81..fa75bff61 100644 --- a/pigx-common/pigx-common-swagger/pom.xml +++ b/pigx-common/pigx-common-swagger/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-swagger diff --git a/pigx-common/pigx-common-transaction/pom.xml b/pigx-common/pigx-common-transaction/pom.xml index b165ce19d..43ecb65ac 100644 --- a/pigx-common/pigx-common-transaction/pom.xml +++ b/pigx-common/pigx-common-transaction/pom.xml @@ -5,7 +5,7 @@ com.pig4cloud pigx-common - 3.0.0 + 3.2 pigx-common-transaction diff --git a/pigx-common/pom.xml b/pigx-common/pom.xml index 99e723dfc..1227d7038 100644 --- a/pigx-common/pom.xml +++ b/pigx-common/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx - 3.0.0 + 3.2 pigx-common @@ -42,6 +42,7 @@ pigx-common-minio pigx-common-security pigx-common-swagger + pigx-common-sequence pigx-common-transaction pigx-common-datasource diff --git a/pigx-gateway/pom.xml b/pigx-gateway/pom.xml index ba9c39a12..af095c4c5 100644 --- a/pigx-gateway/pom.xml +++ b/pigx-gateway/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx - 3.0.0 + 3.2 pigx-gateway diff --git a/pigx-register/pom.xml b/pigx-register/pom.xml index 323247d1a..465fbc118 100755 --- a/pigx-register/pom.xml +++ b/pigx-register/pom.xml @@ -18,7 +18,7 @@ com.pig4cloud pigx - 3.0.0 + 3.2 pigx-register diff --git a/pigx-upms/pigx-upms-api/pom.xml b/pigx-upms/pigx-upms-api/pom.xml index df9f82ff2..e942e30a3 100644 --- a/pigx-upms/pigx-upms-api/pom.xml +++ b/pigx-upms/pigx-upms-api/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-upms - 3.0.0 + 3.2 pigx-upms-api diff --git a/pigx-upms/pigx-upms-biz/pom.xml b/pigx-upms/pigx-upms-biz/pom.xml index bee4afd42..973e768ef 100644 --- a/pigx-upms/pigx-upms-biz/pom.xml +++ b/pigx-upms/pigx-upms-biz/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-upms - 3.0.0 + 3.2 pigx-upms-biz diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java index 8e69d5642..bbe36559f 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/FileController.java @@ -35,6 +35,8 @@ import java.io.InputStream; import java.util.HashMap; import java.util.Map; +; + /** * @author lengleng * @date 2018-12-30 diff --git a/pigx-upms/pom.xml b/pigx-upms/pom.xml index d2b2c35d0..216c94d24 100644 --- a/pigx-upms/pom.xml +++ b/pigx-upms/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx - 3.0.0 + 3.2 pigx-upms diff --git a/pigx-visual/pigx-activiti/pom.xml b/pigx-visual/pigx-activiti/pom.xml index 139eace01..04dd6a0b5 100644 --- a/pigx-visual/pigx-activiti/pom.xml +++ b/pigx-visual/pigx-activiti/pom.xml @@ -23,7 +23,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 pigx-activiti diff --git a/pigx-visual/pigx-codegen/pom.xml b/pigx-visual/pigx-codegen/pom.xml index c2e9352f7..1376a0199 100755 --- a/pigx-visual/pigx-codegen/pom.xml +++ b/pigx-visual/pigx-codegen/pom.xml @@ -6,7 +6,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 pigx-codegen diff --git a/pigx-visual/pigx-daemon-elastic-job/pom.xml b/pigx-visual/pigx-daemon-elastic-job/pom.xml index 800a91a8e..fcbd9fd20 100644 --- a/pigx-visual/pigx-daemon-elastic-job/pom.xml +++ b/pigx-visual/pigx-daemon-elastic-job/pom.xml @@ -23,7 +23,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 pigx-daemon-elastic-job diff --git a/pigx-visual/pigx-daemon-quartz/pom.xml b/pigx-visual/pigx-daemon-quartz/pom.xml index 1f1897e60..33ac0e143 100644 --- a/pigx-visual/pigx-daemon-quartz/pom.xml +++ b/pigx-visual/pigx-daemon-quartz/pom.xml @@ -5,7 +5,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 4.0.0 diff --git a/pigx-visual/pigx-monitor/pom.xml b/pigx-visual/pigx-monitor/pom.xml index 03c1e4970..ba5ad66c2 100644 --- a/pigx-visual/pigx-monitor/pom.xml +++ b/pigx-visual/pigx-monitor/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 pigx-monitor @@ -36,7 +36,7 @@ com.pig4cloud pigx-common-core - 3.0.0 + 3.2 org.springframework.boot diff --git a/pigx-visual/pigx-mp-manager/pom.xml b/pigx-visual/pigx-mp-manager/pom.xml index f40bc2cc0..a736a505a 100755 --- a/pigx-visual/pigx-mp-manager/pom.xml +++ b/pigx-visual/pigx-mp-manager/pom.xml @@ -6,7 +6,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 pigx-mp-manager diff --git a/pigx-visual/pigx-pay/Dockerfile b/pigx-visual/pigx-pay/Dockerfile new file mode 100644 index 000000000..9385d4860 --- /dev/null +++ b/pigx-visual/pigx-pay/Dockerfile @@ -0,0 +1,15 @@ +FROM anapsix/alpine-java:8_server-jre_unlimited + +MAINTAINER wangiegie@gmail.com + +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime + +RUN mkdir -p /pigx-pay + +WORKDIR /pigx-pay + +EXPOSE 5003 + +ADD ./pigx-visual/pigx-pay/target/pigx-pay.jar ./ + +CMD sleep 30;java -Djava.security.egd=file:/dev/./urandom -jar pigx-pay.jar diff --git a/pigx-visual/pigx-pay/pom.xml b/pigx-visual/pigx-pay/pom.xml new file mode 100755 index 000000000..01cda2a9d --- /dev/null +++ b/pigx-visual/pigx-pay/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + + com.pig4cloud + pigx-visual + 3.2 + + + pigx-pay + jar + + 支付系统 + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-config + + + + com.baomidou + mybatis-plus-boot-starter + + + mysql + mysql-connector-java + + + + com.alibaba + druid-spring-boot-starter + + + + com.pig4cloud + pigx-common-data + + + com.pig4cloud + pigx-common-sequence + + + + com.pig4cloud + pigx-common-swagger + + + + com.pig4cloud + pigx-common-security + + + com.pig4cloud + pigx-common-log + + + + com.github.javen205 + IJPay + 1.2.0 + + + com.alipay.sdk + alipay-sdk-java + 3.0.52.ALL + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-undertow + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + com.spotify + docker-maven-plugin + + + + diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java new file mode 100755 index 000000000..8c264f846 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay; + +import com.pig4cloud.pigx.common.security.annotation.EnablePigxFeignClients; +import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer; +import com.pig4cloud.pigx.common.swagger.annotation.EnablePigxSwagger2; +import org.springframework.boot.SpringApplication; +import org.springframework.cloud.client.SpringCloudApplication; + +/** + * @author lengleng + * @date 2019年05月27日17:25:38 + *

+ * 支付模块 + */ +@EnablePigxSwagger2 +@SpringCloudApplication +@EnablePigxFeignClients +@EnablePigxResourceServer +public class PigxPayApplication { + + public static void main(String[] args) { + SpringApplication.run(PigxPayApplication.class, args); + } +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java new file mode 100644 index 000000000..94d004024 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java @@ -0,0 +1,41 @@ +package com.pig4cloud.pigx.pay.config; + +import com.jpay.alipay.AliPayApiConfig; +import com.jpay.alipay.AliPayApiConfigKit; +import com.pig4cloud.pigx.pay.service.PayChannelService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.event.EventListener; +import org.springframework.core.annotation.Order; +import org.springframework.scheduling.annotation.Async; + +/** + * @author lengleng + * @date 2019-05-31 + *

+ * 支付参数初始化 + */ +@Slf4j +@Configuration +@AllArgsConstructor +public class PayConfigParmaInitRunner { + private final PayChannelService channelService; + + @Async + @Order + @EventListener({WebServerInitializedEvent.class}) + public void initPayConfig() { + + AliPayApiConfig rsa2 = AliPayApiConfig.New() + .setAppId("2016102000727659") + .setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkejVpiLJlece9KLb8gG/+WODkpe5SRfr65n3aUAvRPoouDUp/URBAtt24mzHFdGkaU/Il7ZxG7KUjLaFNTfq8t/bHEF7HBt7MZidpEjVaDxeG/hkA+xc+X2ePAJXVhy7v1tH+XRrxuggTj+d4q7vVGD7r1mtgX4d5hK9TTKnyhO6IUcthPOUSn07wx+5wlbv4/51ggj4Ku4AWCGaCWiebDFy4VZ/FmOMP5u3O7TocCGSy5UtaFZaVMM1nH603DG6NJ8fG+zKum9IvrdQMMmBWPT8rpy0U9ztchcd+0gTNrTfE/NOCgl/RF6z7Qic7NiTKjLxkGRq73XPzfJx0hyfpAgMBAAECggEAa2/sndAN/90JjNUgmlVnUnRKCvEceJ9/rw6KXOV2oqrAZg6GgB26iRsqP6EYZMuCsBDvlrjcITQJNq5is/Vg+I8OYr+duVISjN+ZlLexI+/BxYsLWCmr6DE3myCdvwn7rezb5NR6ejWzetvALoG3Qx4AU9sO7rfX7ZevUrE8Pc5pa/rTCHOIec9P7Hfm4xrXd0DPmbAwFvUQ4spcC9xjcBhLJ3tfmkoEU11jC6Y/J7N0/TZZxqNC+HcYftSNEmbO3vxYfz/9mbabx7Uzp8xs4qHPJACmaP5tcWOCf1qJVOwP53Cd3H9J9Be9cAvlxKfT48s1ghoxLn7QB27p0UwntQKBgQDzTpCCFDoUH328B3iGTkwZq24DOUh5ZwhMG6VIFPLHwJYK6HVM473SX0nJWkbiBYFG4WiQWUZnOhz/qjTH1vvE/nzJwQ79zZahren2b8XulXKM6S/mafiBAHKl/FArcr14iAWkh+scZKWFKrNf6Hp8rQ6zu0fWdwzUOlaQFaSnTwKBgQCtDtpIagRPyNj0J39uMRJqsaY0TdJ53TD4bflf5UiFhNFH2Dikgw/uX8Pom2qtIvf3xnO2bzmJW2+OSkF7U0fL+UXkAaBHW+7YVcs8pWARSd5LWBXGWysV2wUALwynZSdwtgpgrzMQnuzklQ3hNR9LBSEGN7yJwkU83ZRWPzbvRwKBgQDU3E8g/oExSbu+3Opc1fNOIeTFfUAitjlUHHulbG5aw+qA8I5vDm/rtOHg/tI0u4w2bs4EO5aUiQsFwesbSsJJvjt+ZyCue0blfDnMGE2aRbVKAlidxOhcNAAZp3ycBm4tHROStjbDSGpm7syvg7xlhyHtrFNVFiJrKf7BX64FkQKBgCA8lAzJMuRp1YAlm2c7XOLjFMLJfFuXCHg+hCWI4Gl+xD1N2b9LarxMuoGp8cUurmJJZWSmc2FS1wT6cBg4+zbTyGEgrGqehW9nC+TQKYUO7Ym7btL0SKJZmiTenszP2vjz8Bryh+CguiAaY+t/qcSfv/cYitZeiec8n1UxkVohAoGAa8YwnzkEGBgz0TpdrGFxVBCqMIriMH4PQs2tWZ1nEBk6A7GrODRcRL0FQnRpHyf3mY5N/iEiNQ5GhQ5p1lifTvolTkVkdHpTGFhVfnYegaEAOznigi7dWJPoYlloN36AROxirGJKRIm+Od2bsybM/dNPJfoTDBDPFWGBH/klEBs=") + .setCharset("UTF-8") + .setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuPkP2VJMR6vWCX8RwSFqNIa3klCdvRFJbuS1PN1anzQeeL9eOwtU7kGdI85yxb0dcdPzOYlG+jf9go8W9hBlgjxSRoXxLx03Yfl7cLmzJO9l9vIM1+HmNF0Ctm+el4Yi9dGs/P6q7lcHPUqs/RXGfeLrg33GMVwJbLmRcDZYeIcqPAA1OVF/4SHYr+f+O7glDOd60z+veOOexyoHmvUzYWlEz5+R4kOCNM/Z0w7KGgEYvHbZopexuTuFgUWy/9tYlNrnX+cZUWXVTskLUgD1UGWM1dS5+qfriqY9MPEwJjetcPJkoCK7A4IReE4q1DffUY9KS50/1ML+7na3R/p/UQIDAQAB") + .setServiceUrl("https://openapi.alipaydev.com/gateway.do") + .setSignType("RSA2") + .build(); + AliPayApiConfigKit.putApiConfig(rsa2); + } +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java new file mode 100644 index 000000000..fed0964f2 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java @@ -0,0 +1,61 @@ +package com.pig4cloud.pigx.pay.config; + +import cn.hutool.core.date.DateUtil; +import com.pig4cloud.common.sequence.builder.DbSeqBuilder; +import com.pig4cloud.common.sequence.properties.SequenceDbProperties; +import com.pig4cloud.common.sequence.sequence.Sequence; +import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +/** + * @author lengleng + * @date 2019-05-26 + *

+ * 设置发号器生成规则 + */ +@Configuration +public class SequenceConfig { + + /** + * 订单流水号发号器 + * + * @param dataSource + * @param properties + * @return + */ + @Bean + public Sequence paySequence(DataSource dataSource, + SequenceDbProperties properties) { + return DbSeqBuilder + .create() + .bizName(() -> String.format("pay_%s_%s", TenantContextHolder.getTenantId(), DateUtil.today())) + .dataSource(dataSource) + .step(properties.getStep()) + .retryTimes(properties.getRetryTimes()) + .tableName(properties.getTableName()) + .build(); + } + + /** + * 通道编号发号器 + * + * @param dataSource + * @param properties + * @return + */ + @Bean + public Sequence channelSequence(DataSource dataSource, + SequenceDbProperties properties) { + return DbSeqBuilder + .create() + .bizName(() -> String.format("channel_%s", TenantContextHolder.getTenantId())) + .dataSource(dataSource) + .step(properties.getStep()) + .retryTimes(properties.getRetryTimes()) + .tableName(properties.getTableName()) + .build(); + } +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java new file mode 100755 index 000000000..7695ec207 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.controller; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.pay.entity.PayChannel; +import com.pig4cloud.pigx.pay.service.PayChannelService; +import io.swagger.annotations.Api; +import lombok.AllArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + + +/** + * 渠道 + * + * @author lengleng + * @date 2019-05-28 23:57:58 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/paychannel") +@Api(value = "paychannel", tags = "paychannel管理") +public class PayChannelController { + private final PayChannelService payChannelService; + + /** + * 分页查询 + * + * @param page 分页对象 + * @param payChannel 渠道 + * @return + */ + @GetMapping("/page") + public R getPayChannelPage(Page page, PayChannel payChannel) { + return R.ok(payChannelService.page(page, Wrappers.query(payChannel))); + } + + + /** + * 通过id查询渠道 + * + * @param id id + * @return R + */ + @GetMapping("/{id}") + public R getById(@PathVariable("id") Integer id) { + return R.ok(payChannelService.getById(id)); + } + + /** + * 新增渠道 + * + * @param payChannel 渠道 + * @return R + */ + @SysLog("新增渠道") + @PostMapping + @PreAuthorize("@pms.hasPermission('pay_paychannel_add')") + public R save(@RequestBody PayChannel payChannel) { + return R.ok(payChannelService.saveChannel(payChannel)); + } + + /** + * 修改渠道 + * + * @param payChannel 渠道 + * @return R + */ + @SysLog("修改渠道") + @PutMapping + @PreAuthorize("@pms.hasPermission('pay_paychannel_edit')") + public R updateById(@RequestBody PayChannel payChannel) { + return R.ok(payChannelService.updateById(payChannel)); + } + + /** + * 通过id删除渠道 + * + * @param id id + * @return R + */ + @SysLog("删除渠道") + @DeleteMapping("/{id}") + @PreAuthorize("@pms.hasPermission('pay_paychannel_del')") + public R removeById(@PathVariable Integer id) { + return R.ok(payChannelService.removeById(id)); + } + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckBatchController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckBatchController.java new file mode 100755 index 000000000..6dad14c97 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckBatchController.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.controller; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.pay.entity.PayCheckBatch; +import com.pig4cloud.pigx.pay.service.PayCheckBatchService; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + + +/** + * 批量对账 + * + * @author lengleng + * @date 2019-05-28 23:57:38 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/paycheckbatch" ) +@Api(value = "paycheckbatch", tags = "paycheckbatch管理") +public class PayCheckBatchController { + + private final PayCheckBatchService payCheckBatchService; + + /** + * 分页查询 + * @param page 分页对象 + * @param payCheckBatch 批量对账 + * @return + */ + @GetMapping("/page" ) + public R getPayCheckBatchPage(Page page, PayCheckBatch payCheckBatch) { + return R.ok(payCheckBatchService.page(page, Wrappers.query(payCheckBatch))); + } + + + /** + * 通过id查询批量对账 + * @param id id + * @return R + */ + @GetMapping("/{id}" ) + public R getById(@PathVariable("id" ) Long id) { + return R.ok(payCheckBatchService.getById(id)); + } + + /** + * 新增批量对账 + * @param payCheckBatch 批量对账 + * @return R + */ + @SysLog("新增批量对账" ) + @PostMapping + @PreAuthorize("@pms.hasPermission('pay_paycheckbatch_add')" ) + public R save(@RequestBody PayCheckBatch payCheckBatch) { + return R.ok(payCheckBatchService.save(payCheckBatch)); + } + + /** + * 修改批量对账 + * @param payCheckBatch 批量对账 + * @return R + */ + @SysLog("修改批量对账" ) + @PutMapping + @PreAuthorize("@pms.hasPermission('pay_paycheckbatch_edit')" ) + public R updateById(@RequestBody PayCheckBatch payCheckBatch) { + return R.ok(payCheckBatchService.updateById(payCheckBatch)); + } + + /** + * 通过id删除批量对账 + * @param id id + * @return R + */ + @SysLog("删除批量对账" ) + @DeleteMapping("/{id}" ) + @PreAuthorize("@pms.hasPermission('pay_paycheckbatch_del')" ) + public R removeById(@PathVariable Long id) { + return R.ok(payCheckBatchService.removeById(id)); + } + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckMistakeController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckMistakeController.java new file mode 100755 index 000000000..080842960 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayCheckMistakeController.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.controller; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.pay.entity.PayCheckMistake; +import com.pig4cloud.pigx.pay.service.PayCheckMistakeService; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + + +/** + * 差错 + * + * @author lengleng + * @date 2019-05-28 23:57:50 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/paycheckmistake" ) +@Api(value = "paycheckmistake", tags = "paycheckmistake管理") +public class PayCheckMistakeController { + + private final PayCheckMistakeService payCheckMistakeService; + + /** + * 分页查询 + * @param page 分页对象 + * @param payCheckMistake 差错 + * @return + */ + @GetMapping("/page" ) + public R getPayCheckMistakePage(Page page, PayCheckMistake payCheckMistake) { + return R.ok(payCheckMistakeService.page(page, Wrappers.query(payCheckMistake))); + } + + + /** + * 通过id查询差错 + * @param id id + * @return R + */ + @GetMapping("/{id}" ) + public R getById(@PathVariable("id" ) Long id) { + return R.ok(payCheckMistakeService.getById(id)); + } + + /** + * 新增差错 + * @param payCheckMistake 差错 + * @return R + */ + @SysLog("新增差错" ) + @PostMapping + @PreAuthorize("@pms.hasPermission('pay_paycheckmistake_add')" ) + public R save(@RequestBody PayCheckMistake payCheckMistake) { + return R.ok(payCheckMistakeService.save(payCheckMistake)); + } + + /** + * 修改差错 + * @param payCheckMistake 差错 + * @return R + */ + @SysLog("修改差错" ) + @PutMapping + @PreAuthorize("@pms.hasPermission('pay_paycheckmistake_edit')" ) + public R updateById(@RequestBody PayCheckMistake payCheckMistake) { + return R.ok(payCheckMistakeService.updateById(payCheckMistake)); + } + + /** + * 通过id删除差错 + * @param id id + * @return R + */ + @SysLog("删除差错" ) + @DeleteMapping("/{id}" ) + @PreAuthorize("@pms.hasPermission('pay_paycheckmistake_del')" ) + public R removeById(@PathVariable Long id) { + return R.ok(payCheckMistakeService.removeById(id)); + } + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java new file mode 100755 index 000000000..c392bb301 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.controller; + +import cn.hutool.core.util.StrUtil; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.common.security.annotation.Inner; +import com.pig4cloud.pigx.pay.service.PayGoodsOrderService; +import io.swagger.annotations.Api; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + + +/** + * 商品 + * + * @author lengleng + * @date 2019-05-28 23:58:27 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/goods") +@Api(value = "goods", tags = "商品订单管理") +public class PayGoodsOrderController { + + private final PayGoodsOrderService payGoodsOrderService; + + + /** + * 商品订单 + * + * @param amount 金额 + * @return R + */ + @Inner(false) + @GetMapping("/buy") + @SysLog("新增商品订单") + public R save(Long amount, HttpServletRequest request) { + String ua = request.getHeader(HttpHeaders.USER_AGENT); + if (StrUtil.isBlank(ua)) { + return R.failed("终端不合法"); + } + return payGoodsOrderService.buy(amount); + } +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java new file mode 100755 index 000000000..d2ae2f1fa --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.controller; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.pay.entity.PayNotifyRecord; +import com.pig4cloud.pigx.pay.service.PayNotifyRecordService; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + + +/** + * 异步通知记录 + * + * @author lengleng + * @date 2019-05-28 23:57:23 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/paynotifyrecord" ) +@Api(value = "paynotifyrecord", tags = "paynotifyrecord管理") +public class PayNotifyRecordController { + + private final PayNotifyRecordService payNotifyRecordService; + + /** + * 分页查询 + * @param page 分页对象 + * @param payNotifyRecord 异步通知记录 + * @return + */ + @GetMapping("/page" ) + public R getPayNotifyRecordPage(Page page, PayNotifyRecord payNotifyRecord) { + return R.ok(payNotifyRecordService.page(page, Wrappers.query(payNotifyRecord))); + } + + + /** + * 通过id查询异步通知记录 + * @param id id + * @return R + */ + @GetMapping("/{id}" ) + public R getById(@PathVariable("id" ) Long id) { + return R.ok(payNotifyRecordService.getById(id)); + } + + /** + * 新增异步通知记录 + * @param payNotifyRecord 异步通知记录 + * @return R + */ + @SysLog("新增异步通知记录" ) + @PostMapping + @PreAuthorize("@pms.hasPermission('pay_paynotifyrecord_add')" ) + public R save(@RequestBody PayNotifyRecord payNotifyRecord) { + return R.ok(payNotifyRecordService.save(payNotifyRecord)); + } + + /** + * 修改异步通知记录 + * @param payNotifyRecord 异步通知记录 + * @return R + */ + @SysLog("修改异步通知记录" ) + @PutMapping + @PreAuthorize("@pms.hasPermission('pay_paynotifyrecord_edit')" ) + public R updateById(@RequestBody PayNotifyRecord payNotifyRecord) { + return R.ok(payNotifyRecordService.updateById(payNotifyRecord)); + } + + /** + * 通过id删除异步通知记录 + * @param id id + * @return R + */ + @SysLog("删除异步通知记录" ) + @DeleteMapping("/{id}" ) + @PreAuthorize("@pms.hasPermission('pay_paynotifyrecord_del')" ) + public R removeById(@PathVariable Long id) { + return R.ok(payNotifyRecordService.removeById(id)); + } + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java new file mode 100755 index 000000000..43e963634 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.controller; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.pay.entity.PayRefundOrder; +import com.pig4cloud.pigx.pay.service.PayRefundOrderService; +import io.swagger.annotations.Api; +import lombok.AllArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + + +/** + * 退款 + * + * @author lengleng + * @date 2019-05-28 23:58:11 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/payrefundorder") +@Api(value = "payrefundorder", tags = "payrefundorder管理") +public class PayRefundOrderController { + + private final PayRefundOrderService payRefundOrderService; + + /** + * 分页查询 + * + * @param page 分页对象 + * @param payRefundOrder 退款 + * @return + */ + @GetMapping("/page") + public R getPayRefundOrderPage(Page page, PayRefundOrder payRefundOrder) { + return R.ok(payRefundOrderService.page(page, Wrappers.query(payRefundOrder))); + } + + + /** + * 通过id查询退款 + * + * @param refundOrderId id + * @return R + */ + @GetMapping("/{refund]orderId}") + public R getById(@PathVariable("refund]orderId") String refundOrderId) { + return R.ok(payRefundOrderService.getById(refundOrderId)); + } + + /** + * 新增退款 + * + * @param payRefundOrder 退款 + * @return R + */ + @SysLog("新增退款") + @PostMapping + @PreAuthorize("@pms.hasPermission('pay_payrefundorder_add')") + public R save(@RequestBody PayRefundOrder payRefundOrder) { + return R.ok(payRefundOrderService.save(payRefundOrder)); + } + + /** + * 修改退款 + * + * @param payRefundOrder 退款 + * @return R + */ + @SysLog("修改退款") + @PutMapping + @PreAuthorize("@pms.hasPermission('pay_payrefundorder_edit')") + public R updateById(@RequestBody PayRefundOrder payRefundOrder) { + return R.ok(payRefundOrderService.updateById(payRefundOrder)); + } + + /** + * 通过id删除退款 + * + * @param refundOrderId refundOrderId + * @return R + */ + @SysLog("删除退款") + @DeleteMapping("/{refundOrderId}") + @PreAuthorize("@pms.hasPermission('pay_payrefundorder_del')") + public R removeById(@PathVariable String refundOrderId) { + return R.ok(payRefundOrderService.removeById(refundOrderId)); + } + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java new file mode 100755 index 000000000..a51cdf3fd --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.controller; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; +import com.pig4cloud.pigx.pay.service.PayTradeOrderService; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + + +/** + * 支付 + * + * @author lengleng + * @date 2019-05-28 23:58:18 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/paytradeorder" ) +@Api(value = "paytradeorder", tags = "paytradeorder管理") +public class PayTradeOrderController { + + private final PayTradeOrderService payTradeOrderService; + + /** + * 分页查询 + * @param page 分页对象 + * @param payTradeOrder 支付 + * @return + */ + @GetMapping("/page" ) + public R getPayTradeOrderPage(Page page, PayTradeOrder payTradeOrder) { + return R.ok(payTradeOrderService.page(page, Wrappers.query(payTradeOrder))); + } + + + /** + * 通过id查询支付 + * @param orderId id + * @return R + */ + @GetMapping("/{orderId}" ) + public R getById(@PathVariable("orderId" ) String orderId) { + return R.ok(payTradeOrderService.getById(orderId)); + } + + /** + * 新增支付 + * @param payTradeOrder 支付 + * @return R + */ + @SysLog("新增支付" ) + @PostMapping + @PreAuthorize("@pms.hasPermission('pay_paytradeorder_add')" ) + public R save(@RequestBody PayTradeOrder payTradeOrder) { + return R.ok(payTradeOrderService.save(payTradeOrder)); + } + + /** + * 修改支付 + * @param payTradeOrder 支付 + * @return R + */ + @SysLog("修改支付" ) + @PutMapping + @PreAuthorize("@pms.hasPermission('pay_paytradeorder_edit')" ) + public R updateById(@RequestBody PayTradeOrder payTradeOrder) { + return R.ok(payTradeOrderService.updateById(payTradeOrder)); + } + + /** + * 通过id删除支付 + * @param orderId id + * @return R + */ + @SysLog("删除支付" ) + @DeleteMapping("/{orderId}" ) + @PreAuthorize("@pms.hasPermission('pay_paytradeorder_del')" ) + public R removeById(@PathVariable String orderId) { + return R.ok(payTradeOrderService.removeById(orderId)); + } + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java new file mode 100755 index 000000000..323021f3f --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 渠道 + * + * @author lengleng + * @date 2019-05-28 23:57:58 + */ +@Data +@TableName("pay_channel") +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "渠道") +public class PayChannel extends Model { + private static final long serialVersionUID = 1L; + + /** + * 渠道主键ID + */ + @TableId + private Integer id; + /** + * 渠道ID + */ + private String channelId; + /** + * 渠道名称,如:alipay,wechat + */ + private String channelName; + /** + * 渠道商户ID + */ + private String channelMchId; + /** + * 内部商户ID + */ + private String mchId; + /** + * 渠道状态 + */ + private String state; + /** + * 配置参数,json字符串 + */ + private String param; + /** + * 备注 + */ + private String remark; + /** + * 删除标记 + */ + @TableLogic + private String delFlag; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 租户ID + */ + private Integer tenantId; + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckBatch.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckBatch.java new file mode 100755 index 000000000..5763bccf9 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckBatch.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 批量对账 + * + * @author lengleng + * @date 2019-05-28 23:57:38 + */ +@Data +@TableName("pay_check_batch") +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "批量对账") +public class PayCheckBatch extends Model { + private static final long serialVersionUID = 1L; + + /** + * + */ + @TableId + private Long id; + /** + * + */ + private String status; + /** + * + */ + private String remark; + /** + * + */ + private String batchNo; + /** + * + */ + private LocalDateTime billDate; + /** + * + */ + private String billType; + /** + * + */ + private String handleStatus; + /** + * + */ + private String bankType; + /** + * + */ + private Integer mistakeCount; + /** + * + */ + private Integer unhandleMistakeCount; + /** + * + */ + private Integer tradeCount; + /** + * + */ + private Integer bankTradeCount; + /** + * + */ + private BigDecimal tradeAmount; + /** + * + */ + private BigDecimal bankTradeAmount; + /** + * + */ + private BigDecimal refundAmount; + /** + * + */ + private BigDecimal bankRefundAmount; + /** + * + */ + private BigDecimal bankFee; + /** + * + */ + private String orgCheckFilePath; + /** + * + */ + private String releaseCheckFilePath; + /** + * + */ + private String releaseStatus; + /** + * + */ + private String checkFailMsg; + /** + * + */ + private String bankErrMsg; + /** + * + */ + @TableLogic + private String delFlag; + /** + * + */ + private LocalDateTime createTime; + /** + * + */ + private LocalDateTime updateTime; + /** + * 租户ID + */ + private Integer tenantId; + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckMistake.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckMistake.java new file mode 100755 index 000000000..d3c62c7b8 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayCheckMistake.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 差错 + * + * @author lengleng + * @date 2019-05-28 23:57:50 + */ +@Data +@TableName("pay_check_mistake") +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "差错") +public class PayCheckMistake extends Model { + private static final long serialVersionUID = 1L; + + /** + * + */ + @TableId + private Long id; + /** + * 商品名称 + */ + private String productName; + /** + * 订单号 + */ + private String orderNo; + /** + * 支付流水号 + */ + private String trxNo; + /** + * 银行订单号 + */ + private String bankOrderNo; + /** + * 银行流水号 + */ + private String bankTrxNo; + /** + * 订单金额 + */ + private BigDecimal orderAmount; + /** + * 平台收入 + */ + private BigDecimal platIncome; + /** + * 费率 + */ + private BigDecimal feeRate; + /** + * 平台成本 + */ + private BigDecimal platCost; + /** + * 平台利润 + */ + private BigDecimal platProfit; + /** + * 状态(参考枚举:paymentrecordstatusenum) + */ + private String status; + /** + * 支付通道编号 + */ + private String payWayCode; + /** + * 支付通道名称 + */ + private String payWayName; + /** + * 支付成功时间 + */ + private LocalDateTime paySuccessTime; + /** + * 完成时间 + */ + private LocalDateTime completeTime; + /** + * 是否退款(100:是,101:否,默认值为:101) + */ + private String isRefund; + /** + * 退款次数(默认值为:0) + */ + private Integer refundTimes; + /** + * 成功退款总金额 + */ + private BigDecimal successRefundAmount; + /** + * 备注 + */ + private String remark; + /** + * + */ + private String batchNo; + /** + * + */ + private LocalDateTime billDate; + /** + * + */ + private LocalDateTime createTime; + /** + * + */ + private LocalDateTime updateTime; + /** + * + */ + @TableLogic + private String delFlag; + /** + * 租户ID + */ + private Integer tenantId; + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java new file mode 100755 index 000000000..947a5ba82 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 商品 + * + * @author lengleng + * @date 2019-05-28 23:58:27 + */ +@Data +@TableName("pay_goods_order") +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "商品") +public class PayGoodsOrder extends Model { + private static final long serialVersionUID = 1L; + + /** + * 商品订单ID + */ + @TableId + private String goodsOrderId; + /** + * 商品ID + */ + private String goodsId; + /** + * 商品名称 + */ + private String goodsName; + /** + * 金额,单位分 + */ + private Long amount; + /** + * 用户ID + */ + private String userId; + /** + * 订单状态,订单生成(0),支付成功(1),处理完成(2),处理失败(-1) + */ + private Integer status; + /** + * 支付订单号 + */ + private String payOrderId; + /** + * 0-正常,1-删除 + */ + @TableLogic + private String delFlag; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 租户ID + */ + private Integer tenantId; + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java new file mode 100755 index 000000000..f932965a8 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 异步通知记录 + * + * @author lengleng + * @date 2019-05-28 23:57:23 + */ +@Data +@TableName("pay_notify_record") +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "异步通知记录") +public class PayNotifyRecord extends Model { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId + private Long id; + /** + * 响应ID + */ + private String notifyId; + /** + * 请求报文 + */ + private String request; + /** + * 响应报文 + */ + private String response; + /** + * 系统订单号 + */ + private String orderNo; + /** + * http状态 + */ + private String httpStatus; + /** + * 删除标记 + */ + @TableLogic + private String delFlag; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 租户ID + */ + private Integer tenantId; + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java new file mode 100755 index 000000000..cae0c0ec3 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 退款 + * + * @author lengleng + * @date 2019-05-28 23:58:11 + */ +@Data +@TableName("pay_refund_order") +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "退款") +public class PayRefundOrder extends Model { + private static final long serialVersionUID = 1L; + + /** + * 退款订单号 + */ + @TableId + private String refundOrderId; + /** + * 支付订单号 + */ + private String payOrderId; + /** + * 渠道支付单号 + */ + private String channelPayOrderNo; + /** + * 商户ID + */ + private String mchId; + /** + * 商户退款单号 + */ + private String mchRefundNo; + /** + * 渠道ID + */ + private String channelId; + /** + * 支付金额,单位分 + */ + private Long payAmount; + /** + * 退款金额,单位分 + */ + private Long refundAmount; + /** + * 三位货币代码,人民币:cny + */ + private String currency; + /** + * 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败,4-业务处理完成 + */ + private Integer status; + /** + * 退款结果:0-不确认结果,1-等待手动处理,2-确认成功,3-确认失败 + */ + private Integer result; + /** + * 客户端IP + */ + private String clientIp; + /** + * 设备 + */ + private String device; + /** + * 备注 + */ + private String remark; + /** + * 渠道用户标识,如微信openId,支付宝账号 + */ + private String channelUser; + /** + * 用户姓名 + */ + private String username; + /** + * 渠道商户ID + */ + private String channelMchId; + /** + * 渠道订单号 + */ + private String channelOrderNo; + /** + * 渠道错误码 + */ + private String channelErrCode; + /** + * 渠道错误描述 + */ + private String channelErrMsg; + /** + * 特定渠道发起时额外参数 + */ + private String extra; + /** + * 通知地址 + */ + private String notifyurl; + /** + * 扩展参数1 + */ + private String param1; + /** + * 扩展参数2 + */ + private String param2; + /** + * 订单失效时间 + */ + private LocalDateTime expireTime; + /** + * 订单退款成功时间 + */ + private LocalDateTime refundSuccTime; + /** + * 删除标记 + */ + @TableLogic + private String delFlag; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 租户ID + */ + private Integer tenantId; + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java new file mode 100755 index 000000000..079c39696 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 支付 + * + * @author lengleng + * @date 2019-05-28 23:58:18 + */ +@Data +@TableName("pay_trade_order") +@EqualsAndHashCode(callSuper = true) +@ApiModel(description = "支付") +public class PayTradeOrder extends Model { + private static final long serialVersionUID = 1L; + + /** + * 支付订单号 + */ + @TableId(type = IdType.INPUT) + private String orderId; + /** + * 渠道ID + */ + private String channelId; + /** + * 支付金额,单位分 + */ + private Long amount; + /** + * 三位货币代码,人民币:cny + */ + private String currency; + /** + * 支付状态,0-订单生成,1-支付中(目前未使用),2-支付成功,3-业务处理完成 + */ + private Integer status; + /** + * 客户端IP + */ + private String clientIp; + /** + * 设备 + */ + private String device; + /** + * 商品标题 + */ + private String subject; + /** + * 商品描述信息 + */ + private String body; + /** + * 特定渠道发起时额外参数 + */ + private String extra; + /** + * 渠道商户ID + */ + private String channelMchId; + /** + * 渠道订单号 + */ + private String channelOrderNo; + /** + * 渠道支付错误码 + */ + private String errCode; + /** + * 渠道支付错误描述 + */ + private String errMsg; + /** + * 扩展参数1 + */ + private String param1; + /** + * 扩展参数2 + */ + private String param2; + /** + * 通知地址 + */ + private String notifyUrl; + /** + * 通知次数 + */ + private Integer notifyCount; + /** + * 最后一次通知时间 + */ + private Long lastNotifyTime; + /** + * 订单失效时间 + */ + private Long expireTime; + /** + * 订单支付成功时间 + */ + private Long paySuccTime; + /** + * 创建时间 + */ + private LocalDateTime createTime; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 删除标记 + */ + @TableLogic + private String delFlaag; + /** + * 租户ID + */ + private Integer tenantId; + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AbstractPayOrderHandler.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AbstractPayOrderHandler.java new file mode 100644 index 000000000..b5cbc30e8 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AbstractPayOrderHandler.java @@ -0,0 +1,44 @@ +package com.pig4cloud.pigx.pay.handler; + +import com.pig4cloud.common.sequence.sequence.Sequence; +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; +import com.pig4cloud.pigx.pay.service.PayGoodsOrderService; +import com.pig4cloud.pigx.pay.utils.OrderStatusEnum; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author lengleng + * @date 2019-05-31 + */ +public abstract class AbstractPayOrderHandler implements PayOrderHandler { + @Autowired + private PayGoodsOrderService goodsOrderService; + @Autowired + private Sequence paySequence; + + + /** + * 创建商品订单 + * + * @param goodsOrder 商品订单 + * @return + */ + @Override + public void createGoodsOrder(PayGoodsOrder goodsOrder) { + goodsOrder.setPayOrderId(paySequence.nextNo()); + goodsOrder.setStatus(OrderStatusEnum.INIT.getStatus()); + goodsOrderService.save(goodsOrder); + } + + /** + * 调用入口 + */ + @Override + public void handle(PayGoodsOrder payGoodsOrder) { + createGoodsOrder(payGoodsOrder); + PayTradeOrder tradeOrder = createTradeOrder(payGoodsOrder); + pay(payGoodsOrder, tradeOrder); + updateOrder(payGoodsOrder, tradeOrder); + } +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AlipayWapPayOrderHandler.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AlipayWapPayOrderHandler.java new file mode 100644 index 000000000..de93897fd --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/AlipayWapPayOrderHandler.java @@ -0,0 +1,102 @@ +package com.pig4cloud.pigx.pay.handler; + +import cn.hutool.extra.servlet.ServletUtil; +import com.alipay.api.AlipayApiException; +import com.alipay.api.domain.AlipayTradeWapPayModel; +import com.jpay.alipay.AliPayApi; +import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder; +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; +import com.pig4cloud.pigx.pay.service.PayGoodsOrderService; +import com.pig4cloud.pigx.pay.service.PayTradeOrderService; +import com.pig4cloud.pigx.pay.utils.OrderStatusEnum; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author lengleng + * @date 2019-05-31 + *

+ * 支付宝手机支付 + */ +@Slf4j +@Service("ALIPAY_WAP") +@AllArgsConstructor +public class AlipayWapPayOrderHandler extends AbstractPayOrderHandler { + private final PayTradeOrderService tradeOrderService; + private final PayGoodsOrderService goodsOrderService; + private final HttpServletRequest request; + private final HttpServletResponse response; + + /** + * 创建交易订单 + * + * @param goodsOrder + * @return + */ + @Override + public PayTradeOrder createTradeOrder(PayGoodsOrder goodsOrder) { + PayTradeOrder tradeOrder = new PayTradeOrder(); + tradeOrder.setOrderId(goodsOrder.getPayOrderId()); + tradeOrder.setAmount(goodsOrder.getAmount()); + tradeOrder.setChannelId("ALIPAY_WAP"); + tradeOrder.setChannelMchId("1517584931"); + tradeOrder.setClientIp(ServletUtil.getClientIP(request)); + tradeOrder.setCurrency("cny"); + tradeOrder.setExpireTime(30L); + tradeOrder.setStatus(OrderStatusEnum.INIT.getStatus()); + tradeOrder.setBody("测试商品"); + tradeOrderService.save(tradeOrder); + return tradeOrder; + } + + /** + * 调起渠道支付 + * + * @param goodsOrder 商品订单 + * @param tradeOrder 交易订单 + */ + @Override + public PayTradeOrder pay(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) { + AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); + model.setBody(tradeOrder.getBody()); + model.setSubject(tradeOrder.getBody()); + model.setOutTradeNo(tradeOrder.getOrderId()); + model.setTimeoutExpress(tradeOrder.getExpireTime() + "m"); + model.setTotalAmount(String.valueOf(tradeOrder.getAmount())); + model.setPassbackParams(String.valueOf(TenantContextHolder.getTenantId())); + model.setProductCode(goodsOrder.getGoodsId()); + try { + AliPayApi.wapPay(response, model, "http://www.baidu.com", "/alipay/notify_url"); + } catch (AlipayApiException e) { + log.warn("支付宝支付失败 {} {}", e.getErrCode(), e.getErrMsg()); + tradeOrder.setErrMsg(e.getErrMsg()); + tradeOrder.setErrCode(e.getErrCode()); + tradeOrder.setStatus(OrderStatusEnum.FAIL.getStatus()); + goodsOrder.setStatus(OrderStatusEnum.FAIL.getStatus()); + } catch (IOException e) { + log.error("支付宝手机支付失败", e); + tradeOrder.setErrMsg(e.getMessage()); + tradeOrder.setStatus(OrderStatusEnum.FAIL.getStatus()); + goodsOrder.setStatus(OrderStatusEnum.FAIL.getStatus()); + } + return tradeOrder; + } + + /** + * 更新订单信息 + * + * @param goodsOrder 商品订单 + * @param tradeOrder 交易订单 + */ + @Override + public void updateOrder(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) { + tradeOrderService.updateById(tradeOrder); + goodsOrderService.updateById(goodsOrder); + } +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java new file mode 100644 index 000000000..6784b0df7 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java @@ -0,0 +1,49 @@ +package com.pig4cloud.pigx.pay.handler; + +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; + +/** + * @author lengleng + * @date 2019-05-31 + *

+ * 支付业务 + */ +public interface PayOrderHandler { + + /** + * 创建商品订单 + * + * @param goodsOrder 金额 + * @return + */ + void createGoodsOrder(PayGoodsOrder goodsOrder); + + /** + * 创建交易订单 + * + * @param goodsOrder 商品订单 + * @return + */ + PayTradeOrder createTradeOrder(PayGoodsOrder goodsOrder); + + /** + * 调起渠道支付 + * + * @param goodsOrder 商品订单 + * @param tradeOrder 交易订单 + */ + PayTradeOrder pay(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder); + + /** + * 更新订单信息 + */ + void updateOrder(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder); + + /** + * 调用入口 + * + * @param goodsOrde 商品订单 + */ + void handle(PayGoodsOrder goodsOrde); +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java new file mode 100755 index 000000000..50a1889f2 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.pig4cloud.pigx.pay.entity.PayChannel; + +/** + * 渠道 + * + * @author lengleng + * @date 2019-05-28 23:57:58 + */ +public interface PayChannelMapper extends BaseMapper { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckBatchMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckBatchMapper.java new file mode 100755 index 000000000..9437cfcda --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckBatchMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.pig4cloud.pigx.pay.entity.PayCheckBatch; + +/** + * 批量对账 + * + * @author lengleng + * @date 2019-05-28 23:57:38 + */ +public interface PayCheckBatchMapper extends BaseMapper { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckMistakeMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckMistakeMapper.java new file mode 100755 index 000000000..63f4268aa --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayCheckMistakeMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.pig4cloud.pigx.pay.entity.PayCheckMistake; + +/** + * 差错 + * + * @author lengleng + * @date 2019-05-28 23:57:50 + */ +public interface PayCheckMistakeMapper extends BaseMapper { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java new file mode 100755 index 000000000..fa337a084 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; + +/** + * 商品 + * + * @author lengleng + * @date 2019-05-28 23:58:27 + */ +public interface PayGoodsOrderMapper extends BaseMapper { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java new file mode 100755 index 000000000..e064f34fa --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.pig4cloud.pigx.pay.entity.PayNotifyRecord; + +/** + * 异步通知记录 + * + * @author lengleng + * @date 2019-05-28 23:57:23 + */ +public interface PayNotifyRecordMapper extends BaseMapper { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java new file mode 100755 index 000000000..1030a66cc --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.pig4cloud.pigx.pay.entity.PayRefundOrder; + +/** + * 退款 + * + * @author lengleng + * @date 2019-05-28 23:58:11 + */ +public interface PayRefundOrderMapper extends BaseMapper { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java new file mode 100755 index 000000000..5e676eca6 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; + +/** + * 支付 + * + * @author lengleng + * @date 2019-05-28 23:58:18 + */ +public interface PayTradeOrderMapper extends BaseMapper { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java new file mode 100755 index 000000000..32a94c904 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.pay.entity.PayChannel; + +/** + * 渠道 + * + * @author lengleng + * @date 2019-05-28 23:57:58 + */ +public interface PayChannelService extends IService { + + /** + * 新增支付渠道 + * + * @param payChannel 支付渠道 + * @return + */ + Boolean saveChannel(PayChannel payChannel); +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckBatchService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckBatchService.java new file mode 100755 index 000000000..88c84f9c8 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckBatchService.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.pay.entity.PayCheckBatch; + +/** + * 批量对账 + * + * @author lengleng + * @date 2019-05-28 23:57:38 + */ +public interface PayCheckBatchService extends IService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckMistakeService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckMistakeService.java new file mode 100755 index 000000000..77f9784ff --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayCheckMistakeService.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.pay.entity.PayCheckMistake; + +/** + * 差错 + * + * @author lengleng + * @date 2019-05-28 23:57:50 + */ +public interface PayCheckMistakeService extends IService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java new file mode 100755 index 000000000..97883e30b --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; + +/** + * 商品 + * + * @author lengleng + * @date 2019-05-28 23:58:27 + */ +public interface PayGoodsOrderService extends IService { + + /** + * 购买商品 + * + * @param amount + * @return + */ + R buy(Long amount); +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java new file mode 100755 index 000000000..6daab7bc9 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.pay.entity.PayNotifyRecord; + +/** + * 异步通知记录 + * + * @author lengleng + * @date 2019-05-28 23:57:23 + */ +public interface PayNotifyRecordService extends IService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java new file mode 100755 index 000000000..e19fe66ee --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.pay.entity.PayRefundOrder; + +/** + * 退款 + * + * @author lengleng + * @date 2019-05-28 23:58:11 + */ +public interface PayRefundOrderService extends IService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java new file mode 100755 index 000000000..eab0776a2 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; + +/** + * 支付 + * + * @author lengleng + * @date 2019-05-28 23:58:18 + */ +public interface PayTradeOrderService extends IService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java new file mode 100755 index 000000000..c29ccbd34 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ +package com.pig4cloud.pigx.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.common.sequence.sequence.Sequence; +import com.pig4cloud.pigx.pay.entity.PayChannel; +import com.pig4cloud.pigx.pay.mapper.PayChannelMapper; +import com.pig4cloud.pigx.pay.service.PayChannelService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 渠道 + * + * @author lengleng + * @date 2019-05-28 23:57:58 + */ +@Service +@AllArgsConstructor +public class PayChannelServiceImpl extends ServiceImpl implements PayChannelService { + private final Sequence channelSequence; + + /** + * 新增支付渠道 + * + * @param payChannel 支付渠道 + * @return + */ + @Override + public Boolean saveChannel(PayChannel payChannel) { + payChannel.setMchId(channelSequence.nextNo()); + return save(payChannel); + } +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckBatchServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckBatchServiceImpl.java new file mode 100755 index 000000000..e11a8c67d --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckBatchServiceImpl.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ +package com.pig4cloud.pigx.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.pigx.pay.entity.PayCheckBatch; +import com.pig4cloud.pigx.pay.mapper.PayCheckBatchMapper; +import com.pig4cloud.pigx.pay.service.PayCheckBatchService; +import org.springframework.stereotype.Service; + +/** + * 批量对账 + * + * @author lengleng + * @date 2019-05-28 23:57:38 + */ +@Service +public class PayCheckBatchServiceImpl extends ServiceImpl implements PayCheckBatchService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckMistakeServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckMistakeServiceImpl.java new file mode 100755 index 000000000..4110281ff --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayCheckMistakeServiceImpl.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ +package com.pig4cloud.pigx.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.pigx.pay.entity.PayCheckMistake; +import com.pig4cloud.pigx.pay.mapper.PayCheckMistakeMapper; +import com.pig4cloud.pigx.pay.service.PayCheckMistakeService; +import org.springframework.stereotype.Service; + +/** + * 差错 + * + * @author lengleng + * @date 2019-05-28 23:57:50 + */ +@Service +public class PayCheckMistakeServiceImpl extends ServiceImpl implements PayCheckMistakeService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java new file mode 100755 index 000000000..2ed7de8a8 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ +package com.pig4cloud.pigx.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.common.sequence.sequence.Sequence; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; +import com.pig4cloud.pigx.pay.mapper.PayGoodsOrderMapper; +import com.pig4cloud.pigx.pay.service.PayGoodsOrderService; +import com.pig4cloud.pigx.pay.service.PayTradeOrderService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 商品 + * + * @author lengleng + * @date 2019-05-28 23:58:27 + */ +@Slf4j +@Service +@AllArgsConstructor +public class PayGoodsOrderServiceImpl extends ServiceImpl implements PayGoodsOrderService { + private final PayTradeOrderService tradeOrderService; + private static final String WX = "MicroMessenger"; + private final HttpServletRequest request; + private final HttpServletResponse response; + private final Sequence paySequence; + + + /** + * 购买商品 + *

+ * 1、 新增商品订单 + * 2、 根据UA 去下单 + * 3、构建支付订单 + * + * @param amount + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public R buy(Long amount) { + } + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java new file mode 100755 index 000000000..75cc6e05e --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ +package com.pig4cloud.pigx.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.pigx.pay.entity.PayNotifyRecord; +import com.pig4cloud.pigx.pay.mapper.PayNotifyRecordMapper; +import com.pig4cloud.pigx.pay.service.PayNotifyRecordService; +import org.springframework.stereotype.Service; + +/** + * 异步通知记录 + * + * @author lengleng + * @date 2019-05-28 23:57:23 + */ +@Service +public class PayNotifyRecordServiceImpl extends ServiceImpl implements PayNotifyRecordService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java new file mode 100755 index 000000000..0c580cedc --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ +package com.pig4cloud.pigx.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.pigx.pay.entity.PayRefundOrder; +import com.pig4cloud.pigx.pay.mapper.PayRefundOrderMapper; +import com.pig4cloud.pigx.pay.service.PayRefundOrderService; +import org.springframework.stereotype.Service; + +/** + * 退款 + * + * @author lengleng + * @date 2019-05-28 23:58:11 + */ +@Service +public class PayRefundOrderServiceImpl extends ServiceImpl implements PayRefundOrderService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java new file mode 100755 index 000000000..9b9042c79 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ +package com.pig4cloud.pigx.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; +import com.pig4cloud.pigx.pay.mapper.PayTradeOrderMapper; +import com.pig4cloud.pigx.pay.service.PayTradeOrderService; +import org.springframework.stereotype.Service; + +/** + * 支付 + * + * @author lengleng + * @date 2019-05-28 23:58:18 + */ +@Service +public class PayTradeOrderServiceImpl extends ServiceImpl implements PayTradeOrderService { + +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java new file mode 100644 index 000000000..1f4967bb4 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java @@ -0,0 +1,44 @@ +package com.pig4cloud.pigx.pay.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author lengleng + * @date 2019-05-30 + *

+ * 订单状态 + */ +@Getter +@AllArgsConstructor +public enum OrderStatusEnum { + /** + * 订单初始 下单 + */ + INIT(0, "下单"), + + /** + * 订单支付成功 + */ + SUCCESS(1, "成功"), + + /** + * 订单支付完成 + */ + COMPLETE(2, "完成"), + + /** + * 订单支付失败 + */ + FAIL(-1, "失败"); + + + /** + * 状态 + */ + private Integer status; + /** + * 描述 + */ + private String description; +} diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java new file mode 100644 index 000000000..35ecfdeb2 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java @@ -0,0 +1,38 @@ +package com.pig4cloud.pigx.pay.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author lengleng + * @date 2019-05-30 + *

+ * 支付渠道名称 + */ +@Getter +@AllArgsConstructor +public enum PayChannelNameEnum { + /** + * 支付宝 + */ + ALIPAY("alipay", "支付宝"), + + /** + * 微信支付 + */ + WXPAY("wxpay", "微信支付"), + + /** + * 微信服务商支付 + */ + WESUBPAY("wxsubpay", "微信服务商支付"); + + /** + * 名称 + */ + private String name; + /** + * 描述 + */ + private String description; +} diff --git a/pigx-visual/pigx-pay/src/main/resources/bootstrap.yml b/pigx-visual/pigx-pay/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..8d8a9b22c --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/bootstrap.yml @@ -0,0 +1,16 @@ +server: + port: 5003 + +spring: + application: + name: @artifactId@ + cloud: + nacos: + discovery: + server-addr: ${NACOS-HOST:pigx-register}:${NACOS-PORT:8848} + config: + server-addr: ${spring.cloud.nacos.discovery.server-addr} + file-extension: yml + shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + profiles: + active: dev \ No newline at end of file diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml new file mode 100755 index 000000000..c85d2d2a7 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckBatchMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckBatchMapper.xml new file mode 100755 index 000000000..7d15fa34a --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckBatchMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckMistakeMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckMistakeMapper.xml new file mode 100755 index 000000000..2ce7c6527 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayCheckMistakeMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml new file mode 100755 index 000000000..062bf059f --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml new file mode 100755 index 000000000..b12d1538e --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml new file mode 100755 index 000000000..f038ae10e --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml b/pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml new file mode 100755 index 000000000..cd68a0852 --- /dev/null +++ b/pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pigx-visual/pigx-seata-server/pom.xml b/pigx-visual/pigx-seata-server/pom.xml deleted file mode 100755 index 1d9c33897..000000000 --- a/pigx-visual/pigx-seata-server/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - com.pig4cloud - pigx-visual - 3.0.0 - - - 4.0.0 - pigx-seata-server - jar - pigx-seata-server - - - - io.seata - seata-core - 0.5.2 - - - io.seata - seata-config-all - 0.5.2 - - - io.seata - seata-discovery-all - 0.5.2 - - - diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java deleted file mode 100755 index d6655196e..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import io.seata.common.XID; -import io.seata.core.exception.AbstractExceptionHandler; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.GlobalStatus; -import io.seata.core.protocol.transaction.BranchRegisterRequest; -import io.seata.core.protocol.transaction.BranchRegisterResponse; -import io.seata.core.protocol.transaction.BranchReportRequest; -import io.seata.core.protocol.transaction.BranchReportResponse; -import io.seata.core.protocol.transaction.GlobalBeginRequest; -import io.seata.core.protocol.transaction.GlobalBeginResponse; -import io.seata.core.protocol.transaction.GlobalCommitRequest; -import io.seata.core.protocol.transaction.GlobalCommitResponse; -import io.seata.core.protocol.transaction.GlobalLockQueryRequest; -import io.seata.core.protocol.transaction.GlobalLockQueryResponse; -import io.seata.core.protocol.transaction.GlobalRollbackRequest; -import io.seata.core.protocol.transaction.GlobalRollbackResponse; -import io.seata.core.protocol.transaction.GlobalStatusRequest; -import io.seata.core.protocol.transaction.GlobalStatusResponse; -import io.seata.core.protocol.transaction.TCInboundHandler; -import io.seata.core.rpc.RpcContext; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; - -/** - * The type Abstract tc inbound handler. - * - * @author sharajava - */ -public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler implements TCInboundHandler { - - @Override - public GlobalBeginResponse handle(GlobalBeginRequest request, final RpcContext rpcContext) { - GlobalBeginResponse response = new GlobalBeginResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalBeginRequest request, GlobalBeginResponse response) throws TransactionException { - doGlobalBegin(request, response, rpcContext); - } - }, request, response); - return response; - } - - /** - * Do global begin. - * - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalCommitResponse handle(GlobalCommitRequest request, final RpcContext rpcContext) { - GlobalCommitResponse response = new GlobalCommitResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalCommitRequest request, GlobalCommitResponse response) - throws TransactionException { - doGlobalCommit(request, response, rpcContext); - } - }, request, response); - return response; - } - - /** - * Do global commit. - * - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalRollbackResponse handle(GlobalRollbackRequest request, final RpcContext rpcContext) { - GlobalRollbackResponse response = new GlobalRollbackResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalRollbackRequest request, GlobalRollbackResponse response) - throws TransactionException { - doGlobalRollback(request, response, rpcContext); - } - - @Override - public void onTransactionException(GlobalRollbackRequest request, GlobalRollbackResponse response, - TransactionException tex) { - super.onTransactionException(request, response, tex); - GlobalSession globalSession = SessionHolder.findGlobalSession( - XID.getTransactionId(request.getXid())); - if (globalSession != null) { - response.setGlobalStatus(globalSession.getStatus()); - } else { - response.setGlobalStatus(GlobalStatus.Finished); - } - } - - @Override - public void onException(GlobalRollbackRequest request, GlobalRollbackResponse response, Exception rex) { - super.onException(request, response, rex); - GlobalSession globalSession = SessionHolder.findGlobalSession( - XID.getTransactionId(request.getXid())); - if (globalSession != null) { - response.setGlobalStatus(globalSession.getStatus()); - } else { - response.setGlobalStatus(GlobalStatus.Finished); - } - } - }, request, response); - return response; - } - - /** - * Do global rollback. - * - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public BranchRegisterResponse handle(BranchRegisterRequest request, final RpcContext rpcContext) { - BranchRegisterResponse response = new BranchRegisterResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(BranchRegisterRequest request, BranchRegisterResponse response) - throws TransactionException { - doBranchRegister(request, response, rpcContext); - } - }, request, response); - return response; - } - - /** - * Do branch register. - * - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public BranchReportResponse handle(BranchReportRequest request, final RpcContext rpcContext) { - BranchReportResponse response = new BranchReportResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(BranchReportRequest request, BranchReportResponse response) - throws TransactionException { - doBranchReport(request, response, rpcContext); - } - }, request, response); - return response; - } - - /** - * Do branch report. - * - * @param request the request - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doBranchReport(BranchReportRequest request, BranchReportResponse response, - RpcContext rpcContext) - throws TransactionException; - - @Override - public GlobalLockQueryResponse handle(GlobalLockQueryRequest request, final RpcContext rpcContext) { - GlobalLockQueryResponse response = new GlobalLockQueryResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalLockQueryRequest request, GlobalLockQueryResponse response) - throws TransactionException { - doLockCheck(request, response, rpcContext); - } - }, request, response); - return response; - } - - /** - * Do lock check. - * - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response, - RpcContext rpcContext) throws TransactionException; - - @Override - public GlobalStatusResponse handle(GlobalStatusRequest request, final RpcContext rpcContext) { - GlobalStatusResponse response = new GlobalStatusResponse(); - exceptionHandleTemplate(new AbstractCallback() { - @Override - public void execute(GlobalStatusRequest request, GlobalStatusResponse response) - throws TransactionException { - doGlobalStatus(request, response, rpcContext); - } - }, request, response); - return response; - } - - /** - * Do global status. - * - * @param request the request - * @param response the response - * @param rpcContext the rpc context - * @throws TransactionException the transaction exception - */ - protected abstract void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response, - RpcContext rpcContext) throws TransactionException; - -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java deleted file mode 100755 index 43df651ee..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import io.seata.common.XID; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.NetUtil; -import io.seata.core.rpc.netty.RpcServer; -import io.seata.core.rpc.netty.ShutdownHook; -import io.seata.server.coordinator.DefaultCoordinator; -import io.seata.server.session.SessionHolder; - -import java.io.IOException; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * The type Server. - * - * @author jimin.jm @alibaba-inc.com - */ -public class Server { - - private static final int MIN_SERVER_POOL_SIZE = 10; - private static final int MAX_SERVER_POOL_SIZE = 50; - private static final int MAX_TASK_QUEUE_SIZE = 2000; - private static final int KEEP_ALIVE_TIME = 50; - private static final int SERVER_DEFAULT_PORT = 8091; - private static final ThreadPoolExecutor WORKING_THREADS = new ThreadPoolExecutor(MIN_SERVER_POOL_SIZE, - MAX_SERVER_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, - new LinkedBlockingQueue(MAX_TASK_QUEUE_SIZE), - new NamedThreadFactory("ServerHandlerThread", MAX_SERVER_POOL_SIZE), new ThreadPoolExecutor.CallerRunsPolicy()); - - /** - * The entry point of application. - * - * @param args the input arguments - * @throws IOException the io exception - */ - public static void main(String[] args) throws IOException { - RpcServer rpcServer = new RpcServer(WORKING_THREADS); - - rpcServer.setListenPort(SERVER_DEFAULT_PORT); - - //log store mode : file、db - String storeMode = "file"; - - UUIDGenerator.init(1); - SessionHolder.init(storeMode); - - DefaultCoordinator coordinator = new DefaultCoordinator(rpcServer); - coordinator.init(); - rpcServer.setHandler(coordinator); - // register ShutdownHook - ShutdownHook.getInstance().addDisposable(coordinator); - - XID.setIpAddress(NetUtil.getLocalIp()); - XID.setPort(rpcServer.getListenPort()); - - rpcServer.init(); - - System.exit(0); - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java deleted file mode 100755 index efc55e555..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.concurrent.atomic.AtomicLong; - -import io.seata.common.exception.ShouldNeverHappenException; - -/** - * The type Uuid generator. - * - * @author sharajava - */ -public class UUIDGenerator { - - private static final AtomicLong UUID = new AtomicLong(1000); - private static int serverNodeId = 1; - private static final long UUID_INTERNAL = 2000000000; - - /** - * Generate uuid long. - * - * @return the long - */ - public static long generateUUID() { - long id = UUID.incrementAndGet(); - if (id >= UUID_INTERNAL * (serverNodeId + 1)) { - synchronized (UUID) { - if (UUID.get() >= id) { - id -= UUID_INTERNAL; - UUID.set(id); - } - } - } - return id; - } - - /** - * Gets current uuid. - * - * @return the current uuid - */ - public static long getCurrentUUID() { - return UUID.get(); - } - - /** - * Sets uuid. - * - * @param expect the expect - * @param update the update - * @return the uuid - */ - public static boolean setUUID(long expect, long update) { - return UUID.compareAndSet(expect, update); - - } - - /** - * Init. - * - * @param serverNodeId the server node id - */ - public static void init(int serverNodeId) { - try { - UUIDGenerator.serverNodeId = serverNodeId; - UUID.set(UUID_INTERNAL * serverNodeId); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); - Calendar cal = Calendar.getInstance(); - Date date = format.parse("2019-01-01"); - cal.setTime(date); - long base = cal.getTimeInMillis(); - long current = System.currentTimeMillis(); - UUID.addAndGet((current - base) / 1000); - } catch (ParseException e) { - throw new ShouldNeverHappenException(e); - } - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java deleted file mode 100755 index 7d34dfee1..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.ResourceManagerInbound; -import io.seata.core.model.ResourceManagerOutbound; -import io.seata.core.model.TransactionManager; -import io.seata.server.session.GlobalSession; - -/** - * The interface Core. - * - * @author sharajava - */ -public interface Core extends TransactionManager, ResourceManagerOutbound { - - /** - * Sets resource manager inbound. - * - * @param resourceManagerInbound the resource manager inbound - */ - void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbound); - - /** - * Do global commit. - * - * @param globalSession the global session - * @param retrying the retrying - * @throws TransactionException the transaction exception - */ - void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException; - - /** - * Do global rollback. - * - * @param globalSession the global session - * @param retrying the retrying - * @throws TransactionException the transaction exception - */ - void doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException; -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java deleted file mode 100755 index 19e09f70e..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -/** - * The type Core factory. - * - * @author sharajava - */ -public class CoreFactory { - - private static class SingletonHolder { - private static Core INSTANCE = new DefaultCore(); - } - - /** - * Get core. - * - * @return the core - */ - public static final Core get() { - return SingletonHolder.INSTANCE; - } - - /** - * Just for test mocking - * - * @param core the core - */ - public static void set(Core core) { - SingletonHolder.INSTANCE = core; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java deleted file mode 100755 index 024f741a9..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.common.XID; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.ResourceManagerInbound; -import io.seata.core.protocol.AbstractMessage; -import io.seata.core.protocol.AbstractResultMessage; -import io.seata.core.protocol.transaction.*; -import io.seata.core.rpc.Disposable; -import io.seata.core.rpc.RpcContext; -import io.seata.core.rpc.ServerMessageSender; -import io.seata.core.rpc.TransactionMessageHandler; -import io.seata.core.rpc.netty.RpcServer; -import io.seata.server.AbstractTCInboundHandler; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Collection; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchCommitRequest; -import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchRollbackRequest; - -/** - * The type Default coordinator. - * - * @author sharajava - */ -public class DefaultCoordinator extends AbstractTCInboundHandler - implements TransactionMessageHandler, ResourceManagerInbound, Disposable { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCoordinator.class); - - private static final int TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS = 5000; - - private ServerMessageSender messageSender; - - private Core core = CoreFactory.get(); - - /** - * Instantiates a new Default coordinator. - * - * @param messageSender the message sender - */ - public DefaultCoordinator(ServerMessageSender messageSender) { - this.messageSender = messageSender; - core.setResourceManagerInbound(this); - } - - @Override - protected void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, RpcContext rpcContext) - throws TransactionException { - response.setXid(core.begin(rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(), - request.getTransactionName(), request.getTimeout())); - } - - @Override - protected void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, RpcContext rpcContext) - throws TransactionException { - response.setGlobalStatus(core.commit(request.getXid())); - - } - - @Override - protected void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response, - RpcContext rpcContext) throws TransactionException { - response.setGlobalStatus(core.rollback(request.getXid())); - - } - - @Override - protected void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response, RpcContext rpcContext) - throws TransactionException { - response.setGlobalStatus(core.getStatus(request.getXid())); - } - - @Override - protected void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response, - RpcContext rpcContext) throws TransactionException { - response.setBranchId( - core.branchRegister(request.getBranchType(), request.getResourceId(), rpcContext.getClientId(), - request.getXid(), request.getApplicationData(), request.getLockKey())); - - } - - @Override - protected void doBranchReport(BranchReportRequest request, BranchReportResponse response, RpcContext rpcContext) - throws TransactionException { - core.branchReport(request.getBranchType(), request.getXid(), request.getBranchId(), - request.getStatus(), - request.getApplicationData()); - - } - - @Override - protected void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response, RpcContext rpcContext) - throws TransactionException { - response.setLockable(core.lockQuery(request.getBranchType(), request.getResourceId(), - request.getXid(), request.getLockKey())); - } - - @Override - public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId, - String applicationData) - throws TransactionException { - try { - BranchCommitRequest request = new BranchCommitRequest(); - request.setXid(xid); - request.setBranchId(branchId); - request.setResourceId(resourceId); - request.setApplicationData(applicationData); - request.setBranchType(branchType); - - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - if(globalSession == null){ - return BranchStatus.PhaseTwo_Committed; - } - BranchSession branchSession = globalSession.getBranch(branchId); - - BranchCommitResponse response = (BranchCommitResponse)messageSender.sendSyncRequest(resourceId, - branchSession.getClientId(), request); - return response.getBranchStatus(); - } catch (IOException e) { - throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e); - } catch (TimeoutException e) { - throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e); - } - } - - @Override - public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, - String applicationData) - throws TransactionException { - try { - BranchRollbackRequest - request = new BranchRollbackRequest(); - request.setXid(xid); - request.setBranchId(branchId); - request.setResourceId(resourceId); - request.setApplicationData(applicationData); - request.setBranchType(branchType); - - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - if(globalSession == null){ - return BranchStatus.PhaseTwo_Rollbacked; - } - BranchSession branchSession = globalSession.getBranch(branchId); - - BranchRollbackResponse response = (BranchRollbackResponse)messageSender.sendSyncRequest(resourceId, - branchSession.getClientId(), request); - return response.getBranchStatus(); - } catch (IOException e) { - throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e); - } catch (TimeoutException e) { - throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e); - } - } - - private void timeoutCheck() throws TransactionException { - Collection allSessions = SessionHolder.getRootSessionManager().allSessions(); - if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) { - LOGGER.debug("Transaction Timeout Check Begin: " + allSessions.size()); - } - for (GlobalSession globalSession : allSessions) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(globalSession.getTransactionId() + " " + globalSession.getStatus() + " " + - globalSession.getBeginTime() + " " + globalSession.getTimeout()); - } - boolean shouldTimeout = globalSession.lockAndExcute(() -> { - if (globalSession.getStatus() != GlobalStatus.Begin || !globalSession.isTimeout()) { - return false; - } - globalSession.close(); - globalSession.changeStatus(GlobalStatus.TimeoutRollbacking); - return true; - }); - if (!shouldTimeout) { - continue; - } - LOGGER.info( - "Global transaction[" + globalSession.getTransactionId() + "] is timeout and will be rolled back."); - - globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager()); - SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession); - - } - if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) { - LOGGER.debug("Transaction Timeout Check End. "); - } - - } - - private void handleRetryRollbacking() { - Collection rollbackingSessions = SessionHolder.getRetryRollbackingSessionManager().allSessions(); - for (GlobalSession rollbackingSession : rollbackingSessions) { - try { - core.doGlobalRollback(rollbackingSession, true); - } catch (TransactionException ex) { - LOGGER.info("Failed to retry rollbacking [{}] {} {}", - rollbackingSession.getTransactionId(), ex.getCode(), ex.getMessage()); - } - } - } - - private void handleRetryCommitting() { - Collection committingSessions = SessionHolder.getRetryCommittingSessionManager().allSessions(); - for (GlobalSession committingSession : committingSessions) { - try { - core.doGlobalCommit(committingSession, true); - } catch (TransactionException ex) { - LOGGER.info("Failed to retry committing [{}] {} {}", - committingSession.getTransactionId(), ex.getCode(), ex.getMessage()); - } - } - } - - private void handleAsyncCommitting() { - Collection asyncCommittingSessions = SessionHolder.getAsyncCommittingSessionManager() - .allSessions(); - for (GlobalSession asyncCommittingSession : asyncCommittingSessions) { - try { - core.doGlobalCommit(asyncCommittingSession, true); - } catch (TransactionException ex) { - LOGGER.info("Failed to async committing [{}] {} {}", - asyncCommittingSession.getTransactionId(), ex.getCode(), ex.getMessage()); - } - } - } - - private ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("RetryRollbacking", 1)); - - private ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("RetryCommitting", 1)); - - private ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("AsyncCommitting", 1)); - - private ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("TxTimeoutCheck", 1)); - - /** - * Init. - */ - public void init() { - retryRollbacking.scheduleAtFixedRate(new Runnable() { - - @Override - public void run() { - try { - handleRetryRollbacking(); - } catch (Exception e) { - LOGGER.info("Exception retry rollbacking ... ", e); - } - - } - }, 0, 5, TimeUnit.MILLISECONDS); - - retryCommitting.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - handleRetryCommitting(); - } catch (Exception e) { - LOGGER.info("Exception retry committing ... ", e); - } - - } - }, 0, 5, TimeUnit.MILLISECONDS); - - asyncCommitting.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - handleAsyncCommitting(); - } catch (Exception e) { - LOGGER.info("Exception async committing ... ", e); - } - - } - }, 0, 10, TimeUnit.MILLISECONDS); - - timeoutCheck.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - timeoutCheck(); - } catch (Exception e) { - LOGGER.info("Exception timeout checking ... ", e); - } - - } - }, 0, 2, TimeUnit.MILLISECONDS); - } - - @Override - public AbstractResultMessage onRequest(AbstractMessage request, RpcContext context) { - if (!(request instanceof AbstractTransactionRequestToTC)) { - throw new IllegalArgumentException(); - } - AbstractTransactionRequestToTC transactionRequest = (AbstractTransactionRequestToTC)request; - transactionRequest.setTCInboundHandler(this); - - return transactionRequest.handle(context); - } - - @Override - public void onResponse(AbstractResultMessage response, RpcContext context) { - if (!(response instanceof AbstractTransactionResponse)) { - throw new IllegalArgumentException(); - } - - } - - @Override - public void destroy() { - // 1. first shutdown timed task - retryRollbacking.shutdown(); - retryCommitting.shutdown(); - asyncCommitting.shutdown(); - timeoutCheck.shutdown(); - try { - retryRollbacking.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - } catch (InterruptedException ingore) { - - } - // 2. sencond close netty flow - if (messageSender instanceof RpcServer){ - ((RpcServer) messageSender).destroy(); - } - // 3. last destory SessionHolder - SessionHolder.destory(); - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java deleted file mode 100755 index 1ba36763f..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.coordinator; - -import io.seata.common.XID; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.model.ResourceManagerInbound; -import io.seata.server.lock.LockManager; -import io.seata.server.lock.LockManagerFactory; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHelper; -import io.seata.server.session.SessionHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static io.seata.core.exception.TransactionExceptionCode.BranchTransactionNotExist; -import static io.seata.core.exception.TransactionExceptionCode.FailedToAddBranch; -import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionNotActive; -import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionStatusInvalid; -import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflict; - -/** - * The type Default core. - * - * @author sharajava - */ -public class DefaultCore implements Core { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCore.class); - - private LockManager lockManager = LockManagerFactory.get(); - - private ResourceManagerInbound resourceManagerInbound; - - @Override - public void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbound) { - this.resourceManagerInbound = resourceManagerInbound; - } - - @Override - public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, - String applicationData, String lockKeys) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid)); - return globalSession.lockAndExcute(() -> { - if (!globalSession.isActive()) { - throw new TransactionException(GlobalTransactionNotActive, "Current Status: " + globalSession.getStatus()); - } - if (globalSession.getStatus() != GlobalStatus.Begin) { - throw new TransactionException(GlobalTransactionStatusInvalid, - globalSession.getStatus() + " while expecting " + GlobalStatus.Begin); - } - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId, - applicationData, lockKeys, clientId); - if (!branchSession.lock()) { - throw new TransactionException(LockKeyConflict); - } - try { - globalSession.addBranch(branchSession); - } catch (RuntimeException ex) { - throw new TransactionException(FailedToAddBranch); - } - return branchSession.getBranchId(); - }); - } - - private GlobalSession assertGlobalSessionNotNull(long transactionId) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); - if (globalSession == null) { - throw new TransactionException(TransactionExceptionCode.GlobalTransactionNotExist, "" + transactionId + ""); - } - return globalSession; - } - - - @Override - public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, - String applicationData) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid)); - BranchSession branchSession = globalSession.getBranch(branchId); - if (branchSession == null) { - throw new TransactionException(BranchTransactionNotExist); - } - globalSession.changeBranchStatus(branchSession, status); - } - - @Override - public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) - throws TransactionException { - if (branchType == BranchType.AT) { - return lockManager.isLockable(XID.getTransactionId(xid), resourceId, lockKeys); - } else { - return true; - } - - } - - @Override - public String begin(String applicationId, String transactionServiceGroup, String name, int timeout) - throws TransactionException { - GlobalSession session = GlobalSession.createGlobalSession( - applicationId, transactionServiceGroup, name, timeout); - session.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); - - session.begin(); - - return XID.generateXID(session.getTransactionId()); - } - - @Override - public GlobalStatus commit(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - if (globalSession == null) { - return GlobalStatus.Finished; - } - // just lock changeStatus - boolean shouldCommit = globalSession.lockAndExcute(() -> { - globalSession.closeAndClean(); // Highlight: Firstly, close the session, then no more branch can be registered. - if (globalSession.getStatus() == GlobalStatus.Begin) { - globalSession.changeStatus(GlobalStatus.Committing); - return true; - } - return false; - }); - if (!shouldCommit){ - return globalSession.getStatus(); - } - if (globalSession.canBeCommittedAsync()) { - asyncCommit(globalSession); - return GlobalStatus.Committed; - } else { - doGlobalCommit(globalSession, false); - } - return globalSession.getStatus(); - } - - @Override - public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException { - for (BranchSession branchSession : globalSession.getSortedBranches()) { - BranchStatus currentStatus = branchSession.getStatus(); - if (currentStatus == BranchStatus.PhaseOne_Failed) { - globalSession.removeBranch(branchSession); - continue; - } - try { - BranchStatus branchStatus = resourceManagerInbound.branchCommit(branchSession.getBranchType(), - XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(), - branchSession.getResourceId(), branchSession.getApplicationData()); - - switch (branchStatus) { - case PhaseTwo_Committed: - globalSession.removeBranch(branchSession); - continue; - case PhaseTwo_CommitFailed_Unretryable: - if (globalSession.canBeCommittedAsync()) { - LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession); - continue; - } else { - SessionHelper.endCommitFailed(globalSession); - LOGGER.error("Finally, failed to commit global[{}] since branch[{}] commit failed", - globalSession.getTransactionId(), branchSession.getBranchId()); - return; - } - default: - if (!retrying) { - queueToRetryCommit(globalSession); - return; - } - if (globalSession.canBeCommittedAsync()) { - LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession); - continue; - } else { - LOGGER.error( - "Failed to commit global[{}] since branch[{}] commit failed, will retry later.", - globalSession.getTransactionId(), branchSession.getBranchId()); - return; - } - - } - - } catch (Exception ex) { - LOGGER.error("Exception committing branch {}", branchSession, ex); - if (!retrying) { - queueToRetryCommit(globalSession); - throw new TransactionException(ex); - } - - } - - } - if (globalSession.hasBranch()) { - LOGGER.info("Global[{}] committing is NOT done.", globalSession.getTransactionId()); - return; - } - SessionHelper.endCommitted(globalSession); - LOGGER.info("Global[{}] committing is successfully done.", globalSession.getTransactionId()); - } - - private void asyncCommit(GlobalSession globalSession) throws TransactionException { - globalSession.addSessionLifecycleListener(SessionHolder.getAsyncCommittingSessionManager()); - SessionHolder.getAsyncCommittingSessionManager().addGlobalSession(globalSession); - globalSession.changeStatus(GlobalStatus.AsyncCommitting); - } - - private void queueToRetryCommit(GlobalSession globalSession) throws TransactionException { - globalSession.addSessionLifecycleListener(SessionHolder.getRetryCommittingSessionManager()); - SessionHolder.getRetryCommittingSessionManager().addGlobalSession(globalSession); - globalSession.changeStatus(GlobalStatus.CommitRetrying); - } - - private void queueToRetryRollback(GlobalSession globalSession) throws TransactionException { - globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager()); - SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession); - GlobalStatus currentStatus = globalSession.getStatus(); - if (SessionHelper.isTimeoutGlobalStatus(currentStatus)) { - globalSession.changeStatus(GlobalStatus.TimeoutRollbackRetrying); - } else { - globalSession.changeStatus(GlobalStatus.RollbackRetrying); - } - } - - @Override - public GlobalStatus rollback(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - if (globalSession == null) { - return GlobalStatus.Finished; - } - // just lock changeStatus - boolean shouldRollBack = globalSession.lockAndExcute(() -> { - globalSession.close(); // Highlight: Firstly, close the session, then no more branch can be registered. - if (globalSession.getStatus() == GlobalStatus.Begin) { - globalSession.changeStatus(GlobalStatus.Rollbacking); - return true; - } - return false; - }); - if (!shouldRollBack){ - return globalSession.getStatus(); - } - - doGlobalRollback(globalSession, false); - return globalSession.getStatus(); - } - - @Override - public void doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException { - for (BranchSession branchSession : globalSession.getReverseSortedBranches()) { - BranchStatus currentBranchStatus = branchSession.getStatus(); - if (currentBranchStatus == BranchStatus.PhaseOne_Failed) { - globalSession.removeBranch(branchSession); - continue; - } - try { - BranchStatus branchStatus = resourceManagerInbound.branchRollback(branchSession.getBranchType(), - XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(), - branchSession.getResourceId(), branchSession.getApplicationData()); - - switch (branchStatus) { - case PhaseTwo_Rollbacked: - globalSession.removeBranch(branchSession); - LOGGER.error("Successfully rolled back branch " + branchSession); - continue; - case PhaseTwo_RollbackFailed_Unretryable: - SessionHelper.endRollbackFailed(globalSession); - LOGGER.error("Failed to rollback global[" + globalSession.getTransactionId() + "] since branch[" - + branchSession.getBranchId() + "] rollback failed"); - return; - default: - LOGGER.info("Failed to rollback branch " + branchSession); - if (!retrying) { - queueToRetryRollback(globalSession); - } - return; - - } - } catch (Exception ex) { - LOGGER.error("Exception rollbacking branch " + branchSession, ex); - if (!retrying) { - queueToRetryRollback(globalSession); - } - throw new TransactionException(ex); - } - - } - SessionHelper.endRollbacked(globalSession); - } - - @Override - public GlobalStatus getStatus(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - return globalSession.getStatus(); - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java deleted file mode 100755 index a0c576c84..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import io.netty.util.internal.ConcurrentSet; -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.util.StringUtils; -import io.seata.core.exception.TransactionException; -import io.seata.server.session.BranchSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * The type Default lock manager. - * - * @author sharajava - */ -public class DefaultLockManagerImpl implements LockManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLockManagerImpl.class); - - private static final int BUCKET_PER_TABLE = 128; - - private static final - ConcurrentHashMap>>> - LOCK_MAP = new ConcurrentHashMap>>>(); - - @Override - public boolean acquireLock(BranchSession branchSession) throws TransactionException { - String resourceId = branchSession.getResourceId(); - long transactionId = branchSession.getTransactionId(); - ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); - if (dbLockMap == null) { - LOCK_MAP.putIfAbsent(resourceId, - new ConcurrentHashMap>>()); - dbLockMap = LOCK_MAP.get(resourceId); - } - ConcurrentHashMap, Set> bucketHolder = branchSession.getLockHolder(); - - String lockKey = branchSession.getLockKey(); - if (StringUtils.isNullOrEmpty(lockKey)) { - return true; - } - - String[] tableGroupedLockKeys = lockKey.split(";"); - for (String tableGroupedLockKey : tableGroupedLockKeys) { - int idx = tableGroupedLockKey.indexOf(":"); - if (idx < 0) { - branchSession.unlock(); - throw new ShouldNeverHappenException("Wrong format of LOCK KEYS: " + branchSession.getLockKey()); - } - String tableName = tableGroupedLockKey.substring(0, idx); - String mergedPKs = tableGroupedLockKey.substring(idx + 1); - ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); - if (tableLockMap == null) { - dbLockMap.putIfAbsent(tableName, new ConcurrentHashMap>()); - tableLockMap = dbLockMap.get(tableName); - } - String[] pks = mergedPKs.split(","); - for (String pk : pks) { - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - Map bucketLockMap = tableLockMap.get(bucketId); - if (bucketLockMap == null) { - tableLockMap.putIfAbsent(bucketId, new HashMap()); - bucketLockMap = tableLockMap.get(bucketId); - } - synchronized (bucketLockMap) { - Long lockingTransactionId = bucketLockMap.get(pk); - if (lockingTransactionId == null) { - // No existing lock - bucketLockMap.put(pk, transactionId); - Set keysInHolder = bucketHolder.get(bucketLockMap); - if (keysInHolder == null) { - bucketHolder.putIfAbsent(bucketLockMap, new ConcurrentSet()); - keysInHolder = bucketHolder.get(bucketLockMap); - } - keysInHolder.add(pk); - - } else if (lockingTransactionId.longValue() == transactionId) { - // Locked by me - continue; - } else { - LOGGER.info( - "Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); - branchSession.unlock(); // Release all acquired locks. - return false; - } - } - } - } - return true; - } - - @Override - public boolean isLockable(long transactionId, String resourceId, String lockKey) throws TransactionException { - ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); - if (dbLockMap == null) { - return true; - } - String[] tableGroupedLockKeys = lockKey.split(";"); - for (String tableGroupedLockKey : tableGroupedLockKeys) { - int idx = tableGroupedLockKey.indexOf(":"); - if (idx < 0) { - throw new ShouldNeverHappenException("Wrong format of LOCK KEYS: " + lockKey); - } - String tableName = tableGroupedLockKey.substring(0, idx); - String mergedPKs = tableGroupedLockKey.substring(idx + 1); - ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); - if (tableLockMap == null) { - continue; - } - String[] pks = mergedPKs.split(","); - for (String pk : pks) { - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - Map bucketLockMap = tableLockMap.get(bucketId); - if (bucketLockMap == null) { - continue; - } - Long lockingTransactionId = bucketLockMap.get(pk); - if (lockingTransactionId == null || lockingTransactionId.longValue() == transactionId) { - // Locked by me - continue; - } else { - LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); - return false; - } - } - } - return true; - } - - @Override - public void cleanAllLocks() throws TransactionException { - LOCK_MAP.clear(); - } - - @Override - public boolean releaseLock(BranchSession branchSession) throws TransactionException { - ConcurrentHashMap, Set> lockHolder = branchSession.getLockHolder(); - if (lockHolder.size() == 0) { - return true; - } - Iterator, Set>> it = lockHolder.entrySet().iterator(); - while (it.hasNext()) { - Entry, Set> entry = it.next(); - Map bucket = entry.getKey(); - Set keys = entry.getValue(); - synchronized (bucket) { - for (String key : keys) { - Long v = bucket.get(key); - if (v == null) { - continue; - } - if (v.longValue() == branchSession.getTransactionId()) { - bucket.remove(key); - } - } - } - } - lockHolder.clear(); - return true; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManager.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManager.java deleted file mode 100755 index 54bcef3c0..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManager.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import io.seata.core.exception.TransactionException; -import io.seata.server.session.BranchSession; - -/** - * The interface Lock manager. - * - * @author sharajava - */ -public interface LockManager { - - /** - * Acquire lock boolean. - * - * @param branchSession the branch session - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean acquireLock(BranchSession branchSession) throws TransactionException; - - /** - * Is lockable boolean. - * - * @param transactionId the transaction id - * @param resourceId the resource id - * @param lockKey the lock key - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean isLockable(long transactionId, String resourceId, String lockKey) throws TransactionException; - - /** - * Clean all locks. - * - * @throws TransactionException the transaction exception - */ - void cleanAllLocks() throws TransactionException; - - /** - * Release lock boolean. - * - * @param branchSession the branch session - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean releaseLock(BranchSession branchSession) throws TransactionException; -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManagerFactory.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManagerFactory.java deleted file mode 100755 index 3468cc894..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManagerFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -/** - * The type Lock manager factory. - * - * @author sharajava - */ -public class LockManagerFactory { - - private static class SingletonHolder { - private static LockManager INSTANCE = new DefaultLockManagerImpl(); - } - - /** - * Get lock manager. - * - * @return the lock manager - */ - public static final LockManager get() { - return SingletonHolder.INSTANCE; - } - - /** - * Just for test mocking - * - * @param lockManager the lock manager - */ - public static void set(LockManager lockManager) { - SingletonHolder.INSTANCE = lockManager; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/AbstractSessionManager.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/AbstractSessionManager.java deleted file mode 100755 index d58f8b71d..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/AbstractSessionManager.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.TransactionStoreManager.LogOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * The type Abstract session manager. - * - * @author sharajava - */ -public abstract class AbstractSessionManager implements SessionManager, SessionLifecycleListener { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractSessionManager.class); - - /** - * The Session map. - */ - protected Map sessionMap = new ConcurrentHashMap<>(); - - /** - * The Transaction store manager. - */ - protected TransactionStoreManager transactionStoreManager; - - /** - * The Name. - */ - protected String name; - - /** - * Instantiates a new Abstract session manager. - * - * @param name the name - */ - public AbstractSessionManager(String name) { - this.name = name; - } - - @Override - public void addGlobalSession(GlobalSession session) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[" + name + "] SESSION[" + session + "] " + LogOperation.GLOBAL_ADD); - } - writeSession(LogOperation.GLOBAL_ADD, session); - sessionMap.put(session.getTransactionId(), session); - - } - - - - @Override - public GlobalSession findGlobalSession(Long transactionId) { - return sessionMap.get(transactionId); - } - - @Override - public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[" + name + "] SESSION[" + session + "] " + LogOperation.GLOBAL_UPDATE); - } - writeSession(LogOperation.GLOBAL_UPDATE, session); - } - - @Override - public void removeGlobalSession(GlobalSession session) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[" + name + "] SESSION[" + session + "] " + LogOperation.GLOBAL_REMOVE); - } - writeSession(LogOperation.GLOBAL_REMOVE, session); - sessionMap.remove(session.getTransactionId()); - - } - - @Override - public void addBranchSession(GlobalSession session, BranchSession branchSession) throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[" + name + "] SESSION[" + branchSession + "] " + LogOperation.BRANCH_ADD); - } - writeSession(LogOperation.BRANCH_ADD, branchSession); - } - - @Override - public void updateBranchSessionStatus(BranchSession branchSession, BranchStatus status) - throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[" + name + "] SESSION[" + branchSession + "] " + LogOperation.GLOBAL_ADD); - } - writeSession(LogOperation.BRANCH_UPDATE, branchSession); - } - - @Override - public void removeBranchSession(GlobalSession globalSession, BranchSession branchSession) - throws TransactionException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MANAGER[" + name + "] SESSION[" + branchSession + "] " + LogOperation.GLOBAL_ADD); - } - writeSession(LogOperation.BRANCH_REMOVE, branchSession); - - } - - @Override - public Collection allSessions() { - return sessionMap.values(); - } - - @Override - public List findGlobalSessions(SessionCondition condition) { - List found = new ArrayList<>(); - for (GlobalSession globalSession : sessionMap.values()) { - if (System.currentTimeMillis() - globalSession.getBeginTime() > condition.getOverTimeAliveMills()) { - found.add(globalSession); - } - } - return found; - } - - @Override - public void onBegin(GlobalSession globalSession) throws TransactionException { - addGlobalSession(globalSession); - } - - @Override - public void onStatusChange(GlobalSession globalSession, GlobalStatus status) throws TransactionException { - updateGlobalSessionStatus(globalSession, status); - } - - @Override - public void onBranchStatusChange(GlobalSession globalSession, BranchSession branchSession, BranchStatus status) - throws TransactionException { - updateBranchSessionStatus(branchSession, status); - } - - @Override - public void onAddBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException { - addBranchSession(globalSession, branchSession); - } - - @Override - public void onRemoveBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException { - removeBranchSession(globalSession, branchSession); - } - - @Override - public void onClose(GlobalSession globalSession) throws TransactionException { - globalSession.setActive(false); - - } - - @Override - public void onEnd(GlobalSession globalSession) throws TransactionException { - removeGlobalSession(globalSession); - - } - - private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException{ - if (!transactionStoreManager.writeSession(logOperation, sessionStorable)) { - throw new TransactionException(TransactionExceptionCode.FailedWriteSession); - } - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/BranchSession.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/BranchSession.java deleted file mode 100755 index 31e519612..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/BranchSession.java +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import io.seata.common.util.CompressUtil; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.server.lock.LockManagerFactory; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.StoreConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Branch session. - * - * @author sharajava - */ -public class BranchSession implements Lockable, Comparable, SessionStorable { - - private static final Logger LOGGER = LoggerFactory.getLogger(BranchSession.class); - - private static final int MAX_BRANCH_SESSION_SIZE = StoreConfig.getMaxBranchSessionSize(); - - private static ThreadLocal byteBufferThreadLocal = ThreadLocal.withInitial(() -> ByteBuffer.allocate( - MAX_BRANCH_SESSION_SIZE)); - - private long transactionId; - - private long branchId; - - private String resourceGroupId; - - private String resourceId; - - private String lockKey; - - private BranchType branchType; - - private BranchStatus status = BranchStatus.Unknown; - - private String clientId; - - private String applicationData; - - private ConcurrentHashMap, Set> lockHolder - = new ConcurrentHashMap, Set>(); - - /** - * Gets application data. - * - * @return the application data - */ - public String getApplicationData() { - return applicationData; - } - - /** - * Sets application data. - * - * @param applicationData the application data - */ - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } - - /** - * Gets resource group id. - * - * @return the resource group id - */ - public String getResourceGroupId() { - return resourceGroupId; - } - - /** - * Sets resource group id. - * - * @param resourceGroupId the resource group id - */ - public void setResourceGroupId(String resourceGroupId) { - this.resourceGroupId = resourceGroupId; - } - - /** - * Gets client id. - * - * @return the client id - */ - public String getClientId() { - return clientId; - } - - /** - * Sets client id. - * - * @param clientId the client id - */ - public void setClientId(String clientId) { - this.clientId = clientId; - } - - /** - * Gets resource id. - * - * @return the resource id - */ - public String getResourceId() { - return resourceId; - } - - /** - * Sets resource id. - * - * @param resourceId the resource id - */ - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - /** - * Gets lock key. - * - * @return the lock key - */ - public String getLockKey() { - return lockKey; - } - - /** - * Sets lock key. - * - * @param lockKey the lock key - */ - public void setLockKey(String lockKey) { - this.lockKey = lockKey; - } - - /** - * Gets branch type. - * - * @return the branch type - */ - public BranchType getBranchType() { - return branchType; - } - - /** - * Sets branch type. - * - * @param branchType the branch type - */ - public void setBranchType(BranchType branchType) { - this.branchType = branchType; - } - - /** - * Gets status. - * - * @return the status - */ - public BranchStatus getStatus() { - return status; - } - - /** - * Sets status. - * - * @param status the status - */ - void setStatus(BranchStatus status) { - this.status = status; - } - - /** - * Gets transaction id. - * - * @return the transaction id - */ - public long getTransactionId() { - return transactionId; - } - - /** - * Sets transaction id. - * - * @param transactionId the transaction id - */ - public void setTransactionId(long transactionId) { - this.transactionId = transactionId; - } - - /** - * Gets branch id. - * - * @return the branch id - */ - public long getBranchId() { - return branchId; - } - - /** - * Sets branch id. - * - * @param branchId the branch id - */ - public void setBranchId(long branchId) { - this.branchId = branchId; - } - - @Override - public String toString() { - return "BR:" + branchId + "/" + transactionId; - } - - @Override - public int compareTo(BranchSession o) { - return this.branchId < o.branchId ? -1 : (this.branchId > o.branchId ? 1 : 0); - } - - /** - * Gets lock holder. - * - * @return the lock holder - */ - public ConcurrentHashMap, Set> getLockHolder() { - return lockHolder; - } - - @Override - public boolean lock() throws TransactionException { - return LockManagerFactory.get().acquireLock(this); - } - - @Override - public boolean unlock() throws TransactionException { - return LockManagerFactory.get().releaseLock(this); - } - - @Override - public byte[] encode() { - - byte[] resourceIdBytes = resourceId != null ? resourceId.getBytes() : null; - - byte[] lockKeyBytes = lockKey != null ? lockKey.getBytes() : null; - - byte[] clientIdBytes = clientId != null ? clientId.getBytes() : null; - - byte[] applicationDataBytes = applicationData != null ? applicationData.getBytes() : null; - - int size = calBranchSessionSize(resourceIdBytes, lockKeyBytes, clientIdBytes, applicationDataBytes); - - if (size > MAX_BRANCH_SESSION_SIZE) { - if (lockKeyBytes == null) { - throw new RuntimeException("branch session size exceeded, size : " + size + " maxBranchSessionSize : " - + MAX_BRANCH_SESSION_SIZE); - } - // try compress lockkey - try { - size -= lockKeyBytes.length; - lockKeyBytes = CompressUtil.compress(lockKeyBytes); - } catch (IOException e) { - LOGGER.error("compress lockKey error", e); - } finally { - size += lockKeyBytes.length; - } - - if (size > MAX_BRANCH_SESSION_SIZE) { - throw new RuntimeException( - "compress branch session size exceeded, compressSize : " + size + " maxBranchSessionSize : " - + MAX_BRANCH_SESSION_SIZE); - } - } - - ByteBuffer byteBuffer = byteBufferThreadLocal.get(); - //recycle - byteBuffer.clear(); - - byteBuffer.putLong(transactionId); - byteBuffer.putLong(branchId); - - if (null != resourceIdBytes) { - byteBuffer.putInt(resourceIdBytes.length); - byteBuffer.put(resourceIdBytes); - } else { - byteBuffer.putInt(0); - } - - if (null != lockKeyBytes) { - byteBuffer.putInt(lockKeyBytes.length); - byteBuffer.put(lockKeyBytes); - } else { - byteBuffer.putInt(0); - } - - if (null != clientIdBytes) { - byteBuffer.putShort((short)clientIdBytes.length); - byteBuffer.put(clientIdBytes); - } else { - byteBuffer.putShort((short)0); - } - - if (null != applicationDataBytes) { - byteBuffer.putInt(applicationDataBytes.length); - byteBuffer.put(applicationDataBytes); - } else { - byteBuffer.putInt(0); - } - - byteBuffer.put((byte)status.getCode()); - byteBuffer.flip(); - byte[] result = new byte[byteBuffer.limit()]; - byteBuffer.get(result); - return result; - } - - private int calBranchSessionSize(byte[] resourceIdBytes, byte[] lockKeyBytes, byte[] clientIdBytes, - byte[] applicationDataBytes) { - final int size = 8 // trascationId - + 8 // branchId - + 4 // resourceIdBytes.length - + 4 // lockKeyBytes.length - + 2 // clientIdBytes.length - + 4 // applicationDataBytes.length - + 1 // statusCode - + (resourceIdBytes == null ? 0 : resourceIdBytes.length) - + (lockKeyBytes == null ? 0 : lockKeyBytes.length) - + (clientIdBytes == null ? 0 : clientIdBytes.length) - + (applicationDataBytes == null ? 0 : applicationDataBytes.length); - return size; - } - - @Override - public void decode(byte[] a) { - ByteBuffer byteBuffer = ByteBuffer.wrap(a); - this.transactionId = byteBuffer.getLong(); - this.branchId = byteBuffer.getLong(); - int resourceLen = byteBuffer.getInt(); - if (resourceLen > 0) { - byte[] byResource = new byte[resourceLen]; - byteBuffer.get(byResource); - this.resourceId = new String(byResource); - } - int lockKeyLen = byteBuffer.getInt(); - if (lockKeyLen > 0) { - byte[] byLockKey = new byte[lockKeyLen]; - byteBuffer.get(byLockKey); - if (CompressUtil.isCompressData(byLockKey)) { - try { - this.lockKey = new String(CompressUtil.uncompress(byLockKey)); - } catch (IOException e) { - throw new RuntimeException("uncompress lockKey error", e); - } - } else { - this.lockKey = new String(byLockKey); - } - - } - short clientIdLen = byteBuffer.getShort(); - if (clientIdLen > 0) { - byte[] byClientId = new byte[clientIdLen]; - byteBuffer.get(byClientId); - this.clientId = new String(byClientId); - } - int applicationDataLen = byteBuffer.getInt(); - if (applicationDataLen > 0) { - byte[] byApplicationData = new byte[applicationDataLen]; - byteBuffer.get(byApplicationData); - this.applicationData = new String(byApplicationData); - } - this.status = BranchStatus.get(byteBuffer.get()); - - } - -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/DefaultSessionManager.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/DefaultSessionManager.java deleted file mode 100755 index ff24f7f6b..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/DefaultSessionManager.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import java.util.List; - -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.TransactionWriteStore; - -/** - * The type Default session manager. - * - * @author sharajava - */ -public class DefaultSessionManager extends AbstractSessionManager { - - /** - * Instantiates a new Default session manager. - * - * @param name the name - */ - public DefaultSessionManager(String name) { - super(name); - transactionStoreManager = new TransactionStoreManager() { - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - return true; - } - - @Override - public void shutdown() { - - } - - @Override - public List readWriteStoreFromFile(int readSize, boolean isHistory) { - return null; - } - - @Override - public boolean hasRemaining(boolean isHistory) { - return false; - } - }; - } - - @Override - public void destroy() { - transactionStoreManager.shutdown(); - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/FileBasedSessionManager.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/FileBasedSessionManager.java deleted file mode 100755 index 1684cccdf..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/FileBasedSessionManager.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.model.GlobalStatus; -import io.seata.server.UUIDGenerator; -import io.seata.server.store.FileTransactionStoreManager; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.TransactionWriteStore; - -/** - * The type File based session manager. - * - * @author jimin.jm @alibaba-inc.com - */ -public class FileBasedSessionManager extends AbstractSessionManager implements Reloadable { - - private static final int READ_SIZE = ConfigurationFactory.getInstance().getInt( - ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE, 100); - - /** - * Instantiates a new File based session manager. - * - * @param name the name - * @param sessionStoreFilePath the session store file path - * @throws IOException the io exception - */ - public FileBasedSessionManager(String name, String sessionStoreFilePath) throws IOException { - super(name); - transactionStoreManager = new FileTransactionStoreManager(sessionStoreFilePath + File.separator + name, this); - } - - @Override - public void reload() { - restoreSessions(); - washSessions(); - } - - private void restoreSessions() { - Map unhandledBranchBuffer = new HashMap<>(); - - restoreSessions(true, unhandledBranchBuffer); - restoreSessions(false, unhandledBranchBuffer); - - if (!unhandledBranchBuffer.isEmpty()) { - unhandledBranchBuffer.values().forEach(branchSession -> { - long tid = branchSession.getTransactionId(); - long bid = branchSession.getBranchId(); - GlobalSession found = sessionMap.get(tid); - if (found == null) { - // Ignore - if (LOGGER.isInfoEnabled()) { - LOGGER.info("GlobalSession Does Not Exists For BranchSession [" + bid + "/" + tid + "]"); - } - } else { - BranchSession existingBranch = found.getBranch(branchSession.getBranchId()); - if (existingBranch == null) { - found.add(branchSession); - } else { - existingBranch.setStatus(branchSession.getStatus()); - } - } - - }); - } - } - - private void washSessions() { - if (sessionMap.size() > 0) { - Iterator> iterator = sessionMap.entrySet().iterator(); - while (iterator.hasNext()) { - GlobalSession globalSession = iterator.next().getValue(); - - GlobalStatus globalStatus = globalSession.getStatus(); - switch (globalStatus) { - case UnKnown: - case Committed: - case CommitFailed: - case Rollbacked: - case RollbackFailed: - case TimeoutRollbacked: - case TimeoutRollbackFailed: - case Finished: - // Remove all sessions finished - iterator.remove(); - break; - default: - break; - } - } - } - } - - private void restoreSessions(boolean isHistory, Map unhandledBranchBuffer) { - while (transactionStoreManager.hasRemaining(isHistory)) { - List stores = transactionStoreManager.readWriteStoreFromFile(READ_SIZE, isHistory); - restore(stores, unhandledBranchBuffer); - } - } - - private void restore(List stores, Map unhandledBranchSessions) { - long maxRecoverId = UUIDGenerator.getCurrentUUID(); - for (TransactionWriteStore store : stores) { - TransactionStoreManager.LogOperation logOperation = store.getOperate(); - SessionStorable sessionStorable = store.getSessionRequest(); - maxRecoverId = getMaxId(maxRecoverId, sessionStorable); - switch (logOperation) { - case GLOBAL_ADD: - case GLOBAL_UPDATE: { - GlobalSession globalSession = (GlobalSession)sessionStorable; - long tid = globalSession.getTransactionId(); - GlobalSession foundGlobalSession = sessionMap.get(tid); - if (foundGlobalSession == null) { - sessionMap.put(globalSession.getTransactionId(), globalSession); - } else { - foundGlobalSession.setStatus(globalSession.getStatus()); - } - break; - } - case GLOBAL_REMOVE: { - GlobalSession globalSession = (GlobalSession)sessionStorable; - long tid = globalSession.getTransactionId(); - if (sessionMap.remove(tid) == null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("GlobalSession To Be Removed Does Not Exists [" + tid + "]"); - } - } - break; - } - case BRANCH_ADD: - case BRANCH_UPDATE: { - BranchSession branchSession = (BranchSession)sessionStorable; - long tid = branchSession.getTransactionId(); - GlobalSession foundGlobalSession = sessionMap.get(tid); - if (foundGlobalSession == null) { - unhandledBranchSessions.put(branchSession.getBranchId(), branchSession); - } else { - BranchSession existingBranch = foundGlobalSession.getBranch(branchSession.getBranchId()); - if (existingBranch == null) { - foundGlobalSession.add(branchSession); - } else { - existingBranch.setStatus(branchSession.getStatus()); - } - } - break; - } - case BRANCH_REMOVE: { - BranchSession branchSession = (BranchSession)sessionStorable; - long tid = branchSession.getTransactionId(); - long bid = branchSession.getBranchId(); - GlobalSession found = sessionMap.get(tid); - if (found == null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info( - "GlobalSession To Be Updated (Remove Branch) Does Not Exists [" + bid + "/" + tid - + "]"); - } - } else { - BranchSession theBranch = found.getBranch(bid); - if (theBranch == null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("BranchSession To Be Updated Does Not Exists [" + bid + "/" + tid + "]"); - } - } else { - found.remove(theBranch); - } - } - break; - } - - default: - throw new ShouldNeverHappenException("Unknown Operation: " + logOperation); - - } - } - setMaxId(maxRecoverId); - - } - - private long getMaxId(long maxRecoverId, SessionStorable sessionStorable) { - long currentId = 0; - if (sessionStorable instanceof GlobalSession) { - currentId = ((GlobalSession)sessionStorable).getTransactionId(); - } else if (sessionStorable instanceof BranchSession) { - currentId = ((BranchSession)sessionStorable).getBranchId(); - } - - return maxRecoverId > currentId ? maxRecoverId : currentId; - } - - private void setMaxId(long maxRecoverId) { - long currentId; - // will be recover multi-thread later - while ((currentId = UUIDGenerator.getCurrentUUID()) < maxRecoverId) { - if (UUIDGenerator.setUUID(currentId, maxRecoverId)) { - break; - } - } - } - - private void restore(TransactionWriteStore store) { - } - - @Override - public void destroy() { - transactionStoreManager.shutdown(); - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/GlobalSession.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/GlobalSession.java deleted file mode 100755 index 1c9f31d5b..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/GlobalSession.java +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.server.UUIDGenerator; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.StoreConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * The type Global session. - * - * @author sharajava - */ -public class GlobalSession implements SessionLifecycle, SessionStorable { - - private static final Logger LOGGER = LoggerFactory.getLogger(GlobalSession.class); - - private static final int MAX_GLOBAL_SESSION_SIZE = StoreConfig.getMaxGlobalSessionSize(); - - private static ThreadLocal byteBufferThreadLocal = ThreadLocal.withInitial(() -> ByteBuffer.allocate( - MAX_GLOBAL_SESSION_SIZE)); - - private long transactionId; - - private volatile GlobalStatus status; - - private String applicationId; - - private String transactionServiceGroup; - - private String transactionName; - - private int timeout; - - private long beginTime; - - private boolean active; - - private ArrayList branchSessions = new ArrayList<>(); - - private GlobalSessionLock globalSessionLock = new GlobalSessionLock(); - - /** - * Add boolean. - * - * @param branchSession the branch session - * @return the boolean - */ - public boolean add(BranchSession branchSession) { - return branchSessions.add(branchSession); - } - - /** - * Remove boolean. - * - * @param branchSession the branch session - * @return the boolean - */ - public boolean remove(BranchSession branchSession) { - return branchSessions.remove(branchSession); - } - - private ArrayList lifecycleListeners = new ArrayList<>(); - - /** - * Can be committed async boolean. - * - * @return the boolean - */ - public boolean canBeCommittedAsync() { - for (BranchSession branchSession : branchSessions) { - if (branchSession.getBranchType() == BranchType.TCC) { - return false; - } - } - return true; - } - - /** - * Is timeout boolean. - * - * @return the boolean - */ - public boolean isTimeout() { - return (System.currentTimeMillis() - beginTime) > timeout; - } - - @Override - public void begin() throws TransactionException { - this.status = GlobalStatus.Begin; - this.beginTime = System.currentTimeMillis(); - this.active = true; - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onBegin(this); - } - } - - @Override - public void changeStatus(GlobalStatus status) throws TransactionException { - this.status = status; - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onStatusChange(this, status); - } - - } - - @Override - public void changeBranchStatus(BranchSession branchSession, BranchStatus status) - throws TransactionException { - branchSession.setStatus(status); - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onBranchStatusChange(this, branchSession, status); - } - } - - @Override - public boolean isActive() { - return active; - } - - @Override - public void close() throws TransactionException { - if (active) { - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onClose(this); - } - } - } - - @Override - public void end() throws TransactionException { - // Clean locks first - clean(); - - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onEnd(this); - } - - } - - private void clean() throws TransactionException { - for (BranchSession branchSession : branchSessions) { - branchSession.unlock(); - } - - } - - /** - * Close and clean. - * - * @throws TransactionException the transaction exception - */ - public void closeAndClean() throws TransactionException { - close(); - clean(); - - } - - /** - * Add session lifecycle listener. - * - * @param sessionLifecycleListener the session lifecycle listener - */ - public void addSessionLifecycleListener(SessionLifecycleListener sessionLifecycleListener) { - lifecycleListeners.add(sessionLifecycleListener); - } - - /** - * Remove session lifecycle listener. - * - * @param sessionLifecycleListener the session lifecycle listener - */ - public void removeSessionLifecycleListener(SessionLifecycleListener sessionLifecycleListener) { - lifecycleListeners.remove(sessionLifecycleListener); - } - - @Override - public void addBranch(BranchSession branchSession) throws TransactionException { - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onAddBranch(this, branchSession); - } - branchSession.setStatus(BranchStatus.Registered); - add(branchSession); - } - - @Override - public void removeBranch(BranchSession branchSession) throws TransactionException { - for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { - lifecycleListener.onRemoveBranch(this, branchSession); - } - branchSession.unlock(); - remove(branchSession); - } - - /** - * Gets branch. - * - * @param branchId the branch id - * @return the branch - */ - public BranchSession getBranch(long branchId) { - synchronized (branchSessions) { - for (BranchSession branchSession : branchSessions) { - if (branchSession.getBranchId() == branchId) { - return branchSession; - } - } - - return null; - } - - } - - /** - * Gets sorted branches. - * - * @return the sorted branches - */ - public ArrayList getSortedBranches() { - ArrayList sorted = new ArrayList(); - sorted.addAll(branchSessions); - return sorted; - } - - /** - * Gets reverse sorted branches. - * - * @return the reverse sorted branches - */ - public ArrayList getReverseSortedBranches() { - ArrayList reversed = new ArrayList(); - reversed.addAll(branchSessions); - Collections.reverse(reversed); - return reversed; - } - - /** - * Instantiates a new Global session. - */ - public GlobalSession() {} - - /** - * Instantiates a new Global session. - * - * @param applicationId the application id - * @param transactionServiceGroup the transaction service group - * @param transactionName the transaction name - * @param timeout the timeout - */ - public GlobalSession(String applicationId, String transactionServiceGroup, String transactionName, int timeout) { - this.transactionId = UUIDGenerator.generateUUID(); - this.status = GlobalStatus.Begin; - - this.applicationId = applicationId; - this.transactionServiceGroup = transactionServiceGroup; - this.transactionName = transactionName; - this.timeout = timeout; - } - - /** - * Gets transaction id. - * - * @return the transaction id - */ - public long getTransactionId() { - return transactionId; - } - - /** - * Gets status. - * - * @return the status - */ - public GlobalStatus getStatus() { - return status; - } - - /** - * Sets status. - * - * @param status the status - */ - void setStatus(GlobalStatus status) { - this.status = status; - } - - /** - * Gets application id. - * - * @return the application id - */ - public String getApplicationId() { - return applicationId; - } - - /** - * Gets transaction service group. - * - * @return the transaction service group - */ - public String getTransactionServiceGroup() { - return transactionServiceGroup; - } - - /** - * Gets transaction name. - * - * @return the transaction name - */ - public String getTransactionName() { - return transactionName; - } - - /** - * Gets timeout. - * - * @return the timeout - */ - public int getTimeout() { - return timeout; - } - - /** - * Gets begin time. - * - * @return the begin time - */ - public long getBeginTime() { - return beginTime; - } - - - /** - * Create global session global session. - * - * @param applicationId the application id - * @param txServiceGroup the tx service group - * @param txName the tx name - * @param timeout the timeout - * @return the global session - */ - public static GlobalSession createGlobalSession(String applicationId, String txServiceGroup, String txName, - int timeout) { - GlobalSession session = new GlobalSession(applicationId, txServiceGroup, txName, timeout); - return session; - } - - /** - * Sets active. - * - * @param active the active - */ - public void setActive(boolean active) { - this.active = active; - } - - @Override - public byte[] encode() { - - byte[] byApplicationIdBytes = applicationId != null ? applicationId.getBytes() : null; - - byte[] byServiceGroupBytes = transactionServiceGroup != null ? transactionServiceGroup.getBytes() : null; - - byte[] byTxNameBytes = transactionName != null ? transactionName.getBytes() : null; - - int size = calGlobalSessionSize(byApplicationIdBytes, byServiceGroupBytes, byTxNameBytes); - - if (size > MAX_GLOBAL_SESSION_SIZE) { - throw new RuntimeException("global session size exceeded, size : " + size + " maxBranchSessionSize : " + - MAX_GLOBAL_SESSION_SIZE); - } - ByteBuffer byteBuffer = byteBufferThreadLocal.get(); - //recycle - byteBuffer.clear(); - - byteBuffer.putLong(transactionId); - byteBuffer.putInt(timeout); - if (null != byApplicationIdBytes) { - byteBuffer.putShort((short)byApplicationIdBytes.length); - byteBuffer.put(byApplicationIdBytes); - } else { - byteBuffer.putShort((short)0); - } - if (null != byServiceGroupBytes) { - byteBuffer.putShort((short)byServiceGroupBytes.length); - byteBuffer.put(byServiceGroupBytes); - } else { - byteBuffer.putShort((short)0); - } - if (null != byTxNameBytes) { - byteBuffer.putShort((short)byTxNameBytes.length); - byteBuffer.put(byTxNameBytes); - } else { - byteBuffer.putShort((short)0); - } - byteBuffer.putLong(beginTime); - byteBuffer.put((byte)status.getCode()); - byteBuffer.flip(); - byte[] result = new byte[byteBuffer.limit()]; - byteBuffer.get(result); - return result; - } - - private int calGlobalSessionSize(byte[] byApplicationIdBytes, byte[] byServiceGroupBytes, byte[] byTxNameBytes) { - final int size = 8 // trascationId - + 4 // timeout - + 2 // byApplicationIdBytes.length - + 2 // byServiceGroupBytes.length - + 2 // byTxNameBytes.length - + 8 // beginTime - + 1 // statusCode - + (byApplicationIdBytes == null ? 0 : byApplicationIdBytes.length) - + (byServiceGroupBytes == null ? 0 : byServiceGroupBytes.length) - + (byTxNameBytes == null ? 0 : byTxNameBytes.length); - return size; - } - - @Override - public void decode(byte[] a) { - ByteBuffer byteBuffer = ByteBuffer.wrap(a); - this.transactionId = byteBuffer.getLong(); - this.timeout = byteBuffer.getInt(); - short applicationIdLen = byteBuffer.getShort(); - if (applicationIdLen > 0) { - byte[] byApplicationId = new byte[applicationIdLen]; - byteBuffer.get(byApplicationId); - this.applicationId = new String(byApplicationId); - } - short serviceGroupLen = byteBuffer.getShort(); - if (serviceGroupLen > 0) { - byte[] byServiceGroup = new byte[serviceGroupLen]; - byteBuffer.get(byServiceGroup); - this.transactionServiceGroup = new String(byServiceGroup); - } - short txNameLen = byteBuffer.getShort(); - if (txNameLen > 0) { - byte[] byTxName = new byte[txNameLen]; - byteBuffer.get(byTxName); - this.transactionName = new String(byTxName); - } - this.beginTime = byteBuffer.getLong(); - this.status = GlobalStatus.get(byteBuffer.get()); - } - - /** - * Has branch boolean. - * - * @return the boolean - */ - public boolean hasBranch() { - return branchSessions.size() > 0; - } - - public void lock() throws TransactionException { - globalSessionLock.lock(); - } - - public void unlock(){ - globalSessionLock.unlock(); - } - - public void lockAndExcute(LockRunnable excuteRunnable) throws TransactionException{ - this.lock(); - try { - excuteRunnable.run(); - }finally { - this.unlock(); - } - } - - public T lockAndExcute(LockCallable lockCallable) throws TransactionException{ - this.lock(); - try { - return lockCallable.call(); - }finally { - this.unlock(); - } - } - - private class GlobalSessionLock { - - private Lock globalSessionLock = new ReentrantLock(); - - private static final int GLOBAL_SESSOION_LOCK_TIME_OUT_MILLS = 2 * 1000; - - public void lock() throws TransactionException { - try { - if (globalSessionLock.tryLock(GLOBAL_SESSOION_LOCK_TIME_OUT_MILLS, TimeUnit.MILLISECONDS)){ - return; - } - } catch (InterruptedException e) { - LOGGER.error("Interrupted error", e); - } - throw new TransactionException(TransactionExceptionCode.FailedLockGlobalTranscation); - } - - - public void unlock() { - globalSessionLock.unlock(); - } - - } - - @FunctionalInterface - public interface LockRunnable { - - void run() throws TransactionException; - } - @FunctionalInterface - public interface LockCallable { - - V call() throws TransactionException; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Lockable.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Lockable.java deleted file mode 100755 index d023e632f..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Lockable.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; - -/** - * The interface Lockable. - * - * @author sharajava - */ -public interface Lockable { - - /** - * Lock boolean. - * - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean lock() throws TransactionException; - - /** - * Unlock boolean. - * - * @return the boolean - * @throws TransactionException the transaction exception - */ - boolean unlock() throws TransactionException; -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Reloadable.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Reloadable.java deleted file mode 100755 index 5701c69d6..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Reloadable.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -/** - * Service contains states which can be reloaded. - * - * @author sharajava - */ -public interface Reloadable { - - /** - * Reload states. - */ - void reload(); -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionCondition.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionCondition.java deleted file mode 100755 index 4063d7aa3..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionCondition.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -/** - * The type Session condition. - * - * @author jimin.jm @alibaba-inc.com - * @date 2018 /12/13 - */ -public class SessionCondition { - - private long overTimeAliveMills; - - /** - * Instantiates a new Session condition. - * - * @param overTimeAliveMills the over time alive mills - */ - public SessionCondition( long overTimeAliveMills) { - this.overTimeAliveMills = overTimeAliveMills; - } - - - /** - * Gets over time alive mills. - * - * @return the over time alive mills - */ - public long getOverTimeAliveMills() { - return overTimeAliveMills; - } - - /** - * Sets over time alive mills. - * - * @param overTimeAliveMills the over time alive mills - */ - public void setOverTimeAliveMills(long overTimeAliveMills) { - this.overTimeAliveMills = overTimeAliveMills; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHelper.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHelper.java deleted file mode 100755 index b3295d24e..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHelper.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.server.UUIDGenerator; - -/** - * The type Session helper. - * - * @author sharajava - */ -public class SessionHelper { - - private SessionHelper() {} - - public static BranchSession newBranchByGlobal(GlobalSession globalSession, BranchType branchType, String resourceId, String lockKeys, String clientId) { - return newBranchByGlobal(globalSession, branchType, resourceId, null, lockKeys, clientId); - } - - /** - * New branch by global branch session. - * - * @param globalSession the global session - * @param branchType the branch type - * @param resourceId the resource id - * @param lockKeys the lock keys - * @param clientId the client id - * @return the branch session - */ - public static BranchSession newBranchByGlobal(GlobalSession globalSession, BranchType branchType, String resourceId, - String applicationData, String lockKeys, String clientId) { - BranchSession branchSession = new BranchSession(); - - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setBranchType(branchType); - branchSession.setResourceId(resourceId); - branchSession.setLockKey(lockKeys); - branchSession.setClientId(clientId); - branchSession.setApplicationData(applicationData); - - return branchSession; - } - - /** - * End committed. - * - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - public static void endCommitted(GlobalSession globalSession) throws TransactionException { - globalSession.changeStatus(GlobalStatus.Committed); - globalSession.end(); - } - - /** - * End commit failed. - * - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - public static void endCommitFailed(GlobalSession globalSession) throws TransactionException { - globalSession.changeStatus(GlobalStatus.CommitFailed); - globalSession.end(); - } - - /** - * End rollbacked. - * - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - public static void endRollbacked(GlobalSession globalSession) throws TransactionException { - GlobalStatus currentStatus = globalSession.getStatus(); - if (isTimeoutGlobalStatus(currentStatus)) { - globalSession.changeStatus(GlobalStatus.TimeoutRollbacked); - } else { - globalSession.changeStatus(GlobalStatus.Rollbacked); - } - globalSession.end(); - } - - /** - * End rollback failed. - * - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - public static void endRollbackFailed(GlobalSession globalSession) throws TransactionException { - GlobalStatus currentStatus = globalSession.getStatus(); - if (isTimeoutGlobalStatus(currentStatus)) { - globalSession.changeStatus(GlobalStatus.TimeoutRollbackFailed); - } else { - globalSession.changeStatus(GlobalStatus.RollbackFailed); - } - globalSession.end(); - } - - public static boolean isTimeoutGlobalStatus(GlobalStatus status) { - return status == GlobalStatus.TimeoutRollbacked - || status == GlobalStatus.TimeoutRollbackFailed - || status == GlobalStatus.TimeoutRollbacking - || status == GlobalStatus.TimeoutRollbackRetrying; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHolder.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHolder.java deleted file mode 100755 index a46e7001d..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHolder.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.exception.StoreException; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.StoreMode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; - -/** - * The type Session holder. - * - * @author sharajava - */ -public class SessionHolder { - - private static final Logger LOGGER = LoggerFactory.getLogger(SessionHolder.class); - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The constant ROOT_SESSION_MANAGER_NAME. - */ - public static final String ROOT_SESSION_MANAGER_NAME = "root.data"; - /** - * The constant ASYNC_COMMITTING_SESSION_MANAGER_NAME. - */ - public static final String ASYNC_COMMITTING_SESSION_MANAGER_NAME = "async.commit.data"; - /** - * The constant RETRY_COMMITTING_SESSION_MANAGER_NAME. - */ - public static final String RETRY_COMMITTING_SESSION_MANAGER_NAME = "retry.commit.data"; - /** - * The constant RETRY_ROLLBACKING_SESSION_MANAGER_NAME. - */ - public static final String RETRY_ROLLBACKING_SESSION_MANAGER_NAME = "retry.rollback.data"; - - private static SessionManager ROOT_SESSION_MANAGER; - private static SessionManager ASYNC_COMMITTING_SESSION_MANAGER; - private static SessionManager RETRY_COMMITTING_SESSION_MANAGER; - private static SessionManager RETRY_ROLLBACKING_SESSION_MANAGER; - - /** - * Init. - * - * @param mode the store mode: file、db - * @throws IOException the io exception - */ - public static void init(String mode) throws IOException { - if (StringUtils.isBlank(mode)) { - //use default - mode = CONFIG.getConfig(ConfigurationKeys.STORE_MODE); - } - //the store mode - StoreMode storeMode = StoreMode.valueof(mode); - if (StoreMode.DB.equals(storeMode)) { - //TODO database store - - } else if (StoreMode.FILE.equals(storeMode)) { - //file store - String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR); - if (sessionStorePath == null) { - throw new StoreException("the {store.file.dir} is empty."); - } - ROOT_SESSION_MANAGER = new FileBasedSessionManager(ROOT_SESSION_MANAGER_NAME, sessionStorePath); - ASYNC_COMMITTING_SESSION_MANAGER = new DefaultSessionManager(ASYNC_COMMITTING_SESSION_MANAGER_NAME); - RETRY_COMMITTING_SESSION_MANAGER = new DefaultSessionManager(RETRY_COMMITTING_SESSION_MANAGER_NAME); - RETRY_ROLLBACKING_SESSION_MANAGER = new DefaultSessionManager(RETRY_ROLLBACKING_SESSION_MANAGER_NAME); - } else { - //unknown store - throw new IllegalArgumentException("unknown store mode:" + mode); - } - - if (ROOT_SESSION_MANAGER instanceof Reloadable) { - ((Reloadable) ROOT_SESSION_MANAGER).reload(); - - Collection reloadedSessions = ROOT_SESSION_MANAGER.allSessions(); - if (reloadedSessions != null && !reloadedSessions.isEmpty()) { - reloadedSessions.forEach(globalSession -> { - GlobalStatus globalStatus = globalSession.getStatus(); - switch (globalStatus) { - case UnKnown: - case Committed: - case CommitFailed: - case Rollbacked: - case RollbackFailed: - case TimeoutRollbacked: - case TimeoutRollbackFailed: - case Finished: - throw new ShouldNeverHappenException("Reloaded Session should NOT be " + globalStatus); - case AsyncCommitting: - try { - globalSession.addSessionLifecycleListener(getAsyncCommittingSessionManager()); - getAsyncCommittingSessionManager().addGlobalSession(globalSession); - } catch (TransactionException e) { - throw new ShouldNeverHappenException(e); - } - break; - default: { - ArrayList branchSessions = globalSession.getSortedBranches(); - // Lock - branchSessions.forEach(branchSession -> { - try { - branchSession.lock(); - } catch (TransactionException e) { - throw new ShouldNeverHappenException(e); - } - }); - - switch (globalStatus) { - case Committing: - case CommitRetrying: - try { - globalSession.addSessionLifecycleListener( - getRetryCommittingSessionManager()); - getRetryCommittingSessionManager().addGlobalSession(globalSession); - } catch (TransactionException e) { - throw new ShouldNeverHappenException(e); - } - break; - case Rollbacking: - case RollbackRetrying: - case TimeoutRollbacking: - case TimeoutRollbackRetrying: - try { - globalSession.addSessionLifecycleListener( - getRetryRollbackingSessionManager()); - getRetryRollbackingSessionManager().addGlobalSession(globalSession); - } catch (TransactionException e) { - throw new ShouldNeverHappenException(e); - } - break; - case Begin: - globalSession.setActive(true); - break; - default: - throw new ShouldNeverHappenException("NOT properly handled " + globalStatus); - } - - break; - - } - } - - }); - } - } - - } - - /** - * Gets root session manager. - * - * @return the root session manager - */ - public static final SessionManager getRootSessionManager() { - if (ROOT_SESSION_MANAGER == null) { - throw new ShouldNeverHappenException("SessionManager is NOT init!"); - } - return ROOT_SESSION_MANAGER; - } - - /** - * Gets async committing session manager. - * - * @return the async committing session manager - */ - public static final SessionManager getAsyncCommittingSessionManager() { - if (ASYNC_COMMITTING_SESSION_MANAGER == null) { - throw new ShouldNeverHappenException("SessionManager is NOT init!"); - } - return ASYNC_COMMITTING_SESSION_MANAGER; - } - - /** - * Gets retry committing session manager. - * - * @return the retry committing session manager - */ - public static final SessionManager getRetryCommittingSessionManager() { - if (RETRY_COMMITTING_SESSION_MANAGER == null) { - throw new ShouldNeverHappenException("SessionManager is NOT init!"); - } - return RETRY_COMMITTING_SESSION_MANAGER; - } - - /** - * Gets retry rollbacking session manager. - * - * @return the retry rollbacking session manager - */ - public static final SessionManager getRetryRollbackingSessionManager() { - if (RETRY_ROLLBACKING_SESSION_MANAGER == null) { - throw new ShouldNeverHappenException("SessionManager is NOT init!"); - } - return RETRY_ROLLBACKING_SESSION_MANAGER; - } - - /** - * Find global session. - * - * @param transactionId the transaction id - * @return the global session - */ - public static GlobalSession findGlobalSession(Long transactionId) { - return getRootSessionManager().findGlobalSession(transactionId); - } - - public static void destory() { - ROOT_SESSION_MANAGER.destroy(); - ASYNC_COMMITTING_SESSION_MANAGER.destroy(); - RETRY_COMMITTING_SESSION_MANAGER.destroy(); - RETRY_ROLLBACKING_SESSION_MANAGER.destroy(); - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycle.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycle.java deleted file mode 100755 index 9c46a2fd7..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycle.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; - -/** - * The interface Session lifecycle. - * - * @author sharajava - */ -public interface SessionLifecycle { - - /** - * Begin. - * - * @throws TransactionException the transaction exception - */ - void begin() throws TransactionException; - - /** - * Change status. - * - * @param status the status - * @throws TransactionException the transaction exception - */ - void changeStatus(GlobalStatus status) throws TransactionException; - - /** - * Change branch status. - * - * @param branchSession the branch session - * @param status the status - * @throws TransactionException the transaction exception - */ - void changeBranchStatus(BranchSession branchSession, BranchStatus status) throws TransactionException; - - /** - * Add branch. - * - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void addBranch(BranchSession branchSession) throws TransactionException; - - /** - * Remove branch. - * - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void removeBranch(BranchSession branchSession) throws TransactionException; - - /** - * Is active boolean. - * - * @return the boolean - */ - boolean isActive(); - - /** - * Close. - * - * @throws TransactionException the transaction exception - */ - void close() throws TransactionException; - - /** - * End. - * - * @throws TransactionException the transaction exception - */ - void end() throws TransactionException; -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycleListener.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycleListener.java deleted file mode 100755 index 54c415e92..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycleListener.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; - -/** - * The interface Session lifecycle listener. - * - * @author sharajava - */ -public interface SessionLifecycleListener { - - /** - * On begin. - * - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void onBegin(GlobalSession globalSession) throws TransactionException; - - /** - * On status change. - * - * @param globalSession the global session - * @param status the status - * @throws TransactionException the transaction exception - */ - void onStatusChange(GlobalSession globalSession, GlobalStatus status) throws TransactionException; - - /** - * On branch status change. - * - * @param globalSession the global session - * @param branchSession the branch session - * @param status the status - * @throws TransactionException the transaction exception - */ - void onBranchStatusChange(GlobalSession globalSession, BranchSession branchSession, BranchStatus status) - throws TransactionException; - - /** - * On add branch. - * - * @param globalSession the global session - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void onAddBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - - /** - * On remove branch. - * - * @param globalSession the global session - * @param branchSession the branch session - * @throws TransactionException the transaction exception - */ - void onRemoveBranch(GlobalSession globalSession, BranchSession branchSession) throws TransactionException; - - /** - * On close. - * - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void onClose(GlobalSession globalSession) throws TransactionException; - - /** - * On end. - * - * @param globalSession the global session - * @throws TransactionException the transaction exception - */ - void onEnd(GlobalSession globalSession) throws TransactionException; -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionManager.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionManager.java deleted file mode 100755 index 2883d4404..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionManager.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session; - -import java.util.Collection; -import java.util.List; - -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.core.rpc.Disposable; - -/** - * The interface Session manager. - * - * @author sharajava - */ -public interface SessionManager extends SessionLifecycleListener, Disposable { - - /** - * Add global session. - * - * @param session the session - * @throws TransactionException the transaction exception - */ - void addGlobalSession(GlobalSession session) throws TransactionException; - - /** - * Find global session global session. - * - * @param transactionId the transaction id - * @return the global session - * @throws TransactionException the transaction exception - */ - GlobalSession findGlobalSession(Long transactionId); - - /** - * Update global session status. - * - * @param session the session - * @param status the status - * @throws TransactionException the transaction exception - */ - void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException; - - /** - * Remove global session. - * - * @param session the session - * @throws TransactionException the transaction exception - */ - void removeGlobalSession(GlobalSession session) throws TransactionException; - - /** - * Add branch session. - * - * @param globalSession the global session - * @param session the session - * @throws TransactionException the transaction exception - */ - void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException; - - /** - * Update branch session status. - * - * @param session the session - * @param status the status - * @throws TransactionException the transaction exception - */ - void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException; - - /** - * Remove branch session. - * - * @param globalSession the global session - * @param session the session - * @throws TransactionException the transaction exception - */ - void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException; - - /** - * All sessions collection. - * - * @return the collection - */ - Collection allSessions(); - - /** - * Find global sessions list. - * - * @param condition the condition - * @return the list - */ - List findGlobalSessions(SessionCondition condition); - -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java deleted file mode 100755 index 9b3a32229..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.CollectionUtils; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.session.SessionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.ReentrantLock; - -/** - * The type File transaction store manager. - * - * @author jimin.jm @alibaba-inc.com - */ -public class FileTransactionStoreManager implements TransactionStoreManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(FileTransactionStoreManager.class); - - private static final int MAX_THREAD_WRITE = 1; - - private ExecutorService fileWriteExecutor; - - private volatile boolean stopping = false; - - private static final int MAX_SHUTDOWN_RETRY = 3; - - private static final int SHUTDOWN_CHECK_INTERNAL = 1 * 1000; - - private static final int MAX_WRITE_RETRY = 5; - - private static final String HIS_DATA_FILENAME_POSTFIX = ".1"; - - private static final AtomicLong FILE_TRX_NUM = new AtomicLong(0); - - private static final AtomicLong FILE_FLUSH_NUM = new AtomicLong(0); - - private static final int MARK_SIZE = 4; - - private static final int MAX_WAIT_TIME_MILLS = 2 * 1000; - - private static final int MAX_FLUSH_TIME_MILLS = 2 * 1000; - - private static final int MAX_FLUSH_NUM = 10; - - private static int PER_FILE_BLOCK_SIZE = 65535 * 8; - - private static long MAX_TRX_TIMEOUT_MILLS = 30 * 60 * 1000; - - private static volatile long trxStartTimeMills = System.currentTimeMillis(); - - private File currDataFile; - - private RandomAccessFile currRaf; - - private FileChannel currFileChannel; - - private long recoverCurrOffset = 0; - - private long recoverHisOffset = 0; - - private SessionManager sessionManager; - - private String currFullFileName; - - private String hisFullFileName; - - private WriteDataFileRunnable writeDataFileRunnable; - - private ReentrantLock writeSessionLock = new ReentrantLock(); - - private volatile long lastModifiedTime; - - private static final int MAX_WRITE_BUFFER_SIZE = StoreConfig.getFileWriteBufferCacheSize(); - - private final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(MAX_WRITE_BUFFER_SIZE); - - private static final FlushDiskMode FLUSH_DISK_MODE = StoreConfig.getFlushDiskMode(); - - private static final int MAX_WAIT_FOR_FLUSH_TIME_MILLS = 2 * 1000; - - private static final int INT_BYTE_SIZE = 4; - - /** - * Instantiates a new File transaction store manager. - * - * @param fullFileName the dir path - * @param sessionManager the session manager - * @throws IOException the io exception - */ - public FileTransactionStoreManager(String fullFileName, SessionManager sessionManager) throws IOException { - initFile(fullFileName); - fileWriteExecutor = - new ThreadPoolExecutor(MAX_THREAD_WRITE, MAX_THREAD_WRITE, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(), - new NamedThreadFactory("fileTransactionStore", MAX_THREAD_WRITE, true)); - writeDataFileRunnable = new WriteDataFileRunnable(); - fileWriteExecutor.submit(writeDataFileRunnable); - this.sessionManager = sessionManager; - } - - private void initFile(String fullFileName) throws IOException { - this.currFullFileName = fullFileName; - this.hisFullFileName = fullFileName + HIS_DATA_FILENAME_POSTFIX; - try { - currDataFile = new File(currFullFileName); - if (!currDataFile.exists()) { - //create parent dir first - if (currDataFile.getParentFile() != null && !currDataFile.getParentFile().exists()) { - currDataFile.getParentFile().mkdirs(); - } - currDataFile.createNewFile(); - trxStartTimeMills = System.currentTimeMillis(); - } else { - trxStartTimeMills = currDataFile.lastModified(); - } - lastModifiedTime = System.currentTimeMillis(); - currRaf = new RandomAccessFile(currDataFile, "rw"); - currRaf.seek(currDataFile.length()); - currFileChannel = currRaf.getChannel(); - } catch (IOException exx) { - LOGGER.error("init file error," + exx.getMessage()); - throw exx; - } - } - - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - writeSessionLock.lock(); - long curFileTrxNum; - try { - if (!writeDataFile(new TransactionWriteStore(session, logOperation).encode())) { - return false; - } - lastModifiedTime = System.currentTimeMillis(); - curFileTrxNum = FILE_TRX_NUM.incrementAndGet(); - if (curFileTrxNum % PER_FILE_BLOCK_SIZE == 0 && - (System.currentTimeMillis() - trxStartTimeMills) > MAX_TRX_TIMEOUT_MILLS) { - return saveHistory(); - } - } catch (Exception exx) { - LOGGER.error("writeSession error," + exx.getMessage()); - return false; - } finally { - writeSessionLock.unlock(); - } - flushDisk(curFileTrxNum, currFileChannel); - return true; - } - - private void flushDisk(long curFileNum, FileChannel currFileChannel) { - - if (FLUSH_DISK_MODE == FlushDiskMode.SYNC_MODEL) { - SyncFlushRequest syncFlushRequest = new SyncFlushRequest(curFileNum, currFileChannel); - writeDataFileRunnable.putRequest(syncFlushRequest); - syncFlushRequest.waitForFlush(MAX_WAIT_FOR_FLUSH_TIME_MILLS); - } else { - writeDataFileRunnable.putRequest(new AsyncFlushRequest(curFileNum, currFileChannel)); - } - } - - /** - * get all overTimeSessionStorables - * merge write file - * - * @throws IOException - */ - private boolean saveHistory() throws IOException { - boolean result; - try { - result = findTimeoutAndSave(); - writeDataFileRunnable.putRequest(new CloseFileRequest(currFileChannel, currRaf)); - Files.move(currDataFile.toPath(), new File(hisFullFileName).toPath(), StandardCopyOption.REPLACE_EXISTING); - } catch (IOException exx) { - LOGGER.error("save history data file error," + exx.getMessage()); - result = false; - } finally { - initFile(currFullFileName); - } - return result; - } - - private boolean findTimeoutAndSave() throws IOException { - List globalSessionsOverMaxTimeout = - sessionManager.findGlobalSessions(new SessionCondition(MAX_TRX_TIMEOUT_MILLS)); - if (CollectionUtils.isEmpty(globalSessionsOverMaxTimeout)) { - return true; - } - List listBytes = new ArrayList<>(); - int totalSize = 0; - // 1. find all data and merge - for (GlobalSession globalSession : globalSessionsOverMaxTimeout) { - TransactionWriteStore globalWriteStore = new TransactionWriteStore(globalSession, LogOperation.GLOBAL_ADD); - byte[] data = globalWriteStore.encode(); - listBytes.add(data); - totalSize += data.length + INT_BYTE_SIZE; - List branchSessIonsOverMaXTimeout = globalSession.getSortedBranches(); - if (null != branchSessIonsOverMaXTimeout) { - for (BranchSession branchSession : branchSessIonsOverMaXTimeout) { - TransactionWriteStore branchWriteStore = - new TransactionWriteStore(branchSession, LogOperation.BRANCH_ADD); - data = branchWriteStore.encode(); - listBytes.add(data); - totalSize += data.length + INT_BYTE_SIZE; - } - } - } - // 2. batch write - ByteBuffer byteBuffer = ByteBuffer.allocateDirect(totalSize); - for (byte[] bytes : listBytes) { - byteBuffer.putInt(bytes.length); - byteBuffer.put(bytes); - } - if (writeDataFileByBuffer(byteBuffer)) { - currFileChannel.force(false); - return true; - } - return false; - } - - @Override - public void shutdown() { - if (null != fileWriteExecutor) { - fileWriteExecutor.shutdown(); - stopping = true; - int retry = 0; - while (!fileWriteExecutor.isTerminated() && retry < MAX_SHUTDOWN_RETRY) { - ++retry; - try { - Thread.sleep(SHUTDOWN_CHECK_INTERNAL); - } catch (InterruptedException exx) { - } - } - if (retry >= MAX_SHUTDOWN_RETRY) { - fileWriteExecutor.shutdownNow(); - } - } - try { - currFileChannel.force(true); - } catch (IOException e) { - LOGGER.error("filechannel force error", e); - } - closeFile(currRaf); - } - - @Override - public List readWriteStoreFromFile(int readSize, boolean isHistory) { - File file = null; - long currentOffset = 0; - if (isHistory) { - file = new File(hisFullFileName); - currentOffset = recoverHisOffset; - } else { - file = new File(currFullFileName); - currentOffset = recoverCurrOffset; - } - if (file.exists()) { - return parseDataFile(file, readSize, currentOffset); - } - return null; - } - - @Override - public boolean hasRemaining(boolean isHistory) { - File file = null; - RandomAccessFile raf = null; - long currentOffset = 0; - if (isHistory) { - file = new File(hisFullFileName); - currentOffset = recoverHisOffset; - } else { - file = new File(currFullFileName); - currentOffset = recoverCurrOffset; - } - try { - raf = new RandomAccessFile(file, "r"); - return currentOffset < raf.length(); - - } catch (IOException exx) { - } finally { - closeFile(raf); - } - return false; - } - - private List parseDataFile(File file, int readSize, long currentOffset) { - List transactionWriteStores = new ArrayList<>(readSize); - RandomAccessFile raf = null; - FileChannel fileChannel = null; - try { - raf = new RandomAccessFile(file, "r"); - raf.seek(currentOffset); - fileChannel = raf.getChannel(); - fileChannel.position(currentOffset); - long size = raf.length(); - ByteBuffer buffSize = ByteBuffer.allocate(MARK_SIZE); - while (fileChannel.position() < size) { - try { - buffSize.clear(); - int avilReadSize = fileChannel.read(buffSize); - if (avilReadSize != MARK_SIZE) { - break; - } - buffSize.flip(); - int bodySize = buffSize.getInt(); - byte[] byBody = new byte[bodySize]; - ByteBuffer buffBody = ByteBuffer.wrap(byBody); - avilReadSize = fileChannel.read(buffBody); - if (avilReadSize != bodySize) { - break; - } - TransactionWriteStore writeStore = new TransactionWriteStore(); - writeStore.decode(byBody); - transactionWriteStores.add(writeStore); - if (transactionWriteStores.size() == readSize) { - break; - } - } catch (Exception ex) { - LOGGER.error("decode data file error:" + ex.getMessage()); - break; - } - } - return transactionWriteStores; - } catch (IOException exx) { - LOGGER.error("parse data file error:" + exx.getMessage() + ",file:" + file.getName()); - return null; - } finally { - try { - if (null != fileChannel) { - if (isHisFile(file)) { - recoverHisOffset = fileChannel.position(); - } else { - recoverCurrOffset = fileChannel.position(); - } - } - closeFile(raf); - } catch (IOException exx) { - LOGGER.error("file close error," + exx.getMessage()); - } - } - - } - - private boolean isHisFile(File file) { - - return file.getName().endsWith(HIS_DATA_FILENAME_POSTFIX); - } - - private void closeFile(RandomAccessFile raf) { - try { - if (null != raf) { - raf.close(); - raf = null; - } - } catch (IOException exx) { - LOGGER.error("file close error," + exx.getMessage()); - } - } - - private boolean writeDataFile(byte[] bs) { - if (bs == null) { - return false; - } - ByteBuffer byteBuffer = null; - - if (bs.length > MAX_WRITE_BUFFER_SIZE) { - //allocateNew - byteBuffer = ByteBuffer.allocateDirect(bs.length); - } else { - byteBuffer = writeBuffer; - //recycle - byteBuffer.clear(); - } - - byteBuffer.putInt(bs.length); - byteBuffer.put(bs); - return writeDataFileByBuffer(byteBuffer); - } - - private boolean writeDataFileByBuffer(ByteBuffer byteBuffer) { - byteBuffer.flip(); - for (int retry = 0; retry < MAX_WRITE_RETRY; retry++) { - try { - while (byteBuffer.hasRemaining()) { - currFileChannel.write(byteBuffer); - } - return true; - } catch (IOException exx) { - LOGGER.error("write data file error:" + exx.getMessage()); - } - } - LOGGER.error("write dataFile failed,retry more than :" + MAX_WRITE_RETRY); - return false; - } - - interface StoreRequest { - - } - abstract class AbstractFlushRequest implements StoreRequest{ - private final long curFileTrxNum; - - private final FileChannel curFileChannel; - - protected AbstractFlushRequest(long curFileTrxNum, FileChannel curFileChannel) { - this.curFileTrxNum = curFileTrxNum; - this.curFileChannel = curFileChannel; - } - public long getCurFileTrxNum() { - return curFileTrxNum; - } - - public FileChannel getCurFileChannel() { - return curFileChannel; - } - } - class SyncFlushRequest extends AbstractFlushRequest { - - private final CountDownLatch countDownLatch = new CountDownLatch(1); - - public SyncFlushRequest(long curFileTrxNum, FileChannel curFileChannel) { - super(curFileTrxNum, curFileChannel); - } - - - public void wakeupCustomer() { - this.countDownLatch.countDown(); - } - - public void waitForFlush(long timeout) { - try { - this.countDownLatch.await(timeout, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - LOGGER.error("Interrupted", e); - } - } - } - - class AsyncFlushRequest extends AbstractFlushRequest { - - public AsyncFlushRequest(long curFileTrxNum, FileChannel curFileChannel) { - super(curFileTrxNum, curFileChannel); - } - - } - - class CloseFileRequest implements StoreRequest { - - private FileChannel fileChannel; - - private RandomAccessFile file; - - public CloseFileRequest(FileChannel fileChannel, RandomAccessFile file) { - this.fileChannel = fileChannel; - this.file = file; - } - - public FileChannel getFileChannel() { - return fileChannel; - } - - public RandomAccessFile getFile() { - return file; - } - } - - /** - * The type Write data file runnable. - */ - class WriteDataFileRunnable implements Runnable { - - private LinkedBlockingQueue storeRequests = new LinkedBlockingQueue<>(); - - - public void putRequest(final StoreRequest request) { - storeRequests.add(request); - } - - - @Override - public void run() { - while (!stopping) { - try { - StoreRequest storeRequest = storeRequests.poll(MAX_WAIT_TIME_MILLS, TimeUnit.MILLISECONDS); - handleStoreRequest(storeRequest); - } catch (Exception exx) { - LOGGER.error("write file error", exx.getMessage()); - } - } - handleRestRequest(); - } - - /** - * handle the rest requests when stopping is true - */ - private void handleRestRequest() { - int remainNums = storeRequests.size(); - for (int i = 0; i < remainNums; i++) { - handleStoreRequest(storeRequests.poll()); - } - } - - private void handleStoreRequest(StoreRequest storeRequest) { - if (storeRequest == null){ - flushOnCondition(currFileChannel); - } - if (storeRequest instanceof SyncFlushRequest) { - syncFlush((SyncFlushRequest) storeRequest); - } else if (storeRequest instanceof AsyncFlushRequest) { - async((AsyncFlushRequest) storeRequest); - } else if (storeRequest instanceof CloseFileRequest) { - closeAndFlush((CloseFileRequest) storeRequest); - } - } - - private void closeAndFlush(CloseFileRequest req) { - long diff = FILE_TRX_NUM.get() - FILE_FLUSH_NUM.get(); - flush(req.getFileChannel()); - FILE_FLUSH_NUM.addAndGet(diff); - closeFile(currRaf); - } - - private void async(AsyncFlushRequest req) { - if (req.getCurFileTrxNum() < FILE_FLUSH_NUM.get()) { - flushOnCondition(req.getCurFileChannel()); - } - } - - private void syncFlush(SyncFlushRequest req) { - if (req.getCurFileTrxNum() < FILE_FLUSH_NUM.get()) { - long diff = FILE_TRX_NUM.get() - FILE_FLUSH_NUM.get(); - flush(req.getCurFileChannel()); - FILE_FLUSH_NUM.addAndGet(diff); - } - // notify - req.wakeupCustomer(); - } - - private void flushOnCondition(FileChannel fileChannel) { - if (FLUSH_DISK_MODE == FlushDiskMode.SYNC_MODEL) { - return; - } - long diff = FILE_TRX_NUM.get() - FILE_FLUSH_NUM.get(); - if (diff == 0) { - return; - } - if (diff % MAX_FLUSH_NUM == 0 || - System.currentTimeMillis() - lastModifiedTime > MAX_FLUSH_TIME_MILLS) { - flush(fileChannel); - FILE_FLUSH_NUM.addAndGet(diff); - } - } - - private void flush(FileChannel fileChannel) { - try { - fileChannel.force(false); - } catch (IOException exx) { - LOGGER.error("flush error:" + exx.getMessage()); - } - } - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FlushDiskMode.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FlushDiskMode.java deleted file mode 100755 index 34f9ba331..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FlushDiskMode.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -/** - * - * @author lizhao - */ -public enum FlushDiskMode { - /** - * sync flush disk - */ - SYNC_MODEL("sync"), - /** - * async flush disk - */ - ASYNC_MODEL("async"); - - private String modeStr; - - FlushDiskMode(String modeStr) { - this.modeStr = modeStr; - } - - public static FlushDiskMode findDiskMode(String modeStr) { - if (SYNC_MODEL.modeStr.equals(modeStr)){ - return SYNC_MODEL; - } - return ASYNC_MODEL; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/SessionStorable.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/SessionStorable.java deleted file mode 100755 index 23b5dce75..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/SessionStorable.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -/** - * The interface Session storable. - * - * @author jimin.jm @alibaba-inc.com - */ -public interface SessionStorable { - - /** - * Encode byte [ ]. - * - * @return the byte [ ] - */ - byte[] encode(); - - /** - * Decode. - * - * @param src the src - */ - void decode(byte[] src); -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/StoreConfig.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/StoreConfig.java deleted file mode 100755 index 37e2b0f3b..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/StoreConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; - -import static io.seata.core.constants.ConfigurationKeys.STORE_FILE_PREFIX; - - -/** - * @author lizhao - */ -public class StoreConfig { - - private static final Configuration CONFIGURATION = ConfigurationFactory.getInstance(); - - - // default 16kb - private static final int DEFAULT_MAX_BRANCH_SESSION_SIZE = 1024 * 16; - - // default 512b - private static final int DEFAULT_MAX_GLOBAL_SESSION_SIZE = 512; - - // default 16kb - private static final int DEFAULT_WRITE_BUFFER_SIZE = 1024 * 16; - - public static int getMaxBranchSessionSize() { - return CONFIGURATION.getInt(STORE_FILE_PREFIX + "max-branch-session-size", DEFAULT_MAX_BRANCH_SESSION_SIZE); - } - - public static int getMaxGlobalSessionSize() { - return CONFIGURATION.getInt(STORE_FILE_PREFIX + "max-global-session-size", DEFAULT_MAX_GLOBAL_SESSION_SIZE); - } - - public static int getFileWriteBufferCacheSize() { - return CONFIGURATION.getInt(STORE_FILE_PREFIX + "file-write-buffer-cache-size", DEFAULT_WRITE_BUFFER_SIZE); - } - - public static FlushDiskMode getFlushDiskMode() { - return FlushDiskMode.findDiskMode(CONFIGURATION.getConfig(STORE_FILE_PREFIX + "flush-disk-mode")); - } -} \ No newline at end of file diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionStoreManager.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionStoreManager.java deleted file mode 100755 index da7d44a4a..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionStoreManager.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import java.util.List; - -/** - * The interface Transaction store manager. - * - * @author jimin.jm @alibaba-inc.com - */ -public interface TransactionStoreManager { - - /** - * Write session boolean. - * - * @param logOperation the log operation - * @param session the session - * @return the boolean - */ - boolean writeSession(LogOperation logOperation, SessionStorable session); - - /** - * Shutdown. - */ - void shutdown(); - - /** - * Read write store from file list. - * - * @param readSize the read size - * @param isHistory the is history - * @return the list - */ - List readWriteStoreFromFile(int readSize, boolean isHistory); - - /** - * Has remaining boolean. - * - * @param isHistory the is history - * @return the boolean - */ - boolean hasRemaining(boolean isHistory); - - /** - * The enum Log operation. - */ - enum LogOperation { - - /** - * Global add log operation. - */ - GLOBAL_ADD((byte)1), - /** - * Global update log operation. - */ - GLOBAL_UPDATE((byte)2), - /** - * Global remove log operation. - */ - GLOBAL_REMOVE((byte)3), - /** - * Branch add log operation. - */ - BRANCH_ADD((byte)4), - /** - * Branch update log operation. - */ - BRANCH_UPDATE((byte)5), - /** - * Branch remove log operation. - */ - BRANCH_REMOVE((byte)6); - - private byte code; - - LogOperation(byte code) { - this.code = code; - } - - /** - * Gets code. - * - * @return the code - */ - public byte getCode() { - return this.code; - } - - /** - * Gets log operation by code. - * - * @param code the code - * @return the log operation by code - */ - public static LogOperation getLogOperationByCode(byte code) { - for (LogOperation temp : values()) { - if (temp.getCode() == code) { - return temp; - } - } - throw new IllegalArgumentException("Unknown LogOperation[" + code + "]"); - } - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionWriteStore.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionWriteStore.java deleted file mode 100755 index f7ab6c542..000000000 --- a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionWriteStore.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import java.nio.ByteBuffer; - -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.store.TransactionStoreManager.LogOperation; - -/** - * The type Transaction write store. - * - * @author jimin.jm @alibaba-inc.com - * @date 2018 /12/11 - */ -public class TransactionWriteStore implements SessionStorable { - private SessionStorable sessionRequest; - private LogOperation operate; - - /** - * Instantiates a new Transaction write store. - * - * @param sessionRequest the session request - * @param operate the operate - */ - public TransactionWriteStore(SessionStorable sessionRequest, LogOperation operate) { - this.sessionRequest = sessionRequest; - this.operate = operate; - } - - /** - * Instantiates a new Transaction write store. - */ - public TransactionWriteStore() {} - - /** - * Gets session request. - * - * @return the session request - */ - public SessionStorable getSessionRequest() { - return sessionRequest; - } - - /** - * Sets session request. - * - * @param sessionRequest the session request - */ - public void setSessionRequest(SessionStorable sessionRequest) { - this.sessionRequest = sessionRequest; - } - - /** - * Gets operate. - * - * @return the operate - */ - public LogOperation getOperate() { - return operate; - } - - /** - * Sets operate. - * - * @param operate the operate - */ - public void setOperate(LogOperation operate) { - this.operate = operate; - } - - @Override - public byte[] encode() { - byte[] bySessionRequest = this.sessionRequest.encode(); - byte byOpCode = this.getOperate().getCode(); - int len = bySessionRequest.length + 1; - byte[] byResult = new byte[len]; - ByteBuffer byteBuffer = ByteBuffer.wrap(byResult); - byteBuffer.put(bySessionRequest); - byteBuffer.put(byOpCode); - return byResult; - } - - @Override - public void decode(byte[] src) { - ByteBuffer byteBuffer = ByteBuffer.wrap(src); - byte[] bySessionRequest = new byte[src.length - 1]; - byteBuffer.get(bySessionRequest); - byte byOpCode = byteBuffer.get(); - this.operate = LogOperation.getLogOperationByCode(byOpCode); - SessionStorable tmpSessionStorable = getSessionInstanceByOperation(this.operate); - tmpSessionStorable.decode(bySessionRequest); - this.sessionRequest = tmpSessionStorable; - } - - private SessionStorable getSessionInstanceByOperation(LogOperation logOperation) { - SessionStorable sessionStorable = null; - switch (logOperation) { - case GLOBAL_ADD: - case GLOBAL_UPDATE: - case GLOBAL_REMOVE: - sessionStorable = new GlobalSession(); - break; - case BRANCH_ADD: - case BRANCH_UPDATE: - case BRANCH_REMOVE: - sessionStorable = new BranchSession(); - break; - default: - throw new ShouldNeverHappenException("incorrect logOperation"); - } - return sessionStorable; - } -} diff --git a/pigx-visual/pigx-seata-server/src/main/resources/logback.xml b/pigx-visual/pigx-seata-server/src/main/resources/logback.xml deleted file mode 100755 index 14508c9dd..000000000 --- a/pigx-visual/pigx-seata-server/src/main/resources/logback.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n - - - - - ${LOG_HOME}/seata-server.log - true - - ${LOG_HOME}/seata-server.log.%d{yyyy-MM-dd}.%i - 2GB - 7 - 7GB - true - - - %date %level %msg%n%n - UTF-8 - - - - - - - - - - - - - - diff --git a/pigx-visual/pigx-seata-server/src/main/resources/registry.conf b/pigx-visual/pigx-seata-server/src/main/resources/registry.conf deleted file mode 100755 index 79b92577a..000000000 --- a/pigx-visual/pigx-seata-server/src/main/resources/registry.conf +++ /dev/null @@ -1,71 +0,0 @@ -registry { - # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa - type = "nacos" - - nacos { - serverAddr = "localhost" - namespace = "public" - cluster = "default" - } - eureka { - serviceUrl = "http://localhost:1001/eureka" - application = "default" - weight = "1" - } - redis { - serverAddr = "localhost:6379" - db = "0" - } - zk { - cluster = "default" - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - } - consul { - cluster = "default" - serverAddr = "127.0.0.1:8500" - } - etcd3 { - cluster = "default" - serverAddr = "http://localhost:2379" - } - sofa { - serverAddr = "127.0.0.1:9603" - application = "default" - region = "DEFAULT_ZONE" - datacenter = "DefaultDataCenter" - cluster = "default" - group = "SEATA_GROUP" - addressWaitTime = "3000" - } - file { - name = "file.conf" - } -} - -config { - # file、nacos 、apollo、zk、consul - type = "nacos" - - nacos { - serverAddr = "pigx-nacos" - namespace = "public" - cluster = "default" - } - consul { - serverAddr = "127.0.0.1:8500" - } - apollo { - app.id = "seata-server" - apollo.meta = "http://192.168.1.204:8801" - } - zk { - serverAddr = "127.0.0.1:2181" - session.timeout = 6000 - connect.timeout = 2000 - } - file { - name = "file.conf" - } -} diff --git a/pigx-visual/pigx-sso-client-demo/pom.xml b/pigx-visual/pigx-sso-client-demo/pom.xml index 44b5a2b3f..050a58bec 100644 --- a/pigx-visual/pigx-sso-client-demo/pom.xml +++ b/pigx-visual/pigx-sso-client-demo/pom.xml @@ -29,7 +29,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 diff --git a/pigx-visual/pigx-tx-manager/pom.xml b/pigx-visual/pigx-tx-manager/pom.xml index ae5413a43..648f598a1 100644 --- a/pigx-visual/pigx-tx-manager/pom.xml +++ b/pigx-visual/pigx-tx-manager/pom.xml @@ -5,7 +5,7 @@ com.pig4cloud pigx-visual - 3.0.0 + 3.2 pigx-tx-manager diff --git a/pigx-visual/pom.xml b/pigx-visual/pom.xml index 69c5c19aa..bf29d4f56 100644 --- a/pigx-visual/pom.xml +++ b/pigx-visual/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx - 3.0.0 + 3.2 pigx-visual @@ -36,9 +36,9 @@ pigx-codegen pigx-daemon-elastic-job pigx-daemon-quartz + pigx-pay pigx-monitor pigx-mp-manager - pigx-seata-server pigx-sso-client-demo pigx-tx-manager diff --git a/pom.xml b/pom.xml index b06a2a2ba..f20a54af2 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ com.pig4cloud pigx - 3.0.0 + 3.2 ${project.artifactId} pom