├── hyena-spring-boot-starter-demo ├── src │ └── main │ │ ├── resources │ │ ├── .gitignore │ │ ├── bootstrap.yml │ │ └── application.yml │ │ └── java │ │ └── io │ │ └── github │ │ └── alphajiang │ │ └── hyena │ │ └── demo │ │ └── HyenaDemoMain.java └── build.gradle ├── docker ├── start.sh └── Dockerfile ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── hyena-spring-boot-starter ├── src │ └── main │ │ └── resources │ │ └── META-INF │ │ └── spring.provides └── build.gradle ├── sql └── init.sql ├── hyena-core ├── src │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── github │ │ │ └── alphajiang │ │ │ └── hyena │ │ │ ├── utils │ │ │ ├── IdGenerator.java │ │ │ ├── MemIdGenerator.java │ │ │ ├── DecimalUtils.java │ │ │ ├── JacksonStringDeserialize.java │ │ │ ├── TableNameHelper.java │ │ │ ├── NumberUtils.java │ │ │ ├── JacksonStringSerialize.java │ │ │ ├── DateUtils.java │ │ │ ├── CollectionUtils.java │ │ │ ├── StringUtils.java │ │ │ └── LoggerHelper.java │ │ │ ├── model │ │ │ ├── vo │ │ │ │ ├── PointLogBi.java │ │ │ │ ├── QueueInfo.java │ │ │ │ ├── PointRecCalcResult.java │ │ │ │ ├── PointVo.java │ │ │ │ └── PointOpResult.java │ │ │ ├── param │ │ │ │ ├── PointRefundFrozenParam.java │ │ │ │ ├── TimeFilter.java │ │ │ │ ├── PointFreezeByRecIdParam.java │ │ │ │ ├── PointCancelParam.java │ │ │ │ ├── PointRefundParam.java │ │ │ │ ├── ListPointParam.java │ │ │ │ ├── PointUnfreezeParam.java │ │ │ │ ├── PointDecreaseParam.java │ │ │ │ ├── PointDecreaseFrozenParam.java │ │ │ │ ├── PointFreezeParam.java │ │ │ │ ├── ListPointRecLogParam.java │ │ │ │ ├── ListPointLogParam.java │ │ │ │ ├── ListPointRecParam.java │ │ │ │ ├── PointIncreaseParam.java │ │ │ │ ├── PointOpParam.java │ │ │ │ ├── SortParam.java │ │ │ │ └── BaseListParam.java │ │ │ ├── type │ │ │ │ ├── SortOrder.java │ │ │ │ ├── CalcType.java │ │ │ │ └── PointOpType.java │ │ │ ├── base │ │ │ │ ├── ObjectResponse.java │ │ │ │ ├── BaseObject.java │ │ │ │ ├── ListResponse.java │ │ │ │ ├── BaseResponse.java │ │ │ │ └── BasePo.java │ │ │ ├── po │ │ │ │ ├── SysPropertyPo.java │ │ │ │ ├── FreezeOrderRecPo.java │ │ │ │ ├── PointRecPo.java │ │ │ │ ├── PointLogPo.java │ │ │ │ └── PointRecLogPo.java │ │ │ ├── exception │ │ │ │ ├── HyenaStatusException.java │ │ │ │ ├── HyenaParameterException.java │ │ │ │ ├── HyenaNoPointException.java │ │ │ │ ├── HyenaServiceException.java │ │ │ │ └── BaseException.java │ │ │ └── dto │ │ │ │ ├── PointRecDto.java │ │ │ │ ├── PointLogDto.java │ │ │ │ └── PointRecLogDto.java │ │ │ ├── biz │ │ │ ├── point │ │ │ │ ├── PSession.java │ │ │ │ ├── PointWrapper.java │ │ │ │ ├── strategy │ │ │ │ │ ├── PointStrategy.java │ │ │ │ │ └── PointStrategyFactory.java │ │ │ │ ├── PointCache.java │ │ │ │ └── PointUsage.java │ │ │ ├── cache │ │ │ │ ├── IPointCache.java │ │ │ │ └── HyenaCacheFactory.java │ │ │ ├── flow │ │ │ │ ├── PointDsQueue.java │ │ │ │ ├── QueueItem.java │ │ │ │ ├── QueueMonitor.java │ │ │ │ ├── PointUpdateQueue.java │ │ │ │ ├── PointRecDsQueue.java │ │ │ │ ├── PointLogFlowQueue.java │ │ │ │ ├── PointRecLogFlowQueue.java │ │ │ │ ├── FreezeOrderRecDsQueue.java │ │ │ │ ├── PointUpdateConsumer.java │ │ │ │ ├── PointLogFlowConsumer.java │ │ │ │ └── PointRecLogFlowConsumer.java │ │ │ └── idempotent │ │ │ │ ├── HyenaIdempotent.java │ │ │ │ └── HyenaMemIdempotent.java │ │ │ ├── aop │ │ │ └── Idempotent.java │ │ │ ├── ds │ │ │ ├── mapper │ │ │ │ ├── SysPropertyMapper.java │ │ │ │ ├── FreezeOrderRecMapper.xml │ │ │ │ ├── FreezeOrderRecMapper.java │ │ │ │ ├── PointRecLogMapper.java │ │ │ │ ├── SysPropertyMapper.xml │ │ │ │ ├── PointLogMapper.java │ │ │ │ ├── UpgradeSchemaMapper.java │ │ │ │ ├── PointTableMapper.java │ │ │ │ ├── PointRecMapper.java │ │ │ │ └── PointMapper.java │ │ │ └── service │ │ │ │ ├── FreezeOrderRecDs.java │ │ │ │ └── SysPropertyDs.java │ │ │ ├── HyenaConstants.java │ │ │ └── task │ │ │ └── MemCacheTask.java │ └── test │ │ ├── resources │ │ ├── bootstrap.yml │ │ └── application.yml │ │ └── java │ │ └── io │ │ └── github │ │ └── alphajiang │ │ └── hyena │ │ ├── utils │ │ ├── TestHyenaLockService.java │ │ ├── TestNumberUtils.java │ │ ├── TestStringUtils.java │ │ ├── TestDecimalUtils.java │ │ ├── TestJsonUtils.java │ │ └── TestCollectionUtils.java │ │ ├── ds │ │ ├── TestSysPropertyDs.java │ │ ├── TestPointRecLogDs.java │ │ ├── TestFreezeOrderRecDs.java │ │ └── TestPointLogDs.java │ │ ├── biz │ │ ├── cache │ │ │ └── TestPointRedisCacheService.java │ │ ├── TestPointUsageFacade.java │ │ └── strategy │ │ │ └── TestPointIncreaseStrategy.java │ │ ├── task │ │ └── TestExpirePointTask.java │ │ └── HyenaTestMain.java └── build.gradle ├── settings.gradle ├── hyena-spring-boot-autoconfigure ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── io │ │ └── github │ │ └── alphajiang │ │ └── hyena │ │ └── spring │ │ └── boot │ │ └── autoconfigure │ │ ├── HyenaProperties.java │ │ ├── HyenaSwaggerConfiguration.java │ │ ├── HyenaInitialization.java │ │ └── HyenaAutoConfiguration.java └── build.gradle ├── .travis.yml ├── gradle.properties ├── .gitignore ├── uploadArchives.sh └── gradlew.bat /hyena-spring-boot-starter-demo/src/main/resources/.gitignore: -------------------------------------------------------------------------------- 1 | application.yml.bak -------------------------------------------------------------------------------- /docker/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | /etc/init.d/redis-server start 4 | java -jar hyena.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alphajiang/hyena/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /hyena-spring-boot-starter/src/main/resources/META-INF/spring.provides: -------------------------------------------------------------------------------- 1 | provides: hyena-spring-boot-autoconfigure,hyena-core -------------------------------------------------------------------------------- /sql/init.sql: -------------------------------------------------------------------------------- 1 | create database p_hyena; 2 | 3 | CREATE USER 'hyena'@'%' IDENTIFIED BY 'hyenapass'; 4 | GRANT ALL PRIVILEGES ON p_hyena.* TO 'hyena'@'%' WITH GRANT OPTION; -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/IdGenerator.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.utils; 2 | 3 | public interface IdGenerator { 4 | 5 | String getId(); 6 | } 7 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'hyena' 2 | include 'hyena-core' 3 | include 'hyena-spring-boot-autoconfigure' 4 | include 'hyena-spring-boot-starter' 5 | include 'hyena-spring-boot-starter-demo' -------------------------------------------------------------------------------- /hyena-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | io.github.alphajiang.hyena.spring.boot.autoconfigure.HyenaAutoConfiguration -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.10.1-all.zip -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: java 3 | dist: xenial 4 | jdk: 5 | - openjdk11 6 | 7 | script: 8 | - ./gradlew clean build check test 9 | after_success: 10 | - ./gradlew -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2" jacocoTestReport coveralls 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | snapshotRepoUrl=https://oss.sonatype.org/content/repositories/snapshots 2 | signing.keyId=YourKeyId 3 | signing.password=YourPublicKeyPassword 4 | signing.secretKeyRingFile=PathToYourKeyRingFile 5 | 6 | ossrhUsername=your-jira-id 7 | ossrhPassword=your-jira-password 8 | systemProp.jdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2" -------------------------------------------------------------------------------- /hyena-core/src/test/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | 2 | spring: 3 | application: 4 | name: hyenaServiceTest 5 | 6 | 7 | # config: 8 | # additional-location: "file:~/project/conf/hyena" 9 | # profiles: 10 | # active: common,jdbc,redis,rabbitmq 11 | 12 | 13 | # cloud: 14 | # config: 15 | # uri: https://oam.xxx.com 16 | # label: dev -------------------------------------------------------------------------------- /hyena-spring-boot-starter-demo/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | 2 | spring: 3 | application: 4 | name: hyenaServiceTest 5 | 6 | 7 | # config: 8 | # additional-location: "file:~/project/conf/hyena" 9 | # profiles: 10 | # active: common,jdbc,redis,rabbitmq 11 | 12 | 13 | # cloud: 14 | # config: 15 | # uri: https://oam.xxx.com 16 | # label: dev -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/vo/PointLogBi.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.model.vo; 2 | 3 | import lombok.Data; 4 | import lombok.experimental.Accessors; 5 | 6 | import java.math.BigDecimal; 7 | 8 | @Data 9 | @Accessors(chain = true) 10 | public class PointLogBi { 11 | private Integer logType; 12 | private BigDecimal delta; 13 | private BigDecimal deltaCost; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | **/build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | **/out/ 22 | 23 | ### NetBeans ### 24 | /nbproject/private/ 25 | /nbbuild/ 26 | /dist/ 27 | /nbdist/ 28 | /.nb-gradle/ 29 | 30 | **/*.log 31 | logs/ 32 | 33 | **/.sass-cache 34 | 35 | docker/*.jar 36 | gradle.properties.* -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointRefundFrozenParam.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.model.param; 2 | 3 | /** 4 | * 退款解冻 5 | */ 6 | //@Data 7 | //@Accessors(chain = true) 8 | //@EqualsAndHashCode(callSuper = true) 9 | //@ToString(callSuper = true) 10 | //@Schema(title = "退款(已冻结)请求参数") 11 | //public class PointRefundFrozenParam extends PointOpParam { 12 | // 13 | // 14 | //// @Schema(title = "解冻积分数量", example = "10.00") 15 | //// private BigDecimal unfreezePoint; 16 | // 17 | // @Schema(title = "积分块ID", example = "112") 18 | // private Long recId; 19 | // 20 | //} 21 | -------------------------------------------------------------------------------- /uploadArchives.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/ 4 | PATH=${JAVA_HOME}/bin:${PATH} 5 | 6 | java --version 7 | 8 | ./gradlew clean 9 | 10 | ./gradlew -p hyena-core -DSNAPSHOT publish 11 | if [ $? -ne 0 ]; then 12 | echo "build hyena-core failed!!!" 13 | exit 99 14 | fi 15 | 16 | ./gradlew -p hyena-spring-boot-autoconfigure -DSNAPSHOT publish 17 | if [ $? -ne 0 ]; then 18 | echo "build hyena-spring-boot-autoconfigure failed!!!" 19 | exit 99 20 | fi 21 | 22 | ./gradlew -p hyena-spring-boot-starter -DSNAPSHOT publish 23 | if [ $? -ne 0 ]; then 24 | echo "build hyena-spring-boot-starter failed!!!" 25 | exit 99 26 | fi 27 | echo "build succeed" -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/TimeFilter.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.model.param; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import lombok.Data; 6 | 7 | import java.util.Date; 8 | 9 | @Data 10 | public class TimeFilter { 11 | @Schema(title = "开始时间. 闭区间", example = "2025-10-24 15:34:46") 12 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 13 | private Date startTime; 14 | 15 | @Schema(title = "结束时间. 开区间", example = "2025-10-24 15:34:46") 16 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 17 | private Date endTime; 18 | } 19 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointFreezeByRecIdParam.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.model.param; 2 | 3 | import io.github.alphajiang.hyena.utils.JsonUtils; 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.ToString; 8 | import lombok.experimental.Accessors; 9 | 10 | @Data 11 | @Accessors(chain = true) 12 | @EqualsAndHashCode(callSuper = true) 13 | public class PointFreezeByRecIdParam extends PointOpParam { 14 | 15 | @Schema(title = "积分块ID", example = "123") 16 | private Long recId; 17 | 18 | @Override 19 | public String toString() { 20 | return JsonUtils.toJsonString(this); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/point/PSession.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.biz.point; 2 | 3 | import io.github.alphajiang.hyena.model.vo.PointOpResult; 4 | import io.github.alphajiang.hyena.model.vo.PointVo; 5 | import lombok.Data; 6 | import lombok.experimental.Accessors; 7 | 8 | @Data 9 | @Accessors(chain = true) 10 | public class PSession { 11 | private PointUsage usage; 12 | private PointWrapper pw; 13 | 14 | private PointVo originPoint; // for roll back 15 | 16 | private PointOpResult result; 17 | 18 | public static PSession fromUsage(PointUsage usage) { 19 | PSession session = new PSession(); 20 | session.setUsage(usage); 21 | return session; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | ENV APP_PATH /opt/hyena 4 | WORKDIR $APP_PATH 5 | 6 | RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak 7 | RUN sed 's/archive.ubuntu.com/mirrors.aliyun.com/' /etc/apt/sources.list.bak > /etc/apt/sources.list 8 | RUN apt update -y 9 | RUN apt upgrade -y 10 | 11 | 12 | ENV TZ 'Asia/Shanghai' 13 | RUN echo $TZ > /etc/timezone && \ 14 | apt install -y tzdata && \ 15 | rm /etc/localtime && \ 16 | ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ 17 | dpkg-reconfigure -f noninteractive tzdata && \ 18 | apt clean 19 | 20 | RUN apt install -y openjdk-11-jre-headless redis-server 21 | 22 | 23 | EXPOSE 8080 24 | 25 | ADD start.sh $APP_PATH/ 26 | ADD hyena.jar $APP_PATH/ 27 | 28 | 29 | 30 | CMD ./start.sh 31 | 32 | 33 | -------------------------------------------------------------------------------- /hyena-spring-boot-autoconfigure/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | archivesBaseName = "hyena-spring-boot-autoconfigure" 3 | 4 | //jar { 5 | // enabled = true 6 | //} 7 | 8 | dependencies { 9 | implementation project(':hyena-core') 10 | 11 | implementation("org.springframework.boot:spring-boot-autoconfigure:${springBootVersion}") 12 | // implementation("org.springframework.boot:spring-boot-starter-data-redis:${springBootVersion}") 13 | implementation("org.springframework.boot:spring-boot-starter-data-redis-reactive:${springBootVersion}") 14 | implementation("org.springframework.boot:spring-boot-starter-webflux:${springBootVersion}") 15 | implementation("org.springdoc:springdoc-openapi-ui:${springdocVersion}") 16 | implementation("org.springdoc:springdoc-openapi-webflux-ui:${springdocVersion}") 17 | 18 | } 19 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/utils/TestHyenaLockService.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.utils; 2 | 3 | import io.github.alphajiang.hyena.HyenaTestBase; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | @Slf4j 9 | public class TestHyenaLockService extends HyenaTestBase { 10 | 11 | @Autowired 12 | private HyenaLockService hyenaLockService; 13 | 14 | @Test 15 | public void test_lock() throws InterruptedException { 16 | this.hyenaLockService.lock("score", "84790", "34490"); 17 | this.hyenaLockService.unlock("score", "84790", "34490"); 18 | 19 | // this.hyenaLockService.lock("84790", "34490"); 20 | //this.hyenaLockService.unlock("84790", "34490"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/cache/IPointCache.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.biz.cache; 2 | 3 | import io.github.alphajiang.hyena.biz.point.PointCache; 4 | import io.github.alphajiang.hyena.biz.point.PointWrapper; 5 | import io.github.alphajiang.hyena.model.vo.PointVo; 6 | import reactor.core.publisher.Mono; 7 | 8 | import java.util.Collection; 9 | 10 | public interface IPointCache { 11 | 12 | String getCacheType(); 13 | 14 | Mono getPoint(String type, String uid, String subUid, boolean lock); 15 | 16 | Mono updatePoint(String type, String uid, String subUid, PointVo point); 17 | 18 | Mono removePoint(String type, String uid, String subUid); 19 | 20 | Collection dump(); 21 | 22 | void expireCache(); 23 | 24 | Mono unlock(String type, String uid, String subUid); 25 | } 26 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointDsQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | public interface PointDsQueue { 21 | int getQueueSize(); 22 | } 23 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/type/SortOrder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.type; 19 | 20 | public enum SortOrder { 21 | asc, 22 | 23 | desc 24 | } 25 | -------------------------------------------------------------------------------- /hyena-spring-boot-starter/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | archivesBaseName = "hyena-spring-boot-starter" 3 | 4 | //sourceSets { 5 | // main { 6 | // resources { 7 | // srcDirs "src/main/resources", "src/main/java" 8 | // } 9 | // } 10 | //} 11 | 12 | //jar { 13 | // enabled = true 14 | //} 15 | 16 | 17 | test { 18 | //include 'org/aj/**' 19 | 20 | } 21 | 22 | dependencies { 23 | implementation project(':hyena-core'), project(':hyena-spring-boot-autoconfigure') 24 | 25 | implementation("org.springframework.boot:spring-boot-starter:${springBootVersion}") 26 | implementation("org.springframework.boot:spring-boot-starter-webflux:${springBootVersion}") 27 | implementation("org.springframework.boot:spring-boot-starter-jdbc:${springBootVersion}") 28 | implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:${mybatisStarterVersion}") 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointCancelParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | public class PointCancelParam extends PointOpParam { 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/MemIdGenerator.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.util.concurrent.atomic.AtomicLong; 6 | 7 | /** 8 | * he default id generator for non-cluster environment 9 | */ 10 | @Component 11 | public class MemIdGenerator implements IdGenerator { 12 | 13 | private static final Long MAX_IDX = 1000000L; 14 | private Long time = getTime(); 15 | private AtomicLong curIdx = new AtomicLong(1L); 16 | 17 | @Override 18 | public synchronized String getId() { 19 | if (curIdx.longValue() % MAX_IDX == 0) { 20 | time = getTime(); 21 | curIdx = new AtomicLong(1L); 22 | } 23 | Long val = time * MAX_IDX + curIdx.getAndAdd(1L); 24 | return val.toString(); 25 | } 26 | 27 | private Long getTime() { 28 | return System.currentTimeMillis() / 1000L; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointRefundParam.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.model.param; 2 | 3 | 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import io.swagger.v3.oas.annotations.media.Schema; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.ToString; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.math.BigDecimal; 12 | 13 | @Data 14 | @Accessors(chain = true) 15 | @EqualsAndHashCode(callSuper = true) 16 | @ToString(callSuper = true) 17 | @Schema(title = "退款请求参数") 18 | public class PointRefundParam extends PointUnfreezeParam { 19 | 20 | /** 21 | * 实际成本 22 | */ 23 | @Schema(title = "实际成本", description = "退款按实际成本计算", example = "1.00") 24 | private BigDecimal cost; 25 | 26 | 27 | // @Schema(title = "要退款的积分记录ID") 28 | // private Long recId; // 积分记录的ID 29 | 30 | @Schema(title = "解冻积分数量", example = "10.00") 31 | private BigDecimal unfreezePoint; 32 | } 33 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/QueueItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import lombok.Data; 21 | import lombok.experimental.Accessors; 22 | 23 | @Data 24 | @Accessors(chain = true) 25 | public class QueueItem { 26 | private boolean insert; 27 | private String type; 28 | } 29 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/vo/QueueInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.vo; 19 | 20 | import lombok.Data; 21 | import lombok.experimental.Accessors; 22 | 23 | @Data 24 | @Accessors(chain = true) 25 | public class QueueInfo { 26 | private String name; 27 | private long curSize; 28 | //private long maxSize; 29 | } 30 | -------------------------------------------------------------------------------- /hyena-core/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | app: 2 | name: HyenaServiceTest 3 | 4 | server: 5 | address: 0.0.0.0 6 | port: 8080 7 | use-forward-headers: true 8 | compression.enabled: true 9 | 10 | 11 | management: 12 | context-path: /admin 13 | security: 14 | enabled: false 15 | 16 | 17 | 18 | logging: 19 | level: 20 | io.github.alphajiang.hyena: 'DEBUG' 21 | org.springframework: 'INFO' 22 | org.springframework.transaction: WARN 23 | org.springframework.jdbc: WARN 24 | com.zaxxer.hikari: WARN 25 | 26 | pattern: 27 | console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] - %logger{36}.%M\\(%line\\) - %msg%n" 28 | 29 | 30 | 31 | spring: 32 | h2: 33 | console: 34 | enabled: true 35 | datasource: 36 | continue-on-error: false 37 | driver-class-name: org.h2.Driver 38 | name: hyena 39 | username: sa 40 | password: 41 | url: jdbc:h2:mem:testdbsa;mode=MySQL 42 | initialPoolSize: 1 43 | minPoolSize: 1 44 | maxPoolSize: 20 45 | acquireIncrement: 1 46 | maxIdleTime: 10 47 | checkoutTimeout: 30000 -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/cache/HyenaCacheFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.biz.cache; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.stereotype.Service; 6 | 7 | @Service 8 | @Slf4j 9 | public class HyenaCacheFactory { 10 | 11 | // @Autowired(required = false) 12 | // private PointMemCacheService pointMemCacheService; 13 | 14 | @Value("${hyena.cache:memory}") 15 | private String cacheType; 16 | 17 | private IPointCache pointCacheService; 18 | 19 | // @PostConstruct 20 | // public void init() { 21 | // 22 | // } 23 | 24 | public IPointCache getPointCacheService() { 25 | return this.pointCacheService; 26 | } 27 | 28 | public void setPointCacheService(IPointCache cacheService) { 29 | if (cacheService.getCacheType().equalsIgnoreCase(cacheType)) { 30 | log.info("use {} point cache service", cacheService.getCacheType()); 31 | this.pointCacheService = cacheService; 32 | } 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/DecimalUtils.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.utils; 2 | 3 | import java.math.BigDecimal; 4 | 5 | public class DecimalUtils { 6 | 7 | public static final int SCALE_2 = 2; 8 | public static final BigDecimal ZERO = BigDecimal.valueOf(0, SCALE_2); 9 | 10 | /** 11 | * 12 | * @param left left value 13 | * @param right right value 14 | * @return true if left is less than right 15 | */ 16 | public static boolean lt(BigDecimal left, BigDecimal right) { 17 | return left.compareTo(right) < 0; 18 | } 19 | 20 | public static boolean ltZero(BigDecimal left) { 21 | return left.compareTo(BigDecimal.ZERO) < 0; 22 | } 23 | public static boolean lte(BigDecimal left, BigDecimal right) { 24 | return left.compareTo(right) < 1; 25 | } 26 | 27 | public static boolean gt(BigDecimal left, BigDecimal right) { 28 | return left.compareTo(right) > 0; 29 | } 30 | public static boolean gte(BigDecimal left, BigDecimal right) { 31 | return left.compareTo(right) > -1; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/idempotent/HyenaIdempotent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.idempotent; 19 | 20 | import io.github.alphajiang.hyena.model.base.BaseResponse; 21 | 22 | public interface HyenaIdempotent { 23 | 24 | boolean lock(String seq); 25 | void unlock(String seq); 26 | String getByKey(String name, String seq); 27 | void setByKey(String name, String seq, BaseResponse obj); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/point/PointWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.point; 19 | 20 | import lombok.AllArgsConstructor; 21 | import lombok.Getter; 22 | 23 | @Getter 24 | @AllArgsConstructor 25 | public class PointWrapper implements AutoCloseable { 26 | 27 | private PointCache pointCache; 28 | 29 | @Override 30 | public void close() { 31 | this.pointCache.unlock(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/vo/PointRecCalcResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.vo; 19 | 20 | import io.github.alphajiang.hyena.model.po.PointRecPo; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Data; 23 | 24 | import java.math.BigDecimal; 25 | 26 | @Data 27 | @AllArgsConstructor 28 | public class PointRecCalcResult { 29 | private PointRecPo rec4Update; 30 | private BigDecimal deltaCost; 31 | } 32 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/ListPointParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import java.util.List; 21 | 22 | public class ListPointParam extends BaseListParam{ 23 | 24 | private List uidList; 25 | 26 | public List getUidList() { 27 | return uidList; 28 | } 29 | 30 | public void setUidList(List uidList) { 31 | this.uidList = uidList; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/type/CalcType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.type; 19 | 20 | public enum CalcType { 21 | INCREASE, 22 | 23 | DECREASE, 24 | 25 | DECREASE_FROZEN, 26 | 27 | FREEZE, 28 | 29 | UNFREEZE, 30 | 31 | REFUND, 32 | 33 | //REFUND_FROZEN, 34 | 35 | FREEZE_BY_REC_ID, // 按积分块ID来冻结 36 | 37 | FREEZE_COST, // 退款冻结 38 | 39 | UNFREEZE_COST, // 退款解冻 40 | 41 | EXPIRE, 42 | 43 | CANCEL 44 | } 45 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/base/ObjectResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.base; 19 | 20 | public class ObjectResponse extends BaseResponse { 21 | protected T data; 22 | 23 | public ObjectResponse() { 24 | 25 | } 26 | 27 | public ObjectResponse(T data) { 28 | this.data = data; 29 | } 30 | 31 | public T getData() { 32 | return data; 33 | } 34 | 35 | public void setData(T data) { 36 | this.data = data; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/aop/Idempotent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.aop; 19 | 20 | import com.fasterxml.jackson.core.type.TypeReference; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.reflect.Type; 24 | 25 | @Retention(RetentionPolicy.RUNTIME) 26 | public @interface Idempotent { 27 | /** 28 | * @return the name part of idempotent key 29 | */ 30 | String name() default ""; 31 | 32 | Class resClass(); 33 | } 34 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/po/SysPropertyPo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.po; 19 | 20 | import io.github.alphajiang.hyena.model.base.BasePo; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | 26 | @Data 27 | @Accessors(chain = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | @ToString(callSuper = true) 30 | public class SysPropertyPo extends BasePo { 31 | private String key; 32 | private String value; 33 | } 34 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/point/strategy/PointStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.point.strategy; 19 | 20 | import io.github.alphajiang.hyena.biz.point.PSession; 21 | import io.github.alphajiang.hyena.biz.point.PointUsage; 22 | import io.github.alphajiang.hyena.model.type.CalcType; 23 | import io.github.alphajiang.hyena.model.vo.PointOpResult; 24 | import reactor.core.publisher.Mono; 25 | 26 | public interface PointStrategy { 27 | 28 | CalcType getType(); 29 | 30 | Mono process(PSession session); 31 | } 32 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/JacksonStringDeserialize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import com.fasterxml.jackson.core.JsonParser; 21 | import com.fasterxml.jackson.databind.DeserializationContext; 22 | import com.fasterxml.jackson.databind.JsonDeserializer; 23 | 24 | import java.io.IOException; 25 | 26 | public class JacksonStringDeserialize extends JsonDeserializer { 27 | 28 | @Override 29 | public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 30 | return p.getText(); 31 | } 32 | } -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/SysPropertyMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import io.github.alphajiang.hyena.model.po.SysPropertyPo; 21 | import org.apache.ibatis.annotations.Mapper; 22 | import org.apache.ibatis.annotations.Param; 23 | 24 | @Mapper 25 | public interface SysPropertyMapper { 26 | 27 | void createSysPropertyTable(); 28 | 29 | void insertOrUpdate(SysPropertyPo sysProperty); 30 | 31 | int updateSysProperty(@Param("key") String key, @Param("value") String value); 32 | 33 | SysPropertyPo getSysProperty(@Param("key") String key); 34 | } 35 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/exception/HyenaStatusException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.exception; 19 | 20 | import io.github.alphajiang.hyena.HyenaConstants; 21 | import org.slf4j.event.Level; 22 | 23 | public class HyenaStatusException extends BaseException { 24 | private static final int CODE = HyenaConstants.RES_CODE_STATUS_ERROR; 25 | 26 | 27 | public HyenaStatusException(int code, String msg, Level logLevel) { 28 | super(code, msg, logLevel); 29 | 30 | } 31 | 32 | public HyenaStatusException(String msg) { 33 | super(CODE, msg); 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/dto/PointRecDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.dto; 19 | 20 | import io.github.alphajiang.hyena.model.po.PointRecPo; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | 26 | import java.util.List; 27 | 28 | @Data 29 | @Accessors(chain = true) 30 | @EqualsAndHashCode(callSuper = true) 31 | @ToString(callSuper = true) 32 | public class PointRecDto extends PointRecPo { 33 | private String uid; 34 | 35 | private String subUid; 36 | 37 | private List recLogs; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/exception/HyenaParameterException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.exception; 19 | 20 | import io.github.alphajiang.hyena.HyenaConstants; 21 | import org.slf4j.event.Level; 22 | 23 | public class HyenaParameterException extends BaseException { 24 | private static final int CODE = HyenaConstants.RES_CODE_PARAMETER_ERROR; 25 | 26 | public HyenaParameterException(String msg) { 27 | super(CODE, msg); 28 | } 29 | 30 | 31 | public HyenaParameterException(int code, String msg, Level logLevel) { 32 | super(code, msg, logLevel); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/exception/HyenaNoPointException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.exception; 19 | 20 | import io.github.alphajiang.hyena.HyenaConstants; 21 | import org.slf4j.event.Level; 22 | 23 | public class HyenaNoPointException extends BaseException { 24 | private static final int CODE = HyenaConstants.RES_CODE_NO_ENOUGH_POINT; 25 | 26 | public HyenaNoPointException(String msg, Level logLevel) { 27 | super(CODE, msg, logLevel); 28 | } 29 | 30 | 31 | public HyenaNoPointException(int code, String msg, Level logLevel) { 32 | super(code, msg, logLevel); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointUnfreezeParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.swagger.v3.oas.annotations.media.Schema; 21 | import io.swagger.v3.oas.annotations.media.Schema; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | 27 | @Data 28 | @Accessors(chain = true) 29 | @EqualsAndHashCode(callSuper = true) 30 | @ToString(callSuper = true) 31 | @Schema(title = "解冻请求参数") 32 | public class PointUnfreezeParam extends PointOpParam { 33 | 34 | @Schema(title = "根据订单号做解冻操作") 35 | private Boolean unfreezeByOrderNo; 36 | } 37 | -------------------------------------------------------------------------------- /hyena-spring-boot-autoconfigure/src/main/java/io/github/alphajiang/hyena/spring/boot/autoconfigure/HyenaProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.spring.boot.autoconfigure; 19 | 20 | import org.springframework.boot.context.properties.ConfigurationProperties; 21 | 22 | @ConfigurationProperties(prefix = HyenaProperties.HYENA_PREFIX) 23 | public class HyenaProperties { 24 | public static final String HYENA_PREFIX = "hyena"; 25 | 26 | private String idempotent; 27 | 28 | public String getIdempotent() { 29 | return idempotent; 30 | } 31 | 32 | public void setIdempotent(String idempotent) { 33 | this.idempotent = idempotent; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/TableNameHelper.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | package io.github.alphajiang.hyena.utils; 21 | 22 | import io.github.alphajiang.hyena.HyenaConstants; 23 | 24 | public class TableNameHelper { 25 | 26 | public static String getPointTableName(String type) { 27 | return HyenaConstants.PREFIX_POINT_TABLE_NAME + type; 28 | } 29 | 30 | public static String getPointRecTableName(String type) { 31 | return HyenaConstants.PREFIX_POINT_TABLE_NAME + type + "_rec"; 32 | } 33 | 34 | public static String getPointRecLogTableName(String type) { 35 | return HyenaConstants.PREFIX_POINT_TABLE_NAME + type + "_rec_log"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/dto/PointLogDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.dto; 19 | 20 | import io.github.alphajiang.hyena.model.po.PointLogPo; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | import org.springframework.beans.BeanUtils; 26 | 27 | @Data 28 | @Accessors(chain = true) 29 | @EqualsAndHashCode(callSuper = true) 30 | @ToString(callSuper = true) 31 | public class PointLogDto extends PointLogPo { 32 | 33 | public static PointLogDto build(PointLogPo po) { 34 | PointLogDto o = new PointLogDto(); 35 | BeanUtils.copyProperties(po, o); 36 | return o; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointDecreaseParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.github.alphajiang.hyena.utils.JsonUtils; 21 | import io.swagger.v3.oas.annotations.media.Schema; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | 27 | @Data 28 | @Accessors(chain = true) 29 | @EqualsAndHashCode(callSuper = true) 30 | public class PointDecreaseParam extends PointOpParam { 31 | 32 | @Schema(title = "指定减少的积分块ID", example = "123") 33 | private Long recId; 34 | 35 | @Override 36 | public String toString() { 37 | return JsonUtils.toJsonString(this); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /hyena-spring-boot-starter-demo/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | app: 2 | name: HyenaServiceTest 3 | 4 | server: 5 | address: 0.0.0.0 6 | port: 8080 7 | use-forward-headers: true 8 | compression.enabled: true 9 | 10 | 11 | management: 12 | context-path: /admin 13 | security: 14 | enabled: false 15 | 16 | 17 | 18 | logging: 19 | level: 20 | io.github.alphajiang.hyena: DEBUG 21 | org.springframework: INFO 22 | pattern: 23 | console: "%d{yyyy-MM-dd HH:mm:ss} - %logger{36}.%M\\(%line\\) - %msg%n" 24 | 25 | hyena: 26 | idempotent: redis 27 | cache: redis 28 | 29 | 30 | 31 | 32 | spring: 33 | datasource: 34 | type: com.zaxxer.hikari.HikariDataSource 35 | continue-on-error: false 36 | driver-class-name: com.mysql.cj.jdbc.Driver 37 | name: p_hyena 38 | username: hyena 39 | password: hyenapass 40 | url: jdbc:mysql://127.0.0.1:3306/p_hyena?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL&allowMultiQueries=true 41 | initialPoolSize: 1 42 | minPoolSize: 1 43 | maxPoolSize: 10 44 | acquireIncrement: 1 45 | maxIdleTime: 10 46 | checkoutTimeout: 30000 47 | redis: 48 | database: 3 49 | host: localhost 50 | port: 6379 51 | password: 52 | timeout: 4000 53 | ssl: false 54 | pool: 55 | max-active: 1024 56 | max-idle: 200 57 | max-wait: 10000 58 | min-idle: 0 59 | 60 | 61 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointDecreaseFrozenParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.swagger.v3.oas.annotations.media.Schema; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | 26 | import java.math.BigDecimal; 27 | 28 | @Data 29 | @Accessors(chain = true) 30 | @EqualsAndHashCode(callSuper = true) 31 | @ToString(callSuper = true) 32 | public class PointDecreaseFrozenParam extends PointUnfreezeParam { 33 | 34 | @Schema(title = "创建积分快的订单号", example = "A123") 35 | private String recOrderNo; 36 | 37 | @Schema(title = "解冻积分数量", example = "10.00") 38 | private BigDecimal unfreezePoint; 39 | } 40 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/HyenaConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | package io.github.alphajiang.hyena; 20 | 21 | public interface HyenaConstants { 22 | 23 | int SQL_VERSION = 4; 24 | 25 | int RES_CODE_SUCCESS = 0; 26 | int RES_CODE_SERVICE_ERROR = 1000; 27 | int RES_CODE_NO_ENOUGH_POINT = 1010; 28 | int RES_CODE_PARAMETER_ERROR = 1100; 29 | int RES_CODE_STATUS_ERROR = 1200; 30 | int RES_CODE_SERVICE_BUSY = 1300; 31 | int RES_CODE_DUPLICATE = 2000; 32 | int RES_CODE_DUPLICATE_IDEMPOTENT = 2001; 33 | int RES_CODE_SERVER_ERROR = 9000; 34 | int RES_CODE_UNKNOW_ERROR = 9999; 35 | 36 | String PREFIX_POINT_TABLE_NAME = "t_point_"; 37 | 38 | String REQ_IDEMPOTENT_SEQ_KEY = "hyena-seq"; 39 | 40 | 41 | String CONST_TEST_DB_DRIVER = "org.h2.Driver"; 42 | } 43 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/po/FreezeOrderRecPo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.po; 19 | 20 | import io.github.alphajiang.hyena.model.base.BasePo; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | 26 | import java.math.BigDecimal; 27 | 28 | @Data 29 | @Accessors(chain = true) 30 | @EqualsAndHashCode(callSuper = true) 31 | @ToString(callSuper = true) 32 | public class FreezeOrderRecPo extends BasePo { 33 | private long pid; 34 | private String uid; 35 | private String subUid; 36 | private long recId; 37 | private long seqNum; 38 | private int orderType; 39 | private BigDecimal frozen; 40 | private BigDecimal frozenCost; 41 | private String orderNo; 42 | } 43 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointFreezeParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.github.alphajiang.hyena.utils.JsonUtils; 21 | import io.swagger.v3.oas.annotations.media.Schema; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | 27 | import java.math.BigDecimal; 28 | 29 | @Data 30 | @Accessors(chain = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | public class PointFreezeParam extends PointOpParam { 33 | 34 | @Schema(title = "创建积分快的订单号", example = "A123") 35 | private String recOrderNo; 36 | 37 | @Schema(title = "实际成本, 按成本冻结时传递", example = "1.00") 38 | private BigDecimal cost; 39 | 40 | @Override 41 | public String toString() { 42 | return JsonUtils.toJsonString(this); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/QueueMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.model.vo.QueueInfo; 21 | import org.springframework.stereotype.Service; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | @Service 27 | public class QueueMonitor { 28 | 29 | List queueList = new ArrayList<>(); 30 | 31 | public void addQueue(PointDsQueue q) { 32 | this.queueList.add(q); 33 | } 34 | 35 | public List dump() { 36 | List list = new ArrayList<>(); 37 | queueList.stream().forEach(q -> { 38 | QueueInfo info = new QueueInfo(); 39 | info.setName(q.getClass().getSimpleName()) 40 | .setCurSize(q.getQueueSize()); 41 | list.add(info); 42 | }); 43 | return list; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/ds/TestSysPropertyDs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds; 19 | 20 | import io.github.alphajiang.hyena.HyenaTestBase; 21 | import io.github.alphajiang.hyena.ds.service.SysPropertyDs; 22 | import org.junit.jupiter.api.Assertions; 23 | import org.junit.jupiter.api.BeforeEach; 24 | import org.junit.jupiter.api.Test; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | 27 | public class TestSysPropertyDs extends HyenaTestBase { 28 | 29 | @Autowired 30 | private SysPropertyDs sysPropertyDs; 31 | 32 | @BeforeEach 33 | public void init() { 34 | super.init(); 35 | } 36 | 37 | @Test 38 | public void test_setSqlVersion() { 39 | int ver = 10; 40 | this.sysPropertyDs.setSqlVersion(ver); 41 | int result = this.sysPropertyDs.getSqlVersion(); 42 | Assertions.assertEquals(ver, result); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/utils/TestNumberUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import org.junit.jupiter.api.Assertions; 21 | import org.junit.jupiter.api.Test; 22 | 23 | public class TestNumberUtils { 24 | 25 | @Test 26 | public void test_parseLong_bytes() { 27 | String str = "12345"; 28 | long result = NumberUtils.parseLong(str.getBytes(), 0L); 29 | Assertions.assertEquals(12345L, result); 30 | } 31 | 32 | @Test 33 | public void test_parseLong_bytes_null() { 34 | byte[] in = null; 35 | long result = NumberUtils.parseLong(in, 123L); 36 | Assertions.assertEquals(123L, result); 37 | } 38 | 39 | @Test 40 | public void test_parseLong_not_number() { 41 | String str = "123ab"; 42 | long result = NumberUtils.parseLong(str, 123L); 43 | Assertions.assertEquals(123L, result); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/utils/TestStringUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import org.junit.jupiter.api.Assertions; 21 | import org.junit.jupiter.api.Test; 22 | 23 | public class TestStringUtils { 24 | 25 | 26 | @Test 27 | public void test_upperCase() { 28 | String str = "abc"; 29 | String result = StringUtils.upperCase(str); 30 | Assertions.assertEquals("ABC", result); 31 | } 32 | 33 | @Test 34 | public void test_upperCase_null() { 35 | 36 | String result = StringUtils.upperCase(null); 37 | HyenaAssert.isNull(result, "result should be null"); 38 | 39 | } 40 | 41 | @Test 42 | public void test_equals() { 43 | String left = "abc"; 44 | String right = "abc"; 45 | boolean result = StringUtils.equals(left, right); 46 | HyenaAssert.isTrue(result, "result is true"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/type/PointOpType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.type; 19 | 20 | /** 21 | * 变动类型 22 | */ 23 | public enum PointOpType { 24 | 25 | INCREASE(1), // 增加 26 | 27 | DECREASE(2), // 减少(使用) 28 | 29 | FREEZE(3), // 冻结 30 | 31 | UNFREEZE(4), // 解冻 32 | 33 | EXPIRE(5), // 过期 34 | 35 | CANCEL(6), // 作废 36 | 37 | REFUND(7), // 退款 38 | 39 | UNKNOWN(0) 40 | ; 41 | 42 | 43 | private final int code; 44 | 45 | PointOpType(int code) { 46 | this.code = code; 47 | } 48 | 49 | public static PointOpType fromCode(int code){ 50 | for (PointOpType type : values()) { 51 | if (type.code == code) { 52 | return type; 53 | } 54 | } 55 | return UNKNOWN; 56 | } 57 | 58 | public int code() { 59 | return this.code; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/exception/HyenaServiceException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.exception; 19 | 20 | import io.github.alphajiang.hyena.HyenaConstants; 21 | import org.slf4j.event.Level; 22 | 23 | public class HyenaServiceException extends BaseException { 24 | private static final int CODE = HyenaConstants.RES_CODE_SERVICE_ERROR; 25 | 26 | public HyenaServiceException(String msg, Level logLevel) { 27 | super(CODE, msg, logLevel); 28 | } 29 | 30 | 31 | 32 | public HyenaServiceException(int code, String msg, Level logLevel) { 33 | super(code, msg, logLevel); 34 | 35 | } 36 | 37 | public HyenaServiceException(String msg) { 38 | super(CODE, msg); 39 | } 40 | 41 | 42 | public HyenaServiceException(String msg, Throwable e) { 43 | super(CODE, msg, e); 44 | } 45 | 46 | public HyenaServiceException(int code, String msg) { 47 | super(code, msg); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /hyena-spring-boot-autoconfigure/src/main/java/io/github/alphajiang/hyena/spring/boot/autoconfigure/HyenaSwaggerConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.spring.boot.autoconfigure; 19 | 20 | import org.springdoc.core.GroupedOpenApi; 21 | import org.springframework.context.annotation.Bean; 22 | import org.springframework.context.annotation.Configuration; 23 | 24 | 25 | @Configuration 26 | public class HyenaSwaggerConfiguration { 27 | 28 | @Bean 29 | public GroupedOpenApi hyenaApi() { 30 | // return new Docket(DocumentationType.SWAGGER_2) 31 | // .select() 32 | // // 仅显示 io.github.alphajiang.hyena.rest 目录下的接口 33 | // .apis(RequestHandlerSelectors.basePackage("io.github.alphajiang.hyena.rest")) 34 | // .build(); 35 | return GroupedOpenApi.builder() 36 | .group("hyena") 37 | .packagesToScan("io.github.alphajiang.hyena.rest") 38 | .build(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/NumberUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | public class NumberUtils { 21 | 22 | 23 | public static long parseLong(String val, long defaultValue) { 24 | long ret = defaultValue; 25 | try { 26 | ret = Long.parseLong(val); 27 | } catch (Exception ignored) { 28 | 29 | } 30 | return ret; 31 | } 32 | 33 | public static long parseLong(byte[] val, long defaultValue) { 34 | if (val == null) { 35 | return defaultValue; 36 | } else { 37 | return NumberUtils.parseLong(new String(val), defaultValue); 38 | } 39 | } 40 | 41 | 42 | public static boolean longEquals(Long va, Long vb) { 43 | if (va == null && vb == null) { 44 | return true; 45 | } else if (va == null || vb == null) { 46 | return false; 47 | } else return va.longValue() == vb.longValue(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/biz/cache/TestPointRedisCacheService.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.biz.cache; 2 | 3 | import io.github.alphajiang.hyena.biz.strategy.TestPointStrategyBase; 4 | import io.github.alphajiang.hyena.model.vo.PointVo; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.junit.jupiter.api.Test; 7 | import org.mockito.Mockito; 8 | import org.springframework.beans.BeanUtils; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.mock.mockito.MockBean; 11 | import org.springframework.data.redis.core.RedisTemplate; 12 | 13 | import java.util.List; 14 | 15 | @Slf4j 16 | public class TestPointRedisCacheService extends TestPointStrategyBase { 17 | 18 | @Autowired 19 | private PointRedisCacheService pointRedisCacheService; 20 | 21 | @MockBean 22 | private RedisTemplate redisStringTemplate; 23 | 24 | 25 | @Test 26 | public void test_updatePoint() { 27 | PointVo pv = new PointVo(); 28 | BeanUtils.copyProperties(super.getUserPoint(), pv); 29 | 30 | Mockito.when(redisStringTemplate.exec(Mockito.any())).thenReturn(List.of(Boolean.TRUE)); 31 | 32 | //log.info("aaaaaaaaaaaaaaaa"); 33 | //for(int i = 0; i < 1000; i ++) { 34 | log.info("before updatePoint"); 35 | pointRedisCacheService.lock(super.getPointType(), super.getUid(), super.getSubUid(), 5) 36 | .flatMap(lockRet -> pointRedisCacheService.updatePoint(super.getPointType(), super.getUid(), super.getSubUid(), pv)) 37 | .subscribe(); 38 | log.info("after updatePoint"); 39 | //} 40 | //log.info("bbbbbbbbbbbbbb"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/FreezeOrderRecMapper.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | insert into `${pointTableName}_freeze_order_rec` ( 8 | `id`, 9 | `pid`, `uid`, `subUid`, `recId`, `seqNum`, 10 | `orderType`, 11 | `frozen`, `frozenCost`, 12 | `orderNo` 13 | ) 14 | 15 | #{for.id}, 16 | #{for.pid}, #{for.uid}, #{for.subUid}, #{for.recId}, #{for.seqNum}, 17 | #{for.orderType}, 18 | #{for.frozen}, #{for.frozenCost}, 19 | #{for.orderNo} 20 | 21 | 22 | 23 | 24 | 25 | update `${pointTableName}_freeze_order_rec` 26 | set `enable` = false, updateTime = now() 27 | where 28 | 29 | #{id} 30 | 31 | 32 | 33 | 34 | 45 | 46 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/dto/PointRecLogDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.dto; 19 | 20 | import com.fasterxml.jackson.annotation.JsonInclude; 21 | import io.github.alphajiang.hyena.model.po.PointRecLogPo; 22 | import io.swagger.v3.oas.annotations.media.Schema; 23 | import lombok.Data; 24 | import lombok.EqualsAndHashCode; 25 | import lombok.ToString; 26 | import lombok.experimental.Accessors; 27 | 28 | import java.math.BigDecimal; 29 | 30 | @Data 31 | @Accessors(chain = true) 32 | @EqualsAndHashCode(callSuper = true) 33 | @ToString(callSuper = true) 34 | public class PointRecLogDto extends PointRecLogPo { 35 | 36 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 37 | private String uid; 38 | 39 | private BigDecimal total; 40 | 41 | 42 | @Schema(title = "变动记录的订单号") 43 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 44 | private String orderNo; 45 | 46 | @Schema(title = "创建积分块的订单号") 47 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 48 | private String recOrigOrderNo; 49 | } 50 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/task/MemCacheTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.task; 19 | 20 | import io.github.alphajiang.hyena.biz.cache.PointMemCacheService; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.beans.factory.annotation.Value; 24 | import org.springframework.scheduling.annotation.Scheduled; 25 | import org.springframework.stereotype.Component; 26 | 27 | @Slf4j 28 | @Component 29 | public class MemCacheTask { 30 | 31 | @Value("${hyena.mem.task.duration:10}") 32 | private long expireRate; 33 | 34 | private long idx = 0L; 35 | 36 | @Autowired 37 | private PointMemCacheService pointMemCacheService; 38 | 39 | @Scheduled(fixedRate = 60 * 1000, initialDelay = 30 * 1000) // every minutes 40 | public void memCacheTask() { 41 | //log.debug(">>"); 42 | if (idx % expireRate == 0) { 43 | pointMemCacheService.expireCache(); 44 | } 45 | idx++; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/JacksonStringSerialize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import com.fasterxml.jackson.core.JsonGenerator; 21 | import com.fasterxml.jackson.databind.JsonNode; 22 | import com.fasterxml.jackson.databind.JsonSerializer; 23 | import com.fasterxml.jackson.databind.SerializerProvider; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.io.IOException; 28 | 29 | public class JacksonStringSerialize extends JsonSerializer { 30 | private static final Logger logger = LoggerFactory.getLogger(JacksonStringSerialize.class); 31 | 32 | @Override 33 | public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { 34 | // 35 | if (value != null) { 36 | try { 37 | gen.writeObject(JsonUtils.fromJson(value, JsonNode.class)); 38 | 39 | } catch (Exception e) { 40 | logger.warn(e.getMessage(), e); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/utils/TestDecimalUtils.java: -------------------------------------------------------------------------------- 1 | package io.github.alphajiang.hyena.utils; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.math.BigDecimal; 7 | 8 | public class TestDecimalUtils { 9 | 10 | 11 | @Test 12 | public void test_lt() { 13 | Assertions.assertTrue(DecimalUtils.lt(BigDecimal.valueOf(100), BigDecimal.valueOf(123))); 14 | Assertions.assertFalse(DecimalUtils.lt(BigDecimal.valueOf(100), BigDecimal.valueOf(100))); 15 | Assertions.assertFalse(DecimalUtils.lt(BigDecimal.valueOf(123), BigDecimal.valueOf(100))); 16 | } 17 | 18 | @Test 19 | public void test_lte() { 20 | Assertions.assertTrue(DecimalUtils.lte(BigDecimal.valueOf(100), BigDecimal.valueOf(123))); 21 | Assertions.assertTrue(DecimalUtils.lte(BigDecimal.valueOf(100), BigDecimal.valueOf(100))); 22 | Assertions.assertFalse(DecimalUtils.lte(BigDecimal.valueOf(123), BigDecimal.valueOf(100))); 23 | } 24 | 25 | @Test 26 | public void test_gt() { 27 | Assertions.assertFalse(DecimalUtils.gt(BigDecimal.valueOf(100), BigDecimal.valueOf(123))); 28 | Assertions.assertFalse(DecimalUtils.gt(BigDecimal.valueOf(100), BigDecimal.valueOf(100))); 29 | Assertions.assertTrue(DecimalUtils.gt(BigDecimal.valueOf(123), BigDecimal.valueOf(100))); 30 | } 31 | 32 | @Test 33 | public void test_gte() { 34 | Assertions.assertFalse(DecimalUtils.gte(BigDecimal.valueOf(100), BigDecimal.valueOf(123))); 35 | Assertions.assertTrue(DecimalUtils.gte(BigDecimal.valueOf(100), BigDecimal.valueOf(100))); 36 | Assertions.assertTrue(DecimalUtils.gte(BigDecimal.valueOf(123), BigDecimal.valueOf(100))); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/task/TestExpirePointTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.task; 19 | 20 | import io.github.alphajiang.hyena.HyenaTestBase; 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | 27 | import java.util.Calendar; 28 | 29 | public class TestExpirePointTask extends HyenaTestBase { 30 | private final Logger logger = LoggerFactory.getLogger(TestExpirePointTask.class); 31 | 32 | @Autowired 33 | private ExpirePointTask expirePointTask; 34 | 35 | 36 | @BeforeEach 37 | public void init() { 38 | Calendar calExpire = Calendar.getInstance(); 39 | calExpire.add(Calendar.MINUTE, -1); 40 | super.getInitialPointUsage().setExpireTime(calExpire.getTime()); 41 | super.init(); 42 | 43 | } 44 | 45 | @Test 46 | public void test_expirePointTask() { 47 | this.expirePointTask.expirePointTask(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/ListPointRecLogParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.swagger.v3.oas.annotations.media.Schema; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | 26 | import java.util.List; 27 | 28 | @Data 29 | @Accessors(chain = true) 30 | @EqualsAndHashCode(callSuper = true) 31 | @ToString(callSuper = true) 32 | public class ListPointRecLogParam extends BaseListParam { 33 | 34 | 35 | @Schema(title = "用户ID") 36 | private String uid; 37 | 38 | @Schema(title = "用户二级ID") 39 | private String subUid; 40 | 41 | @Schema(title = "用户记录ID") 42 | private long pid; 43 | 44 | @Schema(title = "变更流水号") 45 | private List seqNumList; 46 | 47 | @Schema(title = "积分记录ID") 48 | private List recIdList; 49 | 50 | @Schema(title = "变更的订单号") 51 | private List orderNoList; 52 | 53 | @Schema(title = "标签") 54 | private String tag; 55 | 56 | 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/base/BaseObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.base; 19 | 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import org.apache.logging.log4j.LogManager; 24 | 25 | public abstract class BaseObject { 26 | 27 | public String toJsonString() { 28 | String ret = ""; 29 | ObjectMapper om = new ObjectMapper(); 30 | try { 31 | ret = om.writeValueAsString(this); 32 | } catch (JsonProcessingException e) { 33 | LogManager.getLogger(this).trace(e.getMessage(), e); 34 | 35 | } 36 | return ret; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | String ret = ""; 42 | ObjectMapper om = new ObjectMapper(); 43 | try { 44 | ret = om.writeValueAsString(this); 45 | } catch (JsonProcessingException e) { 46 | LogManager.getLogger(this).trace(e.getMessage(), e); 47 | 48 | } 49 | return ret; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/point/strategy/PointStrategyFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.point.strategy; 19 | 20 | import io.github.alphajiang.hyena.model.type.CalcType; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | import java.util.Optional; 25 | 26 | public class PointStrategyFactory { 27 | 28 | private static PointStrategyFactory instance; 29 | private Map strategyMap = new HashMap<>(); 30 | 31 | public static void addStrategy(PointStrategy strategy) { 32 | PointStrategyFactory fact = PointStrategyFactory.getInstance(); 33 | fact.strategyMap.put(strategy.getType(), strategy); 34 | } 35 | 36 | public static Optional getStrategy(CalcType type) { 37 | return Optional.ofNullable(PointStrategyFactory.getInstance().strategyMap.get(type)); 38 | } 39 | 40 | 41 | private static synchronized PointStrategyFactory getInstance() { 42 | if (instance == null) { 43 | instance = new PointStrategyFactory(); 44 | } 45 | return instance; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/base/ListResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.base; 19 | 20 | import io.swagger.v3.oas.annotations.media.Schema; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | public class ListResponse extends BaseResponse { 26 | 27 | @Schema(title = "总数据条数") 28 | private long total; 29 | 30 | @Schema(title = "返回结果的数据部分") 31 | private List data; 32 | 33 | public ListResponse() { 34 | data = new ArrayList<>(); 35 | total = 0L; 36 | } 37 | 38 | public ListResponse(List data) { 39 | this.data = data; 40 | } 41 | 42 | public ListResponse(List data, long total) { 43 | this.total = total; 44 | this.data = data; 45 | } 46 | 47 | public long getTotal() { 48 | return total; 49 | } 50 | 51 | public void setTotal(long total) { 52 | this.total = total; 53 | } 54 | 55 | public List getData() { 56 | return data; 57 | } 58 | 59 | public void setData(List data) { 60 | this.data = data; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/FreezeOrderRecMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import io.github.alphajiang.hyena.model.po.FreezeOrderRecPo; 21 | import org.apache.ibatis.annotations.Mapper; 22 | import org.apache.ibatis.annotations.Param; 23 | 24 | import java.util.List; 25 | 26 | @Mapper 27 | public interface FreezeOrderRecMapper { 28 | 29 | 30 | void batchInsert(@Param(value = "pointTableName") String pointTableName, 31 | @Param(value = "freezeOrderRecList") List freezeOrderRecList); 32 | 33 | 34 | void closeByIdList(@Param(value = "pointTableName") String pointTableName, 35 | @Param(value = "idList") List idList); 36 | 37 | List getFreezeOrderRecList(@Param(value = "pointTableName") String pointTableName, 38 | @Param(value = "pid") long pid, 39 | @Param(value = "orderType") Integer orderType, 40 | @Param(value = "orderNo") String orderNo); 41 | } 42 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/exception/BaseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.exception; 19 | 20 | import org.slf4j.event.Level; 21 | 22 | public class BaseException extends RuntimeException { 23 | 24 | private final int code; 25 | 26 | private final Level logLevel; 27 | 28 | 29 | BaseException(int code, String msg) { 30 | super(msg); 31 | this.code = code; 32 | logLevel = Level.ERROR; 33 | } 34 | 35 | BaseException(int code, String msg, Throwable e) { 36 | super(msg, e); 37 | this.code = code; 38 | logLevel = Level.ERROR; 39 | } 40 | 41 | 42 | BaseException(int code, String msg, Level logLevel) { 43 | super(msg); 44 | this.code = code; 45 | this.logLevel = logLevel; 46 | } 47 | 48 | public BaseException(int code, String msg, Level logLevel, Throwable e) { 49 | super(msg, e); 50 | this.code = code; 51 | this.logLevel = logLevel; 52 | } 53 | 54 | public int getCode() { 55 | return code; 56 | } 57 | 58 | public Level getLogLevel() { 59 | return logLevel; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import java.text.ParseException; 21 | import java.text.SimpleDateFormat; 22 | import java.util.Calendar; 23 | 24 | public class DateUtils { 25 | 26 | public static String toYyyyMmDdHhMmSs(Calendar cal) { 27 | return DateUtils.toStringFormat(cal, "yyyy-MM-dd HH:mm:ss"); 28 | } 29 | 30 | public static String toStringFormat(Calendar cal, String pattern) { 31 | if (cal == null) { 32 | return ""; 33 | } 34 | SimpleDateFormat sdf = new SimpleDateFormat(pattern); 35 | return sdf.format(cal.getTime()); 36 | } 37 | 38 | 39 | public static Calendar fromYyyyMmDdHhMmSs(String str) throws ParseException { 40 | return DateUtils.fromStringFormat(str, "yyyy-MM-dd HH:mm:ss"); 41 | } 42 | 43 | public static Calendar fromStringFormat(String str, String pattern) throws ParseException { 44 | 45 | SimpleDateFormat sdf = new SimpleDateFormat(pattern); 46 | Calendar cal = Calendar.getInstance(); 47 | cal.setTime(sdf.parse(str)); 48 | return cal; 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/point/PointCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.point; 19 | 20 | import io.github.alphajiang.hyena.model.exception.HyenaServiceException; 21 | import io.github.alphajiang.hyena.model.vo.PointVo; 22 | import java.util.Date; 23 | import java.util.concurrent.Semaphore; 24 | import java.util.concurrent.TimeUnit; 25 | import lombok.Data; 26 | import lombok.ToString; 27 | import lombok.ToString.Exclude; 28 | import lombok.experimental.Accessors; 29 | 30 | @Data 31 | @Accessors(chain = true) 32 | @ToString 33 | public class PointCache { 34 | 35 | //private Long pid; 36 | private String key; // type + uid 37 | 38 | private PointVo point; 39 | 40 | 41 | private Date updateTime; 42 | 43 | @Exclude 44 | private Semaphore lock = new Semaphore(1); 45 | 46 | public void lock() { 47 | try { 48 | this.lock.tryAcquire(10, TimeUnit.SECONDS); 49 | } catch (InterruptedException e) { 50 | throw new HyenaServiceException("get lock failed", e); 51 | } 52 | } 53 | 54 | public void unlock() { 55 | this.lock.release(); 56 | } 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/PointRecLogMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import io.github.alphajiang.hyena.model.dto.PointRecLogDto; 21 | import io.github.alphajiang.hyena.model.param.ListPointRecLogParam; 22 | import io.github.alphajiang.hyena.model.po.PointRecLogPo; 23 | import org.apache.ibatis.annotations.Mapper; 24 | import org.apache.ibatis.annotations.Param; 25 | 26 | import java.util.List; 27 | 28 | @Mapper 29 | public interface PointRecLogMapper { 30 | void addPointRecLog(@Param(value = "tableName") String tableName, 31 | @Param(value = "recLog") PointRecLogPo recLog); 32 | 33 | void batchInsert(@Param(value = "tableName") String tableName, 34 | @Param(value = "recLogs") List recLogs); 35 | 36 | List listPointRecLog(@Param(value = "pointTableName") String pointTableName, 37 | @Param(value = "param") ListPointRecLogParam param); 38 | 39 | Long countPointRecLog(@Param(value = "pointTableName") String pointTableName, 40 | @Param(value = "param") ListPointRecLogParam param); 41 | } 42 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/ListPointLogParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.swagger.v3.oas.annotations.media.Schema; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | 26 | import java.util.List; 27 | @Data 28 | @Accessors(chain = true) 29 | @EqualsAndHashCode(callSuper = true) 30 | @ToString(callSuper = true) 31 | public class ListPointLogParam extends BaseListParam { 32 | @Schema(title = "用户ID") 33 | private String uid; 34 | 35 | @Schema(title = "用户二级ID") 36 | private String subUid; 37 | 38 | @Schema(title = "积分记录ID") 39 | private long pid; 40 | 41 | @Schema(title = "积分记录序号") 42 | private long seqNum = 0L; 43 | 44 | 45 | @Schema(title = "标签") 46 | private String tag; 47 | 48 | @Schema(title = "订单号") 49 | private String orderNo; 50 | 51 | @Schema(title = "创建时间过滤器") 52 | private TimeFilter createTimeFilter; 53 | 54 | // PointStatus 55 | 56 | private List logTypes; 57 | 58 | private List sourceTypes; 59 | private List orderTypes; 60 | private List payTypes; 61 | } 62 | -------------------------------------------------------------------------------- /hyena-core/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | archivesBaseName = "hyena-core" 3 | 4 | sourceSets { 5 | main { 6 | resources { 7 | srcDirs "src/main/resources", "src/main/java" 8 | } 9 | } 10 | } 11 | 12 | //jar { 13 | // enabled = true 14 | //} 15 | 16 | 17 | test { 18 | include 'io/github/alphajiang/hyena/**' 19 | useJUnitPlatform() 20 | } 21 | 22 | dependencies { 23 | 24 | implementation("org.springframework.boot:spring-boot-starter-webflux:${springBootVersion}") 25 | implementation "org.springframework.boot:spring-boot-starter-aop:${springBootVersion}" 26 | implementation("org.springframework.boot:spring-boot-starter-jdbc:${springBootVersion}") 27 | // implementation("org.springframework.boot:spring-boot-starter-data-redis:${springBootVersion}") 28 | implementation "org.springframework.boot:spring-boot-starter-validation:${springBootVersion}" 29 | implementation("org.springframework.boot:spring-boot-starter-cache:${springBootVersion}") 30 | implementation("org.springframework.boot:spring-boot-starter-data-redis-reactive:${springBootVersion}") 31 | implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:${mybatisStarterVersion}") 32 | 33 | implementation("org.springdoc:springdoc-openapi-ui:${springdocVersion}") 34 | 35 | 36 | implementation("org.ehcache:ehcache:${ehcacheVersion}") 37 | 38 | testRuntimeOnly("org.apache.commons:commons-pool2:${commonsPoolVersion}") 39 | 40 | compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' 41 | 42 | testRuntimeOnly('com.h2database:h2:1.4.200') 43 | testImplementation("org.springframework.boot:spring-boot-starter-test:${springBootVersion}") 44 | testImplementation platform('io.projectreactor:reactor-bom:2020.0.16') 45 | testImplementation('io.projectreactor:reactor-test') 46 | 47 | 48 | } 49 | 50 | 51 | //signing { 52 | // sign configurations.archives 53 | //} 54 | 55 | -------------------------------------------------------------------------------- /hyena-spring-boot-starter-demo/src/main/java/io/github/alphajiang/hyena/demo/HyenaDemoMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.demo; 19 | 20 | import org.mybatis.spring.annotation.MapperScan; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.springframework.boot.WebApplicationType; 24 | import org.springframework.boot.autoconfigure.SpringBootApplication; 25 | import org.springframework.boot.builder.SpringApplicationBuilder; 26 | import org.springframework.context.annotation.ComponentScan; 27 | import org.springframework.scheduling.annotation.EnableScheduling; 28 | import org.springframework.transaction.annotation.EnableTransactionManagement; 29 | 30 | @SpringBootApplication 31 | @ComponentScan({"io.github.alphajiang.hyena"}) 32 | @MapperScan(basePackages = {"io.github.alphajiang.hyena.ds.mapper"}) 33 | @EnableTransactionManagement 34 | @EnableScheduling 35 | public class HyenaDemoMain { 36 | private static final Logger logger = LoggerFactory.getLogger(HyenaDemoMain.class); 37 | 38 | public static void main(String[] args) { 39 | logger.info("starting......"); 40 | new SpringApplicationBuilder(HyenaDemoMain.class).web(WebApplicationType.REACTIVE).run(args); 41 | logger.info("started"); 42 | } 43 | } -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/ListPointRecParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.swagger.v3.oas.annotations.media.Schema; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.ToString; 24 | import lombok.experimental.Accessors; 25 | 26 | import java.util.Date; 27 | import java.util.List; 28 | 29 | @Data 30 | @Accessors(chain = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | @ToString(callSuper = true) 33 | public class ListPointRecParam extends BaseListParam { 34 | 35 | @Schema(title = "积分记录ID") 36 | private List recIdList; 37 | 38 | @Schema(title = "用户ID") 39 | private String uid; 40 | 41 | @Schema(title = "用户二级ID") 42 | private String subUid; 43 | 44 | @Schema(title = "标签") 45 | private String tag; 46 | 47 | @Schema(title = "创建积分的序列号列表") 48 | private List seqNumList; 49 | 50 | @Schema(title = "创建积分的订单号") 51 | private List orderNos; 52 | 53 | @Schema(title = "是否获取积分块对应的流水明细", example = "false") 54 | private Boolean fetchRecLogs; 55 | 56 | //private boolean available = false; 57 | private Boolean cost; 58 | private Boolean frozen; 59 | private Date expireTime; 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/HyenaTestMain.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /* 5 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | */ 20 | 21 | package io.github.alphajiang.hyena; 22 | 23 | import io.github.alphajiang.hyena.biz.idempotent.HyenaIdempotent; 24 | import io.github.alphajiang.hyena.biz.idempotent.HyenaMemIdempotent; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | import org.springframework.boot.SpringApplication; 28 | import org.springframework.boot.autoconfigure.SpringBootApplication; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.ComponentScan; 31 | import org.springframework.transaction.annotation.EnableTransactionManagement; 32 | 33 | 34 | @ComponentScan(basePackages = {"io.github.alphajiang.hyena"}) 35 | @SpringBootApplication 36 | @EnableTransactionManagement 37 | public class HyenaTestMain { 38 | private final static Logger logger = LoggerFactory.getLogger(HyenaTestMain.class); 39 | 40 | public static void main(String[] args) { 41 | logger.info("starting...."); 42 | SpringApplication.run(HyenaTestMain.class, args); 43 | logger.info("started"); 44 | } 45 | 46 | @Bean(name = "hyenaIdempotent") 47 | public HyenaIdempotent hyenaIdempotent() { 48 | return new HyenaMemIdempotent(); 49 | } 50 | } -------------------------------------------------------------------------------- /hyena-spring-boot-starter-demo/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | plugins { 3 | id 'org.springframework.boot' 4 | id 'io.spring.dependency-management' 5 | } 6 | 7 | sourceSets { 8 | main { 9 | resources { 10 | srcDirs "src/main/resources", "src/main/java" 11 | } 12 | } 13 | } 14 | 15 | dependencyManagement { 16 | imports { 17 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation project(':hyena-spring-boot-starter') 23 | 24 | implementation("org.springframework.boot:spring-boot-starter:${springBootVersion}") 25 | // implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") 26 | implementation("org.springframework.boot:spring-boot-starter-webflux:${springBootVersion}") 27 | implementation("org.springframework.boot:spring-boot-starter-jdbc:${springBootVersion}") 28 | implementation "org.springframework.boot:spring-boot-starter-aop:${springBootVersion}" 29 | implementation("org.springframework.boot:spring-boot-starter-cache:${springBootVersion}") 30 | implementation('org.springframework.boot:spring-boot-starter-actuator') 31 | implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:${mybatisStarterVersion}") 32 | implementation("org.springdoc:springdoc-openapi-ui:${springdocVersion}") 33 | implementation("org.springdoc:springdoc-openapi-webflux-ui:${springdocVersion}") 34 | 35 | 36 | implementation 'io.micrometer:micrometer-tracing-bridge-brave' 37 | implementation 'io.zipkin.reporter2:zipkin-reporter-brave' 38 | implementation 'io.github.openfeign:feign-micrometer' 39 | 40 | implementation('net.logstash.logback:logstash-logback-encoder:8.0') 41 | implementation("org.ehcache:ehcache:${ehcacheVersion}") 42 | 43 | 44 | runtimeOnly("org.apache.commons:commons-pool2:${commonsPoolVersion}") 45 | 46 | runtimeOnly('mysql:mysql-connector-java:8.0.23') 47 | 48 | } 49 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointIncreaseParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import com.fasterxml.jackson.annotation.JsonFormat; 21 | import io.github.alphajiang.hyena.utils.JsonUtils; 22 | import io.swagger.v3.oas.annotations.media.Schema; 23 | import lombok.Data; 24 | import lombok.EqualsAndHashCode; 25 | import lombok.ToString; 26 | import lombok.experimental.Accessors; 27 | import org.springframework.lang.Nullable; 28 | 29 | import java.math.BigDecimal; 30 | import java.util.Date; 31 | 32 | @Data 33 | @Accessors(chain = true) 34 | @EqualsAndHashCode(callSuper = true) 35 | public class PointIncreaseParam extends PointOpParam { 36 | 37 | 38 | @Nullable 39 | @Schema(title = "实际成本", example = "1.00") 40 | private BigDecimal cost; 41 | 42 | @Nullable 43 | @Schema(title = "获取积分时间", example = "2005-12-25 15:34:46") 44 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 45 | private Date issueTime; 46 | 47 | @Nullable 48 | @Schema(title = "过期时间", example = "2025-10-24 15:34:46") 49 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 50 | private Date expireTime; 51 | 52 | @Override 53 | public String toString() { 54 | return JsonUtils.toJsonString(this); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/CollectionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import java.util.Collection; 21 | 22 | public class CollectionUtils { 23 | public static boolean isEmpty(final Collection coll) { 24 | return coll == null || coll.isEmpty(); 25 | } 26 | 27 | public static boolean isNotEmpty(final Collection coll) { 28 | return !CollectionUtils.isEmpty(coll); 29 | } 30 | 31 | public static String join(final Collection coll, String separate) { 32 | if (isEmpty(coll)) { 33 | return ""; 34 | } 35 | StringBuilder buf = new StringBuilder(); 36 | coll.stream().filter(a -> a != null).forEach(o -> { 37 | 38 | if (o instanceof Character) { 39 | buf.append(separate).append((Character) o); 40 | } else if (o instanceof String) { 41 | if (StringUtils.isNotBlank((String) o)) { 42 | buf.append(separate).append((String) o); 43 | } 44 | } else { 45 | buf.append(separate).append(o.toString()); 46 | } 47 | }); 48 | if (buf.length() < separate.length()) { 49 | return ""; 50 | } else { 51 | return buf.substring(separate.length()); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/biz/TestPointUsageFacade.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz; 19 | 20 | import io.github.alphajiang.hyena.HyenaTestBase; 21 | import io.github.alphajiang.hyena.biz.point.PSession; 22 | import io.github.alphajiang.hyena.biz.point.PointUsage; 23 | import io.github.alphajiang.hyena.biz.point.PointUsageFacade; 24 | import io.github.alphajiang.hyena.model.po.PointPo; 25 | import org.junit.jupiter.api.Assertions; 26 | import org.junit.jupiter.api.Test; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | import org.springframework.beans.factory.annotation.Autowired; 30 | 31 | import java.math.BigDecimal; 32 | 33 | public class TestPointUsageFacade extends HyenaTestBase { 34 | private final Logger logger = LoggerFactory.getLogger(TestPointUsageFacade.class); 35 | 36 | @Autowired 37 | private PointUsageFacade pointUsageFacade; 38 | 39 | 40 | @Test 41 | public void test_increase() { 42 | PointUsage usage = new PointUsage(); 43 | usage.setType(super.getPointType()).setUid("test_increase") 44 | .setPoint(BigDecimal.valueOf(99887L)); 45 | PointPo ret = this.pointUsageFacade.increase(PSession.fromUsage(usage)) 46 | .block() 47 | .getResult(); 48 | logger.info("point = {}", ret); 49 | Assertions.assertNotNull(ret); 50 | 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/point/PointUsage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.point; 19 | 20 | import io.github.alphajiang.hyena.model.base.BaseObject; 21 | import io.github.alphajiang.hyena.utils.JsonUtils; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | 27 | import java.math.BigDecimal; 28 | import java.util.Date; 29 | 30 | @Data 31 | @Accessors(chain = true) 32 | @EqualsAndHashCode(callSuper = true) 33 | public class PointUsage extends BaseObject { 34 | private String type; 35 | private String uid; 36 | private String subUid; 37 | private String name; 38 | private BigDecimal point; 39 | private BigDecimal unfreezePoint; // 消费积分时同时解冻的积分数量 40 | private BigDecimal cost; 41 | private Boolean unfreezeByOrderNo; 42 | private Long recId; // 积分记录的ID 43 | private String recOrderNo; // 创建积分记录对应的订单号 44 | private String tag; 45 | private String orderNo; 46 | 47 | private Integer sourceType; 48 | private Integer orderType; 49 | private Integer payType; 50 | private String extra; 51 | private String note; 52 | private Date issueTime; 53 | private Date expireTime; 54 | 55 | private boolean doUpdate = true; 56 | 57 | // private PointWrapper pw; 58 | 59 | @Override 60 | public String toString() { 61 | return JsonUtils.toJsonString(this); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/vo/PointVo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.vo; 19 | 20 | import io.github.alphajiang.hyena.model.po.FreezeOrderRecPo; 21 | import io.github.alphajiang.hyena.model.po.PointPo; 22 | import io.github.alphajiang.hyena.model.po.PointRecPo; 23 | import io.github.alphajiang.hyena.utils.CollectionUtils; 24 | import io.github.alphajiang.hyena.utils.JsonUtils; 25 | import lombok.Data; 26 | import lombok.EqualsAndHashCode; 27 | import lombok.ToString; 28 | import lombok.ToString.Exclude; 29 | import lombok.experimental.Accessors; 30 | 31 | import java.util.HashMap; 32 | import java.util.List; 33 | import java.util.Map; 34 | import java.util.stream.Collectors; 35 | 36 | @Data 37 | @Accessors(chain = true) 38 | @EqualsAndHashCode(callSuper = true) 39 | @ToString 40 | public class PointVo extends PointPo { 41 | 42 | @Exclude 43 | private List recList; 44 | 45 | 46 | @Exclude 47 | private Map forList; 48 | 49 | public synchronized void addForList(List inForList) { 50 | if (CollectionUtils.isEmpty(inForList)) { 51 | return; 52 | } 53 | if (forList == null) { 54 | forList = new HashMap<>(); 55 | } 56 | this.forList.putAll(inForList.stream().collect(Collectors.toMap(o -> o.getId(), o -> o, (l, r) -> l))); 57 | } 58 | 59 | // @Override 60 | // public String toString() { 61 | // return JsonUtils.toJsonString(this); 62 | // } 63 | } 64 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import io.github.alphajiang.hyena.HyenaConstants; 21 | 22 | public class StringUtils { 23 | public static String upperCase(final String str) { 24 | if (str == null) { 25 | return null; 26 | } 27 | return str.toUpperCase(); 28 | } 29 | 30 | public static boolean equals(final String cs1, final String cs2) { 31 | if (cs1 == cs2) { 32 | return true; 33 | } 34 | if (cs1 == null || cs2 == null) { 35 | return false; 36 | } 37 | if (cs1.length() != cs2.length()) { 38 | return false; 39 | } 40 | return cs1.equals(cs2); 41 | } 42 | 43 | public static boolean isBlank(final String cs) { 44 | int strLen; 45 | if (cs == null || (strLen = cs.length()) == 0) { 46 | return true; 47 | } 48 | for (int i = 0; i < strLen; i++) { 49 | if (!Character.isWhitespace(cs.charAt(i))) { 50 | return false; 51 | } 52 | } 53 | return true; 54 | } 55 | 56 | public static boolean isNotBlank(final String cs) { 57 | return !isBlank(cs); 58 | } 59 | 60 | public static String replaceFirst(final String str, final String prefix) { 61 | if (isBlank(str)) { 62 | return ""; 63 | } 64 | return str.replaceFirst(HyenaConstants.PREFIX_POINT_TABLE_NAME, ""); 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/utils/TestJsonUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import com.fasterxml.jackson.core.type.TypeReference; 21 | import io.github.alphajiang.hyena.model.base.BaseResponse; 22 | import io.github.alphajiang.hyena.model.base.ObjectResponse; 23 | import io.github.alphajiang.hyena.model.exception.HyenaServiceException; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.junit.jupiter.api.Assertions; 26 | import org.junit.jupiter.api.Test; 27 | 28 | @Slf4j 29 | public class TestJsonUtils { 30 | 31 | @Test 32 | public void test_fromJson() { 33 | var obj = new BaseResponse(123, "gewlgejwg"); 34 | String str = obj.toJsonString(); 35 | log.info("json str = {}", str); 36 | BaseResponse result = JsonUtils.fromJson(str, BaseResponse.class); 37 | HyenaAssert.notNull(result, "result is not null"); 38 | } 39 | 40 | @Test 41 | public void test_fromJson_class_fail() { 42 | String str = "{ 123}"; 43 | Assertions.assertThrows(HyenaServiceException.class, () -> { 44 | JsonUtils.fromJson(str, BaseResponse.class); 45 | Assertions.fail(); 46 | }); 47 | } 48 | 49 | @Test 50 | public void test_fromJson_type_fail() { 51 | String str = "{ 123}"; 52 | Assertions.assertThrows(HyenaServiceException.class, () -> { 53 | JsonUtils.fromJson(str, new TypeReference>() { 54 | }); 55 | Assertions.fail(); 56 | }); 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/base/BaseResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.base; 19 | 20 | import com.fasterxml.jackson.annotation.JsonInclude; 21 | import io.github.alphajiang.hyena.HyenaConstants; 22 | 23 | public class BaseResponse extends BaseObject { 24 | 25 | 26 | private int status = HyenaConstants.RES_CODE_SUCCESS; 27 | 28 | private static final BaseResponse SUCCESS_RES = new BaseResponse(HyenaConstants.RES_CODE_SUCCESS); 29 | 30 | public static final BaseResponse success() { 31 | return SUCCESS_RES; 32 | } 33 | 34 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 35 | private String error = ""; 36 | 37 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 38 | private String seq; 39 | 40 | public BaseResponse() { 41 | 42 | } 43 | 44 | public BaseResponse(int status) { 45 | this.status = status; 46 | } 47 | 48 | public BaseResponse(int status, String error) { 49 | this.status = status; 50 | this.error = error; 51 | } 52 | 53 | 54 | 55 | public int getStatus() { 56 | return status; 57 | } 58 | 59 | public void setStatus(int status) { 60 | this.status = status; 61 | } 62 | 63 | public String getSeq() { 64 | return seq; 65 | } 66 | 67 | public void setSeq(String seq) { 68 | this.seq = seq; 69 | } 70 | 71 | public String getError() { 72 | return error; 73 | } 74 | 75 | public void setError(String error) { 76 | this.error = error; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/utils/TestCollectionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import org.junit.jupiter.api.Assertions; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public class TestCollectionUtils { 27 | 28 | @Test 29 | public void test_join_null() { 30 | String result = CollectionUtils.join(null, ","); 31 | Assertions.assertEquals("", result); 32 | } 33 | 34 | @Test 35 | public void test_join_string() { 36 | List list = new ArrayList<>(); 37 | list.add("aaa"); 38 | list.add(null); 39 | list.add("bbb"); 40 | String result = CollectionUtils.join(list, "=="); 41 | Assertions.assertEquals("aaa==bbb", result); 42 | } 43 | 44 | @Test 45 | public void test_join_empty() { 46 | String result = CollectionUtils.join(List.of("", ""), "=="); 47 | Assertions.assertEquals("", result); 48 | } 49 | 50 | @Test 51 | public void test_join_char() { 52 | String result = CollectionUtils.join(List.of(Character.valueOf('a'), Character.valueOf('b')), "-"); 53 | Assertions.assertEquals("a-b", result); 54 | } 55 | 56 | @Test 57 | public void test_join_int() { 58 | List list = new ArrayList<>(); 59 | list.add(123); 60 | list.add(null); 61 | list.add(456); 62 | String result = CollectionUtils.join(list, "-"); 63 | Assertions.assertEquals("123-456", result); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointUpdateQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.PointDs; 21 | import io.github.alphajiang.hyena.model.po.PointPo; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Service; 28 | 29 | import jakarta.annotation.PostConstruct; 30 | import java.util.concurrent.LinkedBlockingQueue; 31 | 32 | @Service 33 | public class PointUpdateQueue implements PointDsQueue { 34 | 35 | 36 | private LinkedBlockingQueue queue; 37 | 38 | private PointUpdateConsumer consumer; 39 | 40 | @Autowired 41 | private PointDs pointDs; 42 | 43 | @Autowired 44 | private QueueMonitor queueMonitor; 45 | 46 | @PostConstruct 47 | public void init() { 48 | queue = new LinkedBlockingQueue<>(); 49 | consumer = new PointUpdateConsumer(queue, pointDs); 50 | new Thread(consumer).start(); 51 | queueMonitor.addQueue(this); 52 | } 53 | 54 | public boolean offer(Point p) { 55 | return this.queue.offer(p); 56 | } 57 | 58 | @Override 59 | public int getQueueSize() { 60 | return queue.size(); 61 | } 62 | 63 | @Data 64 | @Accessors(chain = true) 65 | @EqualsAndHashCode(callSuper = true) 66 | @ToString(callSuper = true) 67 | public static class Point extends QueueItem { 68 | private PointPo point; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/SysPropertyMapper.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | create table if not exists t_sys_property ( 25 | id bigint(20) not null auto_increment primary key, 26 | `key` varchar(128) not null, 27 | `value` varchar(256) not null default '', 28 | `enable` boolean not null default true, 29 | `createTime` timestamp default now(), 30 | `updateTime` timestamp default now(), 31 | unique index t_sys_property_key(`key`) 32 | ) engine=InnoDB default charset=utf8mb4 33 | 34 | 35 | 36 | insert into t_sys_property(`key`, `value`, `enable`, createTime, updateTime) 37 | values(#{key}, #{value}, #{enable}, now(), now()) 38 | on duplicate key update 39 | value = #{value}, 40 | enable = #{enable}, 41 | updateTime = now() 42 | 43 | 44 | 47 | 48 | 49 | update t_sys_property set `value`=#{value}, 50 | updateTime = now() 51 | where `key`=#{key} 52 | 53 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointRecDsQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.PointRecDs; 21 | import io.github.alphajiang.hyena.model.po.PointRecPo; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Service; 28 | 29 | import jakarta.annotation.PostConstruct; 30 | import java.util.concurrent.LinkedBlockingQueue; 31 | 32 | @Service 33 | public class PointRecDsQueue implements PointDsQueue { 34 | 35 | 36 | private LinkedBlockingQueue queue; 37 | 38 | private PointRecDsConsumer consumer; 39 | 40 | @Autowired 41 | private PointRecDs pointRecDs; 42 | 43 | @Autowired 44 | private QueueMonitor queueMonitor; 45 | 46 | @PostConstruct 47 | public void init() { 48 | queue = new LinkedBlockingQueue<>(); 49 | consumer = new PointRecDsConsumer(queue, pointRecDs); 50 | new Thread(consumer).start(); 51 | queueMonitor.addQueue(this); 52 | } 53 | 54 | public boolean offer(PointRec pl) { 55 | return this.queue.offer(pl); 56 | } 57 | 58 | @Override 59 | public int getQueueSize() { 60 | return queue.size(); 61 | } 62 | 63 | @Data 64 | @Accessors(chain = true) 65 | @EqualsAndHashCode(callSuper = true) 66 | @ToString(callSuper = true) 67 | public static class PointRec extends QueueItem { 68 | private PointRecPo pointRec; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointLogFlowQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.PointLogDs; 21 | import io.github.alphajiang.hyena.model.po.PointLogPo; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Service; 28 | 29 | import jakarta.annotation.PostConstruct; 30 | import java.util.concurrent.LinkedBlockingQueue; 31 | 32 | @Service 33 | public class PointLogFlowQueue implements PointDsQueue { 34 | 35 | 36 | private LinkedBlockingQueue queue; 37 | 38 | private PointLogFlowConsumer consumer; 39 | 40 | @Autowired 41 | private PointLogDs pointLogDs; 42 | 43 | @Autowired 44 | private QueueMonitor queueMonitor; 45 | 46 | @PostConstruct 47 | public void init() { 48 | queue = new LinkedBlockingQueue<>(); 49 | consumer = new PointLogFlowConsumer(queue, pointLogDs); 50 | new Thread(consumer).start(); 51 | queueMonitor.addQueue(this); 52 | } 53 | 54 | public boolean offer(PointLog pl) { 55 | return this.queue.offer(pl); 56 | } 57 | 58 | @Override 59 | public int getQueueSize() { 60 | return queue.size(); 61 | } 62 | 63 | @Data 64 | @Accessors(chain = true) 65 | @EqualsAndHashCode(callSuper = true) 66 | @ToString(callSuper = true) 67 | public static class PointLog extends QueueItem { 68 | private PointLogPo pointLog; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/PointLogMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import io.github.alphajiang.hyena.model.dto.PointLogDto; 21 | import io.github.alphajiang.hyena.model.param.ListPointLogParam; 22 | import io.github.alphajiang.hyena.model.po.PointLogPo; 23 | import io.github.alphajiang.hyena.model.vo.PointLogBi; 24 | import org.apache.ibatis.annotations.Mapper; 25 | import org.apache.ibatis.annotations.Param; 26 | 27 | import java.util.List; 28 | 29 | @Mapper 30 | public interface PointLogMapper { 31 | long addPointLog(@Param(value = "pointTableName") String pointTableName, 32 | @Param(value = "pointLog") PointLogPo pointLog); 33 | 34 | void batchInsert(@Param(value = "pointTableName") String pointTableName, 35 | @Param(value = "pointLogList") List pointLogList); 36 | 37 | void updateAbnormal(@Param(value = "pointTableName") String pointTableName, 38 | @Param(value = "id") Long id, 39 | @Param(value = "abnormal") boolean abnormal); 40 | 41 | 42 | List listPointLog(@Param(value = "pointTableName") String pointTableName, 43 | @Param(value = "param") ListPointLogParam param); 44 | 45 | Long countPointLog(@Param(value = "pointTableName") String pointTableName, 46 | @Param(value = "param") ListPointLogParam param); 47 | 48 | 49 | List listPointLogBi(@Param(value = "pointTableName") String pointTableName, 50 | @Param(value = "param") ListPointLogParam param); 51 | } 52 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointRecLogFlowQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.PointRecLogDs; 21 | import io.github.alphajiang.hyena.model.po.PointRecLogPo; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Service; 28 | 29 | import jakarta.annotation.PostConstruct; 30 | import java.util.concurrent.LinkedBlockingQueue; 31 | 32 | @Service 33 | public class PointRecLogFlowQueue implements PointDsQueue { 34 | 35 | 36 | private LinkedBlockingQueue queue; 37 | 38 | private PointRecLogFlowConsumer consumer; 39 | 40 | @Autowired 41 | private PointRecLogDs pointRecLogDs; 42 | 43 | @Autowired 44 | private QueueMonitor queueMonitor; 45 | 46 | @PostConstruct 47 | public void init() { 48 | queue = new LinkedBlockingQueue<>(); 49 | consumer = new PointRecLogFlowConsumer(queue, pointRecLogDs); 50 | new Thread(consumer).start(); 51 | queueMonitor.addQueue(this); 52 | } 53 | 54 | public boolean offer(PointRecLog pl) { 55 | return this.queue.offer(pl); 56 | } 57 | 58 | @Override 59 | public int getQueueSize() { 60 | return queue.size(); 61 | } 62 | 63 | @Data 64 | @Accessors(chain = true) 65 | @EqualsAndHashCode(callSuper = true) 66 | @ToString(callSuper = true) 67 | public static class PointRecLog extends QueueItem { 68 | private PointRecLogPo pointRecLog; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/FreezeOrderRecDsQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.FreezeOrderRecDs; 21 | import io.github.alphajiang.hyena.model.po.FreezeOrderRecPo; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Service; 28 | 29 | import jakarta.annotation.PostConstruct; 30 | import java.util.concurrent.LinkedBlockingQueue; 31 | 32 | @Service 33 | public class FreezeOrderRecDsQueue implements PointDsQueue { 34 | 35 | 36 | private LinkedBlockingQueue queue; 37 | 38 | private FreezeOrderRecDsConsumer consumer; 39 | 40 | @Autowired 41 | private FreezeOrderRecDs freezeOrderRecDs; 42 | 43 | @Autowired 44 | private QueueMonitor queueMonitor; 45 | 46 | @PostConstruct 47 | public void init() { 48 | queue = new LinkedBlockingQueue<>(); 49 | consumer = new FreezeOrderRecDsConsumer(queue, freezeOrderRecDs); 50 | new Thread(consumer).start(); 51 | queueMonitor.addQueue(this); 52 | } 53 | 54 | public boolean offer(FreezeOrderRec pl) { 55 | return this.queue.offer(pl); 56 | } 57 | 58 | @Override 59 | public int getQueueSize() { 60 | return queue.size(); 61 | } 62 | 63 | @Data 64 | @Accessors(chain = true) 65 | @EqualsAndHashCode(callSuper = true) 66 | @ToString(callSuper = true) 67 | public static class FreezeOrderRec extends QueueItem { 68 | private FreezeOrderRecPo freezeOrderRec; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/ds/TestPointRecLogDs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds; 19 | 20 | import io.github.alphajiang.hyena.HyenaTestBase; 21 | import io.github.alphajiang.hyena.ds.service.PointRecLogDs; 22 | import io.github.alphajiang.hyena.model.po.PointRecLogPo; 23 | import io.github.alphajiang.hyena.model.type.PointOpType; 24 | import org.junit.jupiter.api.BeforeEach; 25 | import org.junit.jupiter.api.Test; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | 28 | import java.math.BigDecimal; 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | 32 | public class TestPointRecLogDs extends HyenaTestBase { 33 | 34 | @Autowired 35 | private PointRecLogDs pointRecLogDs; 36 | 37 | @BeforeEach 38 | public void init() { 39 | super.init(); 40 | } 41 | 42 | @Test 43 | public void test_batchInsert() { 44 | List logs = new ArrayList<>(); 45 | PointRecLogPo log1 = PointRecLogPo.buildRecLog(PointOpType.DECREASE); 46 | log1.setUsed(BigDecimal.valueOf(123L)); 47 | logs.add(log1); 48 | this.pointRecLogDs.batchInsert(super.getPointType(), logs); 49 | 50 | 51 | PointRecLogPo log2 = PointRecLogPo.buildRecLog(PointOpType.DECREASE); 52 | log2.setUsed(BigDecimal.valueOf(456L)); 53 | logs.add(log2); 54 | this.pointRecLogDs.batchInsert(super.getPointType(), logs); 55 | } 56 | 57 | @Test 58 | public void test_addPointRecLog() { 59 | PointRecLogPo log1 = PointRecLogPo.buildRecLog(PointOpType.INCREASE); 60 | log1.setUsed(BigDecimal.valueOf(11.1d)); 61 | 62 | this.pointRecLogDs.addPointRecLog(super.getPointType(), log1); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/PointOpParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.github.alphajiang.hyena.model.base.BaseObject; 21 | import io.swagger.v3.oas.annotations.media.Schema; 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.ToString; 25 | import lombok.experimental.Accessors; 26 | 27 | import java.math.BigDecimal; 28 | 29 | @Data 30 | @Accessors(chain = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | @ToString(callSuper = true) 33 | public class PointOpParam extends BaseObject { 34 | @Schema(title = "请求消息序列号", example = "", hidden = true) 35 | private String seq; 36 | 37 | @Schema(title = "积分类型", example = "score") 38 | private String type = "default"; 39 | 40 | @Schema(title = "用户ID", example = "customer_abc123") 41 | private String uid; 42 | 43 | @Schema(title = "用户二级ID", example = "customer_abc123") 44 | private String subUid; 45 | 46 | @Schema(title = "显示名称", example = "Tom") 47 | private String name; 48 | 49 | @Schema(title = "积分数量", example = "10.00") 50 | private BigDecimal point; 51 | 52 | @Schema(title = "指定操作的积分块ID", example = "123") 53 | private Long recId; 54 | 55 | @Schema(title = "标签", example = "") 56 | private String tag; 57 | 58 | @Schema(title = "变动相关的订单", example = "") 59 | private String orderNo; 60 | 61 | 62 | @Schema(title = "自定义来源") 63 | private Integer sourceType; 64 | @Schema(title = "自定义订单类型") 65 | private Integer orderType; 66 | @Schema(title = "自定义支付方式") 67 | private Integer payType; 68 | 69 | private Object extra; 70 | 71 | @Schema(title = "备注", example = "this is a note") 72 | private String note = ""; 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/service/FreezeOrderRecDs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.service; 19 | 20 | import io.github.alphajiang.hyena.ds.mapper.FreezeOrderRecMapper; 21 | import io.github.alphajiang.hyena.model.po.FreezeOrderRecPo; 22 | import io.github.alphajiang.hyena.utils.TableNameHelper; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.lang.NonNull; 25 | import org.springframework.stereotype.Service; 26 | 27 | import java.util.List; 28 | 29 | @Service 30 | public class FreezeOrderRecDs { 31 | 32 | @Autowired 33 | private FreezeOrderRecMapper freezeOrderRecMapper; 34 | 35 | @Autowired 36 | private PointTableDs pointTableDs; 37 | 38 | public void batchInsert(@NonNull String type, List freezeOrderRecList) { 39 | String pointTableName = TableNameHelper.getPointTableName(type); 40 | this.freezeOrderRecMapper.batchInsert(pointTableName, freezeOrderRecList); 41 | } 42 | 43 | public void closeByIdList(@NonNull String type, List idList) { 44 | String pointTableName = TableNameHelper.getPointTableName(type); 45 | this.freezeOrderRecMapper.closeByIdList(pointTableName, idList); 46 | } 47 | 48 | 49 | public List getFreezeOrderRecList(String type, 50 | long pid, 51 | Integer orderType, 52 | String orderNo) { 53 | String pointTableName = TableNameHelper.getPointTableName(type); 54 | return this.freezeOrderRecMapper.getFreezeOrderRecList(pointTableName, pid, orderType, orderNo); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/UpgradeSchemaMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import org.apache.ibatis.annotations.Mapper; 21 | import org.apache.ibatis.annotations.Param; 22 | 23 | @Mapper 24 | public interface UpgradeSchemaMapper { 25 | 26 | 27 | void addPointRefund(@Param(value = "pointTableName") String pointTableName ); 28 | void addPointCost(@Param(value = "pointTableName") String pointTableName ); 29 | void addPointFrozenCost(@Param(value = "pointTableName") String pointTableName ); 30 | 31 | 32 | void addPointLogDeltaCost(@Param(value = "pointTableName") String pointTableName ); 33 | 34 | void addPointLogRefund(@Param(value = "pointTableName") String pointTableName ); 35 | void addPointLogFrozenCost(@Param(value = "pointTableName") String pointTableName ); 36 | 37 | void addPointRecRefund(@Param(value = "pointTableName") String pointTableName ); 38 | void addPointRecFrozenCost(@Param(value = "pointTableName") String pointTableName ); 39 | void addPointRecRefundCost(@Param(value = "pointTableName") String pointTableName ); 40 | 41 | void addPointRecLogDeltaCost(@Param(value = "pointTableName") String pointTableName ); 42 | void addPointRecLogRefund(@Param(value = "pointTableName") String pointTableName ); 43 | void addPointRecLogFrozenCost(@Param(value = "pointTableName") String pointTableName ); 44 | void addPointRecLogUsedCost(@Param(value = "pointTableName") String pointTableName ); 45 | void addPointRecLogRefundCost(@Param(value = "pointTableName") String pointTableName ); 46 | 47 | 48 | void addPointLogAbnormal(@Param(value = "pointTableName") String pointTableName); 49 | void addPointRecLogAbnormal(@Param(value = "pointTableName") String pointTableName); 50 | } 51 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/SortParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.github.alphajiang.hyena.model.base.BaseObject; 21 | import io.github.alphajiang.hyena.model.type.SortOrder; 22 | import io.github.alphajiang.hyena.utils.CollectionUtils; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | public class SortParam extends BaseObject { 28 | 29 | private List columns = new ArrayList<>(); 30 | private SortOrder order = SortOrder.desc; 31 | 32 | public static SortParam as(String column, SortOrder order) { 33 | return SortParam.buildSort(order).setColumns(List.of(column)); 34 | } 35 | 36 | public static SortParam as(String col1, String col2, SortOrder order) { 37 | return SortParam.buildSort(order).setColumns(List.of(col1, col2)); 38 | } 39 | 40 | public static SortParam as(String col1, String col2, String col3, SortOrder order) { 41 | return SortParam.buildSort(order).setColumns(List.of(col1, col2, col3)); 42 | } 43 | 44 | private static SortParam buildSort(SortOrder order) { 45 | SortParam sort = new SortParam(); 46 | sort.order = order; 47 | return sort; 48 | } 49 | 50 | public List getColumns() { 51 | return columns; 52 | } 53 | 54 | public SortParam setColumns(List columns) { 55 | this.columns = columns; 56 | return this; 57 | } 58 | 59 | public String getColumnsString() { 60 | 61 | return CollectionUtils.join(this.columns, ","); 62 | 63 | } 64 | 65 | public SortOrder getOrder() { 66 | return order; 67 | } 68 | 69 | public SortParam setOrder(SortOrder order) { 70 | this.order = order; 71 | return this; 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/po/PointRecPo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.po; 19 | 20 | import com.fasterxml.jackson.annotation.JsonFormat; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import io.github.alphajiang.hyena.model.base.BasePo; 23 | import io.swagger.v3.oas.annotations.media.Schema; 24 | import lombok.Data; 25 | import lombok.EqualsAndHashCode; 26 | import lombok.ToString; 27 | import lombok.experimental.Accessors; 28 | 29 | import java.math.BigDecimal; 30 | import java.util.Date; 31 | 32 | @Data 33 | @Accessors(chain = true) 34 | @EqualsAndHashCode(callSuper = true) 35 | @ToString(callSuper = true) 36 | public class PointRecPo extends BasePo { 37 | 38 | private long pid; 39 | private long seqNum; 40 | private BigDecimal total; 41 | private BigDecimal available; 42 | private BigDecimal used; 43 | private BigDecimal frozen; 44 | private BigDecimal refund; 45 | private BigDecimal cancelled; 46 | private BigDecimal expire; 47 | @Schema(title = "总成本") 48 | private BigDecimal totalCost; 49 | @Schema(title = "冻结的成本") 50 | private BigDecimal frozenCost; 51 | @Schema(title = "已消耗的成本") 52 | private BigDecimal usedCost; 53 | @Schema(title = "已退款的成本") 54 | private BigDecimal refundCost; 55 | private String tag; 56 | private String orderNo; 57 | 58 | private Integer sourceType; 59 | private Integer orderType; 60 | private Integer payType; 61 | private String extra; 62 | 63 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 64 | @JsonInclude(JsonInclude.Include.NON_NULL) 65 | @Schema(title = "发放时间") 66 | private Date issueTime; 67 | 68 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 69 | private Date expireTime; 70 | 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/service/SysPropertyDs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.service; 19 | 20 | import io.github.alphajiang.hyena.ds.mapper.SysPropertyMapper; 21 | import io.github.alphajiang.hyena.model.po.SysPropertyPo; 22 | import lombok.extern.slf4j.Slf4j; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.stereotype.Repository; 25 | import org.springframework.transaction.annotation.Transactional; 26 | 27 | @Slf4j 28 | @Repository 29 | public class SysPropertyDs { 30 | private static final String KEY_SYS_VERSION = "sql_version"; 31 | 32 | @Autowired 33 | private SysPropertyMapper sysPropertyMapper; 34 | 35 | public int getSqlVersion() { 36 | SysPropertyPo sysProp = this.getSysProperty(KEY_SYS_VERSION); 37 | return sysProp == null ? 0 : Integer.parseInt(sysProp.getValue()); 38 | } 39 | 40 | @Transactional 41 | public void setSqlVersion(int sqlVersion) { 42 | SysPropertyPo sysProp = this.getSysProperty(KEY_SYS_VERSION); 43 | if (sysProp == null) { 44 | sysProp = new SysPropertyPo(); 45 | sysProp.setKey(KEY_SYS_VERSION).setValue(String.valueOf(sqlVersion)).setEnable(true); 46 | this.sysPropertyMapper.insertOrUpdate(sysProp); 47 | } else if (sysProp.getValue().equals(String.valueOf(sqlVersion))) { 48 | log.info("current sql version is {}, ignore set operation", sysProp.getValue()); 49 | }else { 50 | this.sysPropertyMapper.updateSysProperty(sysProp.getKey(), String.valueOf(sqlVersion)); 51 | } 52 | } 53 | 54 | 55 | public SysPropertyPo getSysProperty(String key) { 56 | return this.sysPropertyMapper.getSysProperty(key); 57 | } 58 | 59 | public void createSysPropertyTable() { 60 | this.sysPropertyMapper.createSysPropertyTable(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/base/BasePo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.base; 19 | 20 | import com.fasterxml.jackson.annotation.JsonFormat; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | 23 | import java.util.Date; 24 | 25 | public abstract class BasePo extends BaseObject { 26 | 27 | @JsonInclude(JsonInclude.Include.NON_NULL) 28 | private T id; 29 | 30 | @JsonInclude(JsonInclude.Include.NON_NULL) 31 | private Boolean enable; 32 | 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 34 | @JsonInclude(JsonInclude.Include.NON_NULL) 35 | private Date createTime; 36 | 37 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") 38 | @JsonInclude(JsonInclude.Include.NON_NULL) 39 | private Date updateTime; 40 | 41 | public T getId() { 42 | return id; 43 | } 44 | 45 | public BasePo setId(T id) { 46 | this.id = id; 47 | return this; 48 | } 49 | 50 | public Boolean getEnable() { 51 | return enable; 52 | } 53 | 54 | public BasePo setEnable(Boolean enable) { 55 | this.enable = enable; 56 | return this; 57 | } 58 | 59 | public Date getCreateTime() { 60 | return createTime; 61 | } 62 | 63 | public BasePo setCreateTime(Date createTime) { 64 | this.createTime = createTime; 65 | return this; 66 | } 67 | 68 | public Date getUpdateTime() { 69 | return updateTime; 70 | } 71 | 72 | public BasePo setUpdateTime(Date updateTime) { 73 | this.updateTime = updateTime; 74 | return this; 75 | } 76 | 77 | public void copyBase(BasePo in) { 78 | this.id = in.id; 79 | this.enable = in.enable; 80 | this.createTime = in.createTime; 81 | this.updateTime = in.updateTime; 82 | } 83 | } -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/biz/strategy/TestPointIncreaseStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.strategy; 19 | 20 | import io.github.alphajiang.hyena.biz.point.PSession; 21 | import io.github.alphajiang.hyena.biz.point.PointUsage; 22 | import io.github.alphajiang.hyena.biz.point.strategy.PointStrategy; 23 | import io.github.alphajiang.hyena.model.po.PointPo; 24 | import io.github.alphajiang.hyena.utils.DecimalUtils; 25 | import org.junit.jupiter.api.Assertions; 26 | import org.junit.jupiter.api.Test; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | import org.springframework.beans.factory.annotation.Autowired; 30 | 31 | import java.math.BigDecimal; 32 | 33 | public class TestPointIncreaseStrategy extends TestPointStrategyBase { 34 | private final Logger logger = LoggerFactory.getLogger(TestPointIncreaseStrategy.class); 35 | 36 | @Autowired 37 | private PointStrategy pointIncreaseStrategy; 38 | 39 | 40 | @Test 41 | public void test_increasePoint_twice() { 42 | BigDecimal number = BigDecimal.valueOf(123L).setScale(DecimalUtils.SCALE_2); 43 | BigDecimal resultNumber = this.point.getPoint().add(number); 44 | PointUsage usage = new PointUsage(); 45 | usage.setType(super.getPointType()).setUid(super.getUid()).setPoint(number); 46 | PointPo result = this.pointIncreaseStrategy.process(PSession.fromUsage(usage)) 47 | .block() 48 | .getResult(); 49 | logger.info("result = {}", result); 50 | Assertions.assertEquals(resultNumber, result.getPoint()); 51 | Assertions.assertEquals(resultNumber, result.getAvailable()); 52 | Assertions.assertEquals(DecimalUtils.ZERO, result.getUsed()); 53 | Assertions.assertEquals(DecimalUtils.ZERO, result.getFrozen()); 54 | Assertions.assertEquals(DecimalUtils.ZERO, result.getExpire()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/utils/LoggerHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.utils; 19 | 20 | import org.springframework.web.server.ServerWebExchange; 21 | 22 | import java.util.Iterator; 23 | 24 | 25 | public class LoggerHelper { 26 | 27 | 28 | public static String formatEnterLog(ServerWebExchange exh) { 29 | return ">> " + LoggerHelper.getUserLog(exh, true); 30 | } 31 | 32 | public static String formatEnterLog(ServerWebExchange exh, boolean logParams) { 33 | return ">> " + LoggerHelper.getUserLog(exh, logParams); 34 | } 35 | 36 | public static String formatLeaveLog(ServerWebExchange exh) { 37 | return "<< " + LoggerHelper.getUserLog(exh, false); 38 | } 39 | 40 | private static String getUserLog(ServerWebExchange exh, boolean logParams) { 41 | 42 | StringBuilder sb = new StringBuilder(); 43 | 44 | 45 | if (logParams) { 46 | sb.append("params = { "); 47 | boolean firstKey = true; 48 | Iterator iter = exh.getRequest().getQueryParams().keySet().iterator(); 49 | while (iter.hasNext()) { 50 | String k = iter.next(); 51 | 52 | if (firstKey) { 53 | firstKey = false; 54 | } else { 55 | sb.append(", "); 56 | } 57 | 58 | sb.append(k).append("=["); 59 | boolean firstValue = true; 60 | for (String v : exh.getRequest().getQueryParams().get(k)) { 61 | if (firstValue) { 62 | firstValue = false; 63 | } else { 64 | sb.append(","); 65 | } 66 | sb.append(v); 67 | } 68 | sb.append("]"); 69 | } 70 | sb.append(" } "); 71 | } 72 | return sb.toString(); 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/po/PointLogPo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.po; 19 | 20 | import com.fasterxml.jackson.annotation.JsonInclude; 21 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 22 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 23 | import io.github.alphajiang.hyena.model.base.BasePo; 24 | import io.github.alphajiang.hyena.utils.JacksonStringDeserialize; 25 | import io.github.alphajiang.hyena.utils.JacksonStringSerialize; 26 | import io.swagger.v3.oas.annotations.media.Schema; 27 | import lombok.Data; 28 | import lombok.EqualsAndHashCode; 29 | import lombok.ToString; 30 | import lombok.experimental.Accessors; 31 | 32 | import java.math.BigDecimal; 33 | 34 | @Data 35 | @Accessors(chain = true) 36 | @EqualsAndHashCode(callSuper = true) 37 | @ToString(callSuper = true) 38 | public class PointLogPo extends BasePo { 39 | 40 | private long pid; 41 | private String uid; 42 | private String subUid; 43 | private long seqNum; 44 | private BigDecimal delta; 45 | @Schema(title = "变动部分的实际成本") 46 | private BigDecimal deltaCost; 47 | private BigDecimal point; 48 | private BigDecimal available; 49 | private BigDecimal used; 50 | private BigDecimal frozen; 51 | private BigDecimal refund; 52 | private BigDecimal expire; 53 | @Schema(title = "变动后,实际成本") 54 | private BigDecimal cost; 55 | @Schema(title = "变动后,冻结的成本") 56 | private BigDecimal frozenCost; 57 | /** 58 | * PointOpType 59 | */ 60 | private Integer type; 61 | private String tag; 62 | private String orderNo; 63 | 64 | private Integer sourceType; 65 | private Integer orderType; 66 | private Integer payType; 67 | @JsonSerialize(using = JacksonStringSerialize.class) 68 | @JsonDeserialize(using = JacksonStringDeserialize.class) 69 | private String extra; 70 | private String note; 71 | 72 | @JsonInclude(JsonInclude.Include.NON_NULL) 73 | private Boolean abnormal; 74 | 75 | } 76 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/PointTableMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import org.apache.ibatis.annotations.Mapper; 21 | import org.apache.ibatis.annotations.Param; 22 | 23 | import java.util.List; 24 | 25 | @Mapper 26 | public interface PointTableMapper { 27 | List listCusPointTables(@Param(value = "prefix") String prefix); 28 | 29 | Integer createPointTable(@Param(value = "pointTableName") String pointTableName); 30 | 31 | void createPointTableIndex(@Param(value = "pointTableName") String pointTableName); 32 | 33 | void createPointTableIndexH2(@Param(value = "pointTableName") String pointTableName); 34 | 35 | void createPointLogTable(@Param(value = "pointTableName") String pointTableName); 36 | 37 | 38 | void createPointLogTableIndexPid(@Param(value = "pointTableName") String pointTableName); 39 | void createPointLogTableIndexUid(@Param(value = "pointTableName") String pointTableName); 40 | void createPointLogTableIndexOrderNo(@Param(value = "pointTableName") String pointTableName); 41 | 42 | 43 | Integer createPointRecTable(@Param(value = "pointTableName") String pointTableName); 44 | 45 | 46 | void createPointRecTableIndexPid(@Param(value = "pointTableName") String pointTableName); 47 | void createPointRecTableIndexTag(@Param(value = "pointTableName") String pointTableName); 48 | void createPointRecTableIndexOrderNo(@Param(value = "pointTableName") String pointTableName); 49 | 50 | 51 | Integer createPointRecordLogTable(@Param(value = "pointTableName") String pointTableName); 52 | 53 | void createPointRecordLogTableIndexPid(@Param(value = "pointTableName") String pointTableName); 54 | void createPointRecordLogTableIndexRecId(@Param(value = "pointTableName") String pointTableName); 55 | 56 | 57 | Integer createFreezeOrderRecTable(@Param(value = "pointTableName") String pointTableName); 58 | void createFreezeOrderRecTableIndex(@Param(value = "pointTableName") String pointTableName); 59 | 60 | } 61 | -------------------------------------------------------------------------------- /hyena-spring-boot-autoconfigure/src/main/java/io/github/alphajiang/hyena/spring/boot/autoconfigure/HyenaInitialization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.spring.boot.autoconfigure; 19 | 20 | import io.github.alphajiang.hyena.HyenaConstants; 21 | import io.github.alphajiang.hyena.ds.service.PointTableDs; 22 | import io.github.alphajiang.hyena.ds.service.SysPropertyDs; 23 | import io.github.alphajiang.hyena.ds.service.UpgradeSchemaDs; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.boot.context.event.ApplicationReadyEvent; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.context.event.EventListener; 29 | 30 | import java.util.List; 31 | 32 | @Slf4j 33 | @Configuration 34 | public class HyenaInitialization { 35 | 36 | @Autowired 37 | private SysPropertyDs sysPropertyDs; 38 | 39 | @Autowired 40 | private PointTableDs pointTableDs; 41 | 42 | @Autowired 43 | private UpgradeSchemaDs upgradeSchemaDs; 44 | 45 | @EventListener(ApplicationReadyEvent.class) 46 | public void onApplicationReady() { 47 | log.info("application ready"); 48 | sysPropertyDs.createSysPropertyTable(); 49 | 50 | int dbSqlVer = this.upgradeSql(); 51 | if (dbSqlVer != HyenaConstants.SQL_VERSION) { 52 | sysPropertyDs.setSqlVersion(HyenaConstants.SQL_VERSION); 53 | } 54 | } 55 | 56 | public int upgradeSql() { 57 | int sqlVer = sysPropertyDs.getSqlVersion(); 58 | List tables = pointTableDs.listTable(); 59 | if (sqlVer == 0) { 60 | upgradeSchemaDs.addRefundColumn(tables); 61 | } 62 | if (sqlVer < 2) { 63 | upgradeSchemaDs.addCostColumns(tables); 64 | } 65 | if (sqlVer < 3) { 66 | upgradeSchemaDs.addSqlV3(tables); 67 | } 68 | if (sqlVer < 4) { 69 | upgradeSchemaDs.addSqlV4(tables); 70 | } 71 | return sqlVer; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/PointRecMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import io.github.alphajiang.hyena.model.dto.PointRecDto; 21 | import io.github.alphajiang.hyena.model.param.ListPointRecParam; 22 | import io.github.alphajiang.hyena.model.po.PointRecPo; 23 | import org.apache.ibatis.annotations.Mapper; 24 | import org.apache.ibatis.annotations.Param; 25 | 26 | import java.math.BigDecimal; 27 | import java.util.Date; 28 | import java.util.List; 29 | 30 | @Mapper 31 | public interface PointRecMapper { 32 | 33 | PointRecPo getById(@Param(value = "pointTableName") String pointTableName, 34 | @Param(value = "id") long id, 35 | @Param(value = "lock") boolean lock); 36 | 37 | void addPointRec(@Param(value = "tableName") String tableName, 38 | @Param(value = "rec") PointRecPo rec); 39 | 40 | void batchInsert(@Param(value = "pointTableName") String tableName, 41 | @Param(value = "recList") List recList); 42 | 43 | List listPointRec(@Param(value = "pointTableName") String pointTableName, 44 | @Param(value = "param") ListPointRecParam param); 45 | 46 | Long countPointRec(@Param(value = "pointTableName") String pointTableName, 47 | @Param(value = "param") ListPointRecParam param); 48 | 49 | void updatePointRec(@Param(value = "pointTableName") String pointTableName, 50 | @Param(value = "rec") PointRecPo rec); 51 | 52 | 53 | BigDecimal getIncreasedPoint(@Param(value = "pointTableName") String pointTableName, 54 | @Param(value = "uid") String uid, 55 | @Param(value = "start") Date start, 56 | @Param(value = "end") Date end); 57 | 58 | void batchUpdate(@Param(value = "pointTableName") String pointTableName, 59 | @Param(value = "list") List list); 60 | } 61 | -------------------------------------------------------------------------------- /hyena-spring-boot-autoconfigure/src/main/java/io/github/alphajiang/hyena/spring/boot/autoconfigure/HyenaAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.spring.boot.autoconfigure; 19 | 20 | import io.github.alphajiang.hyena.biz.idempotent.HyenaIdempotent; 21 | import io.github.alphajiang.hyena.biz.idempotent.HyenaMemIdempotent; 22 | import io.github.alphajiang.hyena.biz.idempotent.HyenaRedisIdempotent; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.InitializingBean; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 28 | import org.springframework.context.annotation.Bean; 29 | import org.springframework.context.annotation.Configuration; 30 | import org.springframework.data.redis.core.RedisTemplate; 31 | 32 | @Configuration 33 | @EnableConfigurationProperties(HyenaProperties.class) 34 | public class HyenaAutoConfiguration implements InitializingBean { 35 | private final Logger logger = LoggerFactory.getLogger(HyenaAutoConfiguration.class); 36 | private final HyenaProperties properties; 37 | @Autowired 38 | private RedisTemplate redisStringTemplate; 39 | 40 | public HyenaAutoConfiguration(HyenaProperties properties) { 41 | this.properties = properties; 42 | } 43 | 44 | @Override 45 | public void afterPropertiesSet() throws Exception { 46 | logger.info("hyena.idempotent = {}", properties.getIdempotent()); 47 | } 48 | 49 | @Bean(name = "hyenaIdempotent") 50 | public HyenaIdempotent hyenaIdempotent() { 51 | HyenaIdempotent idempotent = null; 52 | if ("redis".equalsIgnoreCase(properties.getIdempotent())) { 53 | idempotent = new HyenaRedisIdempotent(); 54 | ((HyenaRedisIdempotent) idempotent).setRedisTemplate(redisStringTemplate); 55 | 56 | } else { 57 | idempotent = new HyenaMemIdempotent(); 58 | } 59 | return idempotent; 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/ds/TestFreezeOrderRecDs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds; 19 | 20 | import io.github.alphajiang.hyena.HyenaTestBase; 21 | import io.github.alphajiang.hyena.biz.point.PointBuilder; 22 | import io.github.alphajiang.hyena.ds.service.FreezeOrderRecDs; 23 | import io.github.alphajiang.hyena.model.po.FreezeOrderRecPo; 24 | import io.github.alphajiang.hyena.model.po.PointRecPo; 25 | import lombok.extern.slf4j.Slf4j; 26 | import org.junit.jupiter.api.BeforeEach; 27 | import org.junit.jupiter.api.Test; 28 | import org.springframework.beans.factory.annotation.Autowired; 29 | 30 | import java.math.BigDecimal; 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | import java.util.UUID; 34 | import java.util.stream.Collectors; 35 | 36 | @Slf4j 37 | public class TestFreezeOrderRecDs extends HyenaTestBase { 38 | @Autowired 39 | private FreezeOrderRecDs freezeOrderRecDs; 40 | 41 | @Autowired 42 | private PointBuilder pointBuilder; 43 | 44 | @BeforeEach 45 | public void init() { 46 | super.init(); 47 | } 48 | 49 | @Test 50 | public void test_closeByIdList() { 51 | String orderNo = UUID.randomUUID().toString(); 52 | List foList = new ArrayList<>(); 53 | for (long i = 0L; i < 5L; i++) { 54 | PointRecPo rec = new PointRecPo(); 55 | rec.setId(i + 1); 56 | FreezeOrderRecPo fo = pointBuilder.buildFreezeOrderRec(super.getUserPoint(), 57 | rec, super.getIdGenerator(), 58 | null, orderNo, BigDecimal.valueOf(i + 1), BigDecimal.valueOf(i)); 59 | foList.add(fo); 60 | } 61 | this.freezeOrderRecDs.batchInsert(super.getPointType(), foList); 62 | 63 | List list = this.freezeOrderRecDs.getFreezeOrderRecList(super.getPointType(), 64 | super.getUserPoint().getId(), null, orderNo); 65 | List idList = list.stream().map(FreezeOrderRecPo::getId).collect(Collectors.toList()); 66 | this.freezeOrderRecDs.closeByIdList(super.getPointType(), idList); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/vo/PointOpResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.vo; 19 | 20 | import com.fasterxml.jackson.annotation.JsonIgnore; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import io.github.alphajiang.hyena.model.dto.PointLogDto; 23 | import io.github.alphajiang.hyena.model.dto.PointRecLogDto; 24 | import io.github.alphajiang.hyena.model.po.FreezeOrderRecPo; 25 | import io.github.alphajiang.hyena.model.po.PointLogPo; 26 | import io.github.alphajiang.hyena.model.po.PointPo; 27 | import io.github.alphajiang.hyena.model.po.PointRecPo; 28 | import io.github.alphajiang.hyena.utils.JsonUtils; 29 | import io.swagger.v3.oas.annotations.media.Schema; 30 | import lombok.Data; 31 | import lombok.EqualsAndHashCode; 32 | import lombok.ToString; 33 | import lombok.experimental.Accessors; 34 | 35 | import java.math.BigDecimal; 36 | import java.util.ArrayList; 37 | import java.util.List; 38 | 39 | @Data 40 | @Accessors(chain = true) 41 | @EqualsAndHashCode(callSuper = true) 42 | public class PointOpResult extends PointPo { 43 | 44 | @Schema(title = "变更的积分", example = "100.00") 45 | private BigDecimal opPoint; 46 | 47 | @Schema(title = "变更的成本", example = "10.00") 48 | private BigDecimal opCost; 49 | 50 | @Schema(title = "账户变更明细") 51 | private List logs; 52 | 53 | @Schema(title = "积分块变更明细") 54 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 55 | private List recLogList; 56 | 57 | @Schema(accessMode = Schema.AccessMode.READ_ONLY) 58 | @JsonIgnore 59 | private UpdateQueue updateQ = new UpdateQueue(); 60 | 61 | @Data 62 | @Accessors(chain = true) 63 | public static class UpdateQueue { 64 | private PointPo point = new PointPo(); 65 | private List logs = new ArrayList<>(); 66 | private List recList = new ArrayList<>(); 67 | private List foList = new ArrayList<>(); 68 | private List recLogs = new ArrayList<>(); 69 | } 70 | 71 | 72 | @Override 73 | public String toString() { 74 | return JsonUtils.toJsonString(this); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/idempotent/HyenaMemIdempotent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.idempotent; 19 | 20 | import io.github.alphajiang.hyena.model.base.BaseResponse; 21 | import io.github.alphajiang.hyena.utils.JsonUtils; 22 | import lombok.extern.slf4j.Slf4j; 23 | import org.ehcache.Cache; 24 | import org.ehcache.CacheManager; 25 | import org.ehcache.config.builders.CacheConfigurationBuilder; 26 | import org.ehcache.config.builders.CacheManagerBuilder; 27 | import org.ehcache.config.builders.ExpiryPolicyBuilder; 28 | import org.ehcache.config.builders.ResourcePoolsBuilder; 29 | 30 | import jakarta.annotation.PostConstruct; 31 | import java.time.Duration; 32 | import java.util.List; 33 | 34 | @Slf4j 35 | public class HyenaMemIdempotent implements HyenaIdempotent { 36 | 37 | private CacheManager cm; 38 | 39 | 40 | private List cacheAliases = List.of("increase-point", "decrease-point", "decreaseFrozen-point", 41 | "freeze-point", "unfreeze-point", "cancel-point", "freeze-by-rec-id", 42 | "freeze-cost", "unfreeze-cost", "refund"); 43 | 44 | @PostConstruct 45 | public void init() { 46 | log.info("init ehcache, aliases = {}", cacheAliases); 47 | cm = CacheManagerBuilder.newCacheManagerBuilder().build(true); 48 | cacheAliases.forEach(alias -> { 49 | cm.createCache(alias, CacheConfigurationBuilder 50 | .newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.heap(100)) 51 | .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(10L)))); 52 | 53 | }); 54 | 55 | } 56 | 57 | @Override 58 | public String getByKey(String name, String seq) { 59 | Cache cache = cm.getCache(name, String.class, String.class); 60 | return cache.get(seq); 61 | } 62 | 63 | @Override 64 | public void setByKey(String name, String seq, BaseResponse obj) { 65 | cm.getCache(name, String.class, String.class).put(seq, JsonUtils.toJsonString(obj)); 66 | } 67 | 68 | @Override 69 | public boolean lock(String seq) { 70 | return true; 71 | } 72 | 73 | @Override 74 | public void unlock(String seq) { 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/param/BaseListParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.param; 19 | 20 | import io.github.alphajiang.hyena.model.base.BaseObject; 21 | import io.swagger.v3.oas.annotations.media.Schema; 22 | 23 | import java.util.List; 24 | 25 | public class BaseListParam extends BaseObject { 26 | 27 | private String type; 28 | 29 | @Schema(title = "搜索关键词") 30 | private String sk = ""; 31 | 32 | @Schema(title = "是否有效") 33 | private Boolean enable; 34 | 35 | private boolean lock = false; 36 | 37 | 38 | @Schema(title = "分页开始") 39 | private Long start; 40 | 41 | @Schema(title = "查询最大数量") 42 | private Integer size; 43 | 44 | @Schema(title = "排序方式") 45 | private List sorts; 46 | 47 | 48 | public String getType() { 49 | return type; 50 | } 51 | 52 | public BaseListParam setType(String type) { 53 | this.type = type; 54 | return this; 55 | } 56 | 57 | public String getSk() { 58 | return sk; 59 | } 60 | 61 | public BaseListParam setSk(String sk) { 62 | this.sk = sk; 63 | return this; 64 | } 65 | 66 | public Boolean getEnable() { 67 | return enable; 68 | } 69 | 70 | public BaseListParam setEnable(Boolean enable) { 71 | this.enable = enable; 72 | return this; 73 | } 74 | 75 | public boolean isLock() { 76 | return lock; 77 | } 78 | 79 | public BaseListParam setLock(boolean lock) { 80 | this.lock = lock; 81 | return this; 82 | } 83 | 84 | public Long getStart() { 85 | return start; 86 | } 87 | 88 | public BaseListParam setStart(Long start) { 89 | this.start = start; 90 | return this; 91 | } 92 | 93 | public Integer getSize() { 94 | return size; 95 | } 96 | 97 | public BaseListParam setSize(Integer size) { 98 | this.size = size; 99 | return this; 100 | } 101 | 102 | public List getSorts() { 103 | return sorts; 104 | } 105 | 106 | public BaseListParam setSorts(List sorts) { 107 | this.sorts = sorts; 108 | return this; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointUpdateConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.PointDs; 21 | import io.github.alphajiang.hyena.model.po.PointPo; 22 | import lombok.extern.slf4j.Slf4j; 23 | 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.concurrent.LinkedBlockingQueue; 29 | import java.util.concurrent.TimeUnit; 30 | 31 | @Slf4j 32 | public class PointUpdateConsumer implements Runnable { 33 | 34 | private PointDs pointDs; 35 | private LinkedBlockingQueue queue; 36 | private List list; 37 | 38 | public PointUpdateConsumer(LinkedBlockingQueue queue, 39 | PointDs pointDs) { 40 | this.list = new ArrayList<>(); 41 | this.queue = queue; 42 | this.pointDs = pointDs; 43 | } 44 | 45 | @Override 46 | public void run() { 47 | do { 48 | try { 49 | this.threadLoop(); 50 | } catch (Exception e) { 51 | log.warn("error = {}", e.getMessage(), e); 52 | } 53 | } while (true); 54 | } 55 | 56 | private void threadLoop() throws Exception { 57 | 58 | PointUpdateQueue.Point pl = queue.poll(1, TimeUnit.SECONDS); 59 | if (pl == null) { 60 | return; 61 | } 62 | list.clear(); 63 | list.add(pl); 64 | this.pollMore(list); 65 | Map> map = new HashMap<>(); 66 | list.stream().forEach(o -> { 67 | if (!map.containsKey(o.getType())) { 68 | map.put(o.getType(), new ArrayList<>()); 69 | } 70 | map.get(o.getType()).add(o.getPoint()); 71 | }); 72 | map.forEach((k, v) -> this.pointDs.batchUpdate(k, v)); 73 | } 74 | 75 | private void pollMore(List list) { 76 | PointUpdateQueue.Point pl = null; 77 | int max = 100; 78 | do { 79 | pl = queue.poll(); 80 | if(pl == null) { 81 | break; 82 | } 83 | list.add(pl); 84 | max--; 85 | } while (pl != null && max > 0); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/model/po/PointRecLogPo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.model.po; 19 | 20 | import io.github.alphajiang.hyena.model.base.BasePo; 21 | import io.github.alphajiang.hyena.model.type.PointOpType; 22 | import io.swagger.v3.oas.annotations.media.Schema; 23 | import lombok.Data; 24 | import lombok.EqualsAndHashCode; 25 | import lombok.ToString; 26 | import lombok.experimental.Accessors; 27 | 28 | import java.math.BigDecimal; 29 | 30 | @Data 31 | @Accessors(chain = true) 32 | @EqualsAndHashCode(callSuper = true) 33 | @ToString(callSuper = true) 34 | public class PointRecLogPo extends BasePo { 35 | 36 | private long pid; 37 | private long seqNum; 38 | private long recId; 39 | 40 | /** 41 | * PointOpType 42 | */ 43 | private Integer type; 44 | private BigDecimal delta; 45 | @Schema(title = "变动部分的实际成本") 46 | private BigDecimal deltaCost; 47 | private BigDecimal available; 48 | private BigDecimal used; 49 | private BigDecimal frozen; 50 | private BigDecimal refund; 51 | private BigDecimal cancelled; 52 | private BigDecimal expire; 53 | @Schema(title = "变动后,实际成本") 54 | private BigDecimal cost; 55 | @Schema(title = "变动后,冻结的实际成本") 56 | private BigDecimal frozenCost; 57 | @Schema(title = "变动后,已消耗的实际成本") 58 | private BigDecimal usedCost; 59 | @Schema(title = "已退款的成本") 60 | private BigDecimal refundCost; 61 | 62 | private Integer sourceType; 63 | private Integer orderType; 64 | private Integer payType; 65 | private String note; 66 | 67 | 68 | public static PointRecLogPo buildRecLog(PointOpType type) { 69 | PointRecLogPo recLog = new PointRecLogPo(); 70 | recLog.setType(type.code()) 71 | .setDelta(BigDecimal.ZERO) 72 | .setDeltaCost(BigDecimal.ZERO) 73 | .setAvailable(BigDecimal.ZERO) 74 | .setUsed(BigDecimal.ZERO) 75 | .setFrozen(BigDecimal.ZERO) 76 | .setRefund(BigDecimal.ZERO) 77 | .setCancelled(BigDecimal.ZERO) 78 | .setExpire(BigDecimal.ZERO) 79 | .setCost(BigDecimal.ZERO) 80 | .setFrozenCost(BigDecimal.ZERO) 81 | .setUsedCost(BigDecimal.ZERO) 82 | .setRefundCost(BigDecimal.ZERO); 83 | return recLog; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointLogFlowConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.PointLogDs; 21 | import io.github.alphajiang.hyena.model.po.PointLogPo; 22 | import lombok.extern.slf4j.Slf4j; 23 | 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.concurrent.LinkedBlockingQueue; 29 | import java.util.concurrent.TimeUnit; 30 | 31 | @Slf4j 32 | public class PointLogFlowConsumer implements Runnable { 33 | 34 | private PointLogDs pointLogDs; 35 | private LinkedBlockingQueue queue; 36 | private List list; 37 | 38 | public PointLogFlowConsumer(LinkedBlockingQueue queue, 39 | PointLogDs pointLogDs) { 40 | this.list = new ArrayList<>(); 41 | this.queue = queue; 42 | this.pointLogDs = pointLogDs; 43 | } 44 | 45 | @Override 46 | public void run() { 47 | do { 48 | try { 49 | this.threadLoop(); 50 | } catch (Exception e) { 51 | log.warn("error = {}", e.getMessage(), e); 52 | } 53 | } while (true); 54 | } 55 | 56 | private void threadLoop() throws Exception { 57 | 58 | PointLogFlowQueue.PointLog pl = queue.poll(1, TimeUnit.SECONDS); 59 | if (pl == null) { 60 | return; 61 | } 62 | list.clear(); 63 | list.add(pl); 64 | this.pollMore(list); 65 | Map> map = new HashMap<>(); 66 | list.stream().forEach(o -> { 67 | if (!map.containsKey(o.getType())) { 68 | map.put(o.getType(), new ArrayList<>()); 69 | } 70 | map.get(o.getType()).add(o.getPointLog()); 71 | }); 72 | map.forEach((k, v) -> this.pointLogDs.batchInsert(k, v)); 73 | } 74 | 75 | private void pollMore(List list) { 76 | PointLogFlowQueue.PointLog pl = null; 77 | int max = 100; 78 | do { 79 | pl = queue.poll(); 80 | if(pl == null) { 81 | break; 82 | } 83 | list.add(pl); 84 | max--; 85 | } while (pl != null && max > 0); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/ds/mapper/PointMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds.mapper; 19 | 20 | import io.github.alphajiang.hyena.model.param.BaseListParam; 21 | import io.github.alphajiang.hyena.model.param.ListPointParam; 22 | import io.github.alphajiang.hyena.model.po.PointPo; 23 | import io.github.alphajiang.hyena.model.vo.PointVo; 24 | import org.apache.ibatis.annotations.Mapper; 25 | import org.apache.ibatis.annotations.Param; 26 | 27 | import java.util.List; 28 | 29 | @Mapper 30 | public interface PointMapper { 31 | Integer addPoint(@Param(value = "tableName") String tableName, 32 | @Param(value = "point") PointPo point); 33 | 34 | 35 | PointPo getCusPoint(@Param(value = "tableName") String tableName, 36 | @Param(value = "id") long id, 37 | @Param(value = "lock") boolean lock); 38 | 39 | PointPo getCusPointByUid(@Param(value = "tableName") String tableName, 40 | @Param(value = "uid") String uid, 41 | @Param(value = "subUid") String subUid, 42 | @Param(value = "lock") boolean lock); 43 | 44 | 45 | List listPoint(@Param(value = "pointTableName") String pointTableName, 46 | @Param(value = "param") ListPointParam param); 47 | 48 | 49 | long countPoint(@Param(value = "pointTableName") String pointTableName, 50 | @Param(value = "param") ListPointParam param); 51 | 52 | 53 | List listExpirePoint(@Param(value = "pointTableName") String pointTableName, 54 | @Param(value = "param") BaseListParam param); 55 | 56 | 57 | int disableAccount(@Param(value = "tableName") String tableName, 58 | @Param(value = "uid") String uid, 59 | @Param(value = "subUid") String subUid); 60 | 61 | int updateCusPoint(@Param(value = "tableName") String tableName, 62 | @Param(value = "p") PointPo point); 63 | 64 | void batchUpdate(@Param(value = "pointTableName") String pointTableName, 65 | @Param(value = "pointList") List pointList); 66 | 67 | PointVo getPointVo(@Param(value = "pointTableName") String pointTableName, 68 | @Param(value = "pid") Long pid, 69 | @Param(value = "uid") String uid, 70 | @Param(value = "subUid") String subUid); 71 | } 72 | -------------------------------------------------------------------------------- /hyena-core/src/main/java/io/github/alphajiang/hyena/biz/flow/PointRecLogFlowConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.biz.flow; 19 | 20 | import io.github.alphajiang.hyena.ds.service.PointRecLogDs; 21 | import io.github.alphajiang.hyena.model.po.PointRecLogPo; 22 | import lombok.extern.slf4j.Slf4j; 23 | 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.concurrent.LinkedBlockingQueue; 29 | import java.util.concurrent.TimeUnit; 30 | 31 | @Slf4j 32 | public class PointRecLogFlowConsumer implements Runnable { 33 | 34 | private PointRecLogDs pointRecLogDs; 35 | private LinkedBlockingQueue queue; 36 | private List list; 37 | 38 | public PointRecLogFlowConsumer(LinkedBlockingQueue queue, 39 | PointRecLogDs pointRecLogDs) { 40 | this.list = new ArrayList<>(); 41 | this.queue = queue; 42 | this.pointRecLogDs = pointRecLogDs; 43 | } 44 | 45 | @Override 46 | public void run() { 47 | do { 48 | try { 49 | this.threadLoop(); 50 | } catch (Exception e) { 51 | log.warn("error = {}", e.getMessage(), e); 52 | } 53 | } while (true); 54 | } 55 | 56 | private void threadLoop() throws Exception { 57 | 58 | PointRecLogFlowQueue.PointRecLog prl = queue.poll(1, TimeUnit.SECONDS); 59 | if (prl == null) { 60 | return; 61 | } 62 | list.clear(); 63 | list.add(prl); 64 | this.pollMore(list); 65 | Map> map = new HashMap<>(); 66 | list.stream().forEach(o -> { 67 | if (!map.containsKey(o.getType())) { 68 | map.put(o.getType(), new ArrayList<>()); 69 | } 70 | map.get(o.getType()).add(o.getPointRecLog()); 71 | }); 72 | map.forEach((k, v) -> this.pointRecLogDs.batchInsert(k, v)); 73 | } 74 | 75 | private void pollMore(List list) { 76 | PointRecLogFlowQueue.PointRecLog prl = null; 77 | int max = 100; 78 | do { 79 | prl = queue.poll(); 80 | if(prl == null) { 81 | break; 82 | } 83 | list.add(prl); 84 | max--; 85 | } while (prl != null && max > 0); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /hyena-core/src/test/java/io/github/alphajiang/hyena/ds/TestPointLogDs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Alpha Jiang. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.github.alphajiang.hyena.ds; 19 | 20 | import io.github.alphajiang.hyena.HyenaTestBase; 21 | import io.github.alphajiang.hyena.biz.point.PointBuilder; 22 | import io.github.alphajiang.hyena.biz.point.PointUsage; 23 | import io.github.alphajiang.hyena.ds.service.PointLogDs; 24 | import io.github.alphajiang.hyena.model.base.ListResponse; 25 | import io.github.alphajiang.hyena.model.dto.PointLogDto; 26 | import io.github.alphajiang.hyena.model.param.ListPointLogParam; 27 | import io.github.alphajiang.hyena.model.po.PointLogPo; 28 | import io.github.alphajiang.hyena.model.po.PointPo; 29 | import io.github.alphajiang.hyena.model.type.PointOpType; 30 | import org.junit.jupiter.api.Assertions; 31 | import org.junit.jupiter.api.BeforeEach; 32 | import org.junit.jupiter.api.Test; 33 | import org.springframework.beans.factory.annotation.Autowired; 34 | 35 | import java.math.BigDecimal; 36 | import java.util.List; 37 | 38 | public class TestPointLogDs extends HyenaTestBase { 39 | 40 | @Autowired 41 | private PointLogDs pointLogDs; 42 | 43 | @Autowired 44 | private PointBuilder pointBuilder; 45 | 46 | @BeforeEach 47 | public void init() { 48 | super.init(); 49 | } 50 | 51 | @Test 52 | public void test_addPointLog() { 53 | PointLogPo pl = this.buildPointLog(45L); 54 | this.pointLogDs.addPointLog(super.getPointType(), pl); 55 | } 56 | 57 | @Test 58 | public void test_listPointLog4Page() { 59 | ListPointLogParam param = new ListPointLogParam(); 60 | param.setUid(super.getUid()).setOrderNo("abcd123").setSk("abewfgewgewgewgewg") 61 | .setType(super.getPointType()); 62 | ListResponse res = this.pointLogDs.listPointLog4Page(param); 63 | Assertions.assertNotNull(res); 64 | } 65 | 66 | @Test 67 | public void test_batchInsert() { 68 | long seq = 1L; 69 | List list = List.of( 70 | this.buildPointLog(seq++), 71 | this.buildPointLog(seq++) 72 | ); 73 | this.pointLogDs.batchInsert(super.getPointType(), list); 74 | } 75 | 76 | private PointLogPo buildPointLog(long seq) { 77 | PointUsage usage = new PointUsage(); 78 | usage.setPoint(BigDecimal.valueOf(1000L)); 79 | PointPo point = super.getUserPoint(); 80 | point.setSeqNum(seq); 81 | return this.pointBuilder.buildPointLog(PointOpType.INCREASE, usage, point); 82 | } 83 | } 84 | --------------------------------------------------------------------------------