update 矿机离线邮箱发送定时任务修改
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
package com.m2pool.pool.entity;
|
||||
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @Description 币种实时收益实体类
|
||||
* @Date 2024/6/14 15:57
|
||||
* @Author dy
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class HourIncome implements Serializable {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 挖矿账户
|
||||
*/
|
||||
private String user;
|
||||
|
||||
/**
|
||||
* 矿工编号
|
||||
*/
|
||||
private String miner;
|
||||
|
||||
/**
|
||||
* 挖矿收益nexa 币
|
||||
*/
|
||||
private BigDecimal income;
|
||||
|
||||
/**
|
||||
* 挖矿收益 稳定币usdt
|
||||
*/
|
||||
private BigDecimal usdtIncome;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.m2pool.pool.enums;
|
||||
|
||||
/**
|
||||
* @Description redis key
|
||||
* @Date 2025/8/18 09:49
|
||||
* @Author yyb
|
||||
*/
|
||||
public class RedisKey {
|
||||
/**
|
||||
* nexa币种实时价格
|
||||
*/
|
||||
public static final String NEXA_PRICE = "nexa:price";
|
||||
/**
|
||||
* grs币种实时价格
|
||||
*/
|
||||
public static final String MONA_PRICE = "mona:price";
|
||||
/**
|
||||
* rxd币种实时价格
|
||||
*/
|
||||
public static final String RXD_PRICE = "rxd:price";
|
||||
/**
|
||||
* grs币种实时价格
|
||||
*/
|
||||
public static final String GRS_PRICE = "grs:price";
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.m2pool.pool.mapper;
|
||||
|
||||
import com.m2pool.common.datasource.annotation.DistributionDB;
|
||||
import com.m2pool.common.datasource.annotation.HashRateDB;
|
||||
import com.m2pool.pool.dto.MinerIncomeDto;
|
||||
import com.m2pool.pool.entity.HourIncome;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description 矿机收益
|
||||
* @Date 2025/8/15 17:47
|
||||
* @Author yyb
|
||||
*/
|
||||
public interface IncomeMapper {
|
||||
/**
|
||||
* 获取矿机平均算力
|
||||
* @param coin
|
||||
* @param start
|
||||
* @param end
|
||||
* @return
|
||||
*/
|
||||
@HashRateDB
|
||||
List<MinerIncomeDto> getMinerAvgPower(@Param("coin")String coin,@Param("start")LocalDateTime start, @Param("end")LocalDateTime end);
|
||||
|
||||
/**
|
||||
* 获取有效块数
|
||||
* @param coin
|
||||
* @param start
|
||||
* @param end
|
||||
* @return
|
||||
*/
|
||||
@DistributionDB
|
||||
BigDecimal getVaildBlcoks(@Param("coin")String coin, @Param("start")LocalDateTime start, @Param("end")LocalDateTime end);
|
||||
|
||||
/**
|
||||
* 批量插入小时收益
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
int batchInsertHourIncomes(@Param("coin")String coin,@Param("list")List<HourIncome> list);
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package com.m2pool.pool.task;
|
||||
|
||||
import com.m2pool.common.redis.service.RedisService;
|
||||
import com.m2pool.pool.dto.MinerIncomeDto;
|
||||
import com.m2pool.pool.entity.HourIncome;
|
||||
import com.m2pool.pool.enums.RedisKey;
|
||||
import com.m2pool.pool.mapper.IncomeMapper;
|
||||
import com.m2pool.pool.mapper.PoolMapper;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
/**
|
||||
* @Description 矿机收益 定时任务
|
||||
* @Date 2025/8/15 17:12
|
||||
* @Author yyb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
public class IncomeTask {
|
||||
|
||||
|
||||
@Resource
|
||||
private IncomeMapper incomeMapper;
|
||||
|
||||
|
||||
@Resource
|
||||
private RedisService redisService;
|
||||
|
||||
@Resource
|
||||
private PoolMapper poolMapper;
|
||||
|
||||
private static final int BATCH_SIZE = 1000;
|
||||
|
||||
private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors();
|
||||
private final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
|
||||
|
||||
public void batchInsertHourIncomes(String coin, List<HourIncome> hourIncomes) {
|
||||
// 用于记录执行过程中的异常
|
||||
AtomicReference<Exception> exceptionRef = new AtomicReference<>();
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < hourIncomes.size(); i += BATCH_SIZE) {
|
||||
int toIndex = Math.min(i + BATCH_SIZE, hourIncomes.size());
|
||||
List<HourIncome> subList = hourIncomes.subList(i, toIndex);
|
||||
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
incomeMapper.batchInsertHourIncomes(coin, subList);
|
||||
} catch (Exception e) {
|
||||
exceptionRef.set(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, executorService);
|
||||
|
||||
futures.add(future);
|
||||
}
|
||||
// 等待所有任务完成
|
||||
CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
||||
try {
|
||||
allFutures.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
// 如果有异常,将异常信息设置到 exceptionRef 中
|
||||
exceptionRef.set(e);
|
||||
}
|
||||
|
||||
// 如果有异常,抛出异常触发事务回滚
|
||||
if (exceptionRef.get() != null) {
|
||||
System.out.println("批量插入数据时发生错误"+exceptionRef.get());
|
||||
throw new RuntimeException("批量插入数据时发生错误", exceptionRef.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(cron = "5 21 0/1 * * ? ")
|
||||
public void nexaIncomeTask() {
|
||||
LocalDateTime now = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime end = now.minusHours(1);
|
||||
LocalDateTime start = now.minusHours(2);
|
||||
System.out.println("nexa 矿机收益入库开始"+ LocalDateTime.now());
|
||||
//1.获取m2pool中 1-2小时前的单个矿机算力
|
||||
List<MinerIncomeDto> nexaMinerIncomes = incomeMapper.getMinerAvgPower("nexa", start, end);
|
||||
//2.获取矿池nexa 总算力
|
||||
BigDecimal totalPower = nexaMinerIncomes.stream()
|
||||
.map(MinerIncomeDto::getAvgPower)
|
||||
.reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
|
||||
//3.获取当前nexa币价
|
||||
String price = redisService.getCacheObject(RedisKey.NEXA_PRICE);
|
||||
BigDecimal nexaPrice;
|
||||
if (price == null){
|
||||
nexaPrice = poolMapper.selectPrice("nexa");
|
||||
}else{
|
||||
nexaPrice = new BigDecimal(price);
|
||||
}
|
||||
//4.获取nexa 1-2小时前的报块数
|
||||
BigDecimal nexaBlocks = incomeMapper.getVaildBlcoks("nexa", start, end);
|
||||
|
||||
//5.计算单个矿机的收益
|
||||
List<HourIncome> totalIncomes = new ArrayList<>();
|
||||
nexaMinerIncomes.forEach(minerIncomeDto -> {
|
||||
BigDecimal income = nexaBlocks.multiply(minerIncomeDto.getAvgPower().divide(totalPower, 8, RoundingMode.HALF_UP));
|
||||
BigDecimal usdtIncome = income.multiply(nexaPrice);
|
||||
totalIncomes.add(HourIncome.builder()
|
||||
.user(minerIncomeDto.getUser())
|
||||
.miner(minerIncomeDto.getMiner())
|
||||
.income(income)
|
||||
.usdtIncome(usdtIncome)
|
||||
.build());
|
||||
});
|
||||
//6.矿机收益入库
|
||||
batchInsertHourIncomes("nexa",totalIncomes);
|
||||
|
||||
System.out.println("nexa 矿机收益入库完成"+ LocalDateTime.now());
|
||||
}
|
||||
@Scheduled(cron = "15 22 0/1 * * ? ")
|
||||
public void rxdIncomeTask() {
|
||||
LocalDateTime now = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime end = now.minusHours(1);
|
||||
LocalDateTime start = now.minusHours(2);
|
||||
System.out.println("rxd 矿机收益入库开始"+ LocalDateTime.now());
|
||||
//1.获取m2pool中 1-2小时前的单个矿机算力
|
||||
List<MinerIncomeDto> rxdMinerIncomes = incomeMapper.getMinerAvgPower("rxd", start, end);
|
||||
//2.获取矿池rxd总算力
|
||||
BigDecimal totalPower = rxdMinerIncomes.stream()
|
||||
.map(MinerIncomeDto::getAvgPower)
|
||||
.reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
|
||||
//3.获取当前rxd币价
|
||||
String price = redisService.getCacheObject(RedisKey.RXD_PRICE);
|
||||
BigDecimal rxdPrice;
|
||||
if (price == null){
|
||||
rxdPrice = poolMapper.selectPrice("rxd");
|
||||
}else{
|
||||
rxdPrice = new BigDecimal(price);
|
||||
}
|
||||
//4.获取rxd 1-2小时前的报块数
|
||||
BigDecimal rxdBlocks = incomeMapper.getVaildBlcoks("rxd", start, end);
|
||||
|
||||
//5.计算单个矿机的收益
|
||||
List<HourIncome> totalIncomes = new ArrayList<>();
|
||||
rxdMinerIncomes.forEach(minerIncomeDto -> {
|
||||
BigDecimal income = rxdBlocks.multiply(minerIncomeDto.getAvgPower().divide(totalPower, 8, RoundingMode.HALF_UP));
|
||||
BigDecimal usdtIncome = income.multiply(rxdPrice);
|
||||
totalIncomes.add(HourIncome.builder()
|
||||
.user(minerIncomeDto.getUser())
|
||||
.miner(minerIncomeDto.getMiner())
|
||||
.income(income)
|
||||
.usdtIncome(usdtIncome)
|
||||
.build());
|
||||
});
|
||||
//6.矿机收益入库
|
||||
batchInsertHourIncomes("rxd",totalIncomes);
|
||||
|
||||
System.out.println("rxd 矿机收益入库完成"+ LocalDateTime.now());
|
||||
}
|
||||
@Scheduled(cron = "25 23 0/1 * * ? ")
|
||||
public void monaIncomeTask() {
|
||||
LocalDateTime now = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime end = now.minusHours(1);
|
||||
LocalDateTime start = now.minusHours(2);
|
||||
System.out.println("mona 矿机收益入库开始"+ LocalDateTime.now());
|
||||
//1.获取m2pool中 1-2小时前的单个矿机算力
|
||||
List<MinerIncomeDto> monaMinerIncomes = incomeMapper.getMinerAvgPower("mona", start, end);
|
||||
//2.获取矿池mona总算力
|
||||
BigDecimal totalPower = monaMinerIncomes.stream()
|
||||
.map(MinerIncomeDto::getAvgPower)
|
||||
.reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
|
||||
//3.获取当前mona币价
|
||||
String price = redisService.getCacheObject(RedisKey.MONA_PRICE);
|
||||
BigDecimal monaPrice;
|
||||
if (price == null){
|
||||
monaPrice = poolMapper.selectPrice("mona");
|
||||
}else{
|
||||
monaPrice = new BigDecimal(price);
|
||||
}
|
||||
//4.获取mona 1-2小时前的报块数
|
||||
BigDecimal monaBlocks = incomeMapper.getVaildBlcoks("rxd", start, end);
|
||||
|
||||
//5.计算单个矿机的收益
|
||||
List<HourIncome> totalIncomes = new ArrayList<>();
|
||||
monaMinerIncomes.forEach(minerIncomeDto -> {
|
||||
BigDecimal income = monaBlocks.multiply(minerIncomeDto.getAvgPower().divide(totalPower, 8, RoundingMode.HALF_UP));
|
||||
BigDecimal usdtIncome = income.multiply(monaPrice);
|
||||
totalIncomes.add(HourIncome.builder()
|
||||
.user(minerIncomeDto.getUser())
|
||||
.miner(minerIncomeDto.getMiner())
|
||||
.income(income)
|
||||
.usdtIncome(usdtIncome)
|
||||
.build());
|
||||
});
|
||||
//6.矿机收益入库
|
||||
batchInsertHourIncomes("mona",totalIncomes);
|
||||
|
||||
System.out.println("mona 矿机收益入库完成"+ LocalDateTime.now());
|
||||
}
|
||||
@Scheduled(cron = "35 24 0/1 * * ? ")
|
||||
public void grsIncomeTask() {
|
||||
LocalDateTime now = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime end = now.minusHours(1);
|
||||
LocalDateTime start = now.minusHours(2);
|
||||
System.out.println("grs 矿机收益入库开始"+ LocalDateTime.now());
|
||||
//1.获取m2pool中 1-2小时前的单个矿机算力
|
||||
List<MinerIncomeDto> grsMinerIncomes = incomeMapper.getMinerAvgPower("rxd", start, end);
|
||||
//2.获取矿池grs总算力
|
||||
BigDecimal totalPower = grsMinerIncomes.stream()
|
||||
.map(MinerIncomeDto::getAvgPower)
|
||||
.reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
|
||||
//3.获取当前grs币价
|
||||
String price = redisService.getCacheObject(RedisKey.GRS_PRICE);
|
||||
BigDecimal grsPrice ;
|
||||
if (price == null){
|
||||
grsPrice = poolMapper.selectPrice("grs");
|
||||
}else{
|
||||
grsPrice = new BigDecimal(price);
|
||||
}
|
||||
//4.获取rxd 1-2小时前的报块数
|
||||
BigDecimal grsBlocks = incomeMapper.getVaildBlcoks("grs", start, end);
|
||||
|
||||
//5.计算单个矿机的收益
|
||||
List<HourIncome> totalIncomes = new ArrayList<>();
|
||||
grsMinerIncomes.forEach(minerIncomeDto -> {
|
||||
BigDecimal income = grsBlocks.multiply(minerIncomeDto.getAvgPower().divide(totalPower, 8, RoundingMode.HALF_UP));
|
||||
BigDecimal usdtIncome = income.multiply(grsPrice);
|
||||
totalIncomes.add(HourIncome.builder()
|
||||
.user(minerIncomeDto.getUser())
|
||||
.miner(minerIncomeDto.getMiner())
|
||||
.income(income)
|
||||
.usdtIncome(usdtIncome)
|
||||
.build());
|
||||
});
|
||||
//6.矿机收益入库
|
||||
batchInsertHourIncomes("grs",totalIncomes);
|
||||
|
||||
System.out.println("grs 矿机收益入库完成"+ LocalDateTime.now());
|
||||
}
|
||||
|
||||
//TODO 门罗收益
|
||||
|
||||
}
|
||||
@@ -101,9 +101,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.NEXA.getCoin()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.NEXA.getCoin()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -190,9 +190,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.NEXA.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.NEXA.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -277,9 +277,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.MONA.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.MONA.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -363,9 +363,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.DGBO.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.DGBO.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -449,9 +449,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.DGBQ.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.DGBQ.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -535,9 +535,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.DGBS.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.DGBS.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -621,9 +621,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.RXD.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.RXD.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -707,9 +707,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.ALPH.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.ALPH.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -793,9 +793,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.ENX.getName()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.ENX.getName()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -882,9 +882,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.MONERO.getCoin()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.MONERO.getCoin()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
@@ -973,9 +973,9 @@ public class OffLineNoticeTask {
|
||||
//执行通知
|
||||
List<String> emails = userEmails.getOrDefault(e.getUser(), null);
|
||||
if(StringUtils.isNotNull(emails)){
|
||||
String text = "您的"+Pools.SHA3X.getCoin()+"下挖矿账户: "+e.getUser()+"有矿机离线!离线矿机列表如下:\n" +
|
||||
e.getMiners() + " \n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
String text = "您的"+Pools.SHA3X.getCoin()+"下挖矿账户: "+e.getUser()+"\n有" +
|
||||
e.getOffline() + "台矿机离线!\n"+
|
||||
"若您的矿机是因异常断开,请及时处理!";
|
||||
emails.stream().forEach(email ->{
|
||||
System.out.println("用户"+e.getUser()+"矿机离线通知到"+email);
|
||||
EmailEntity entity = new EmailEntity();
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.m2pool.pool.task;
|
||||
|
||||
import com.m2pool.pool.entity.BlockInfo;
|
||||
import com.m2pool.pool.mapper.PoolMapper;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static com.m2pool.pool.utils.dome4j.*;
|
||||
|
||||
/**
|
||||
* @Description TODO
|
||||
* @Date 2025/9/28 09:39
|
||||
* @Author yyb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
public class XtmBlockInfoTask {
|
||||
|
||||
@Resource
|
||||
private PoolMapper poolMapper;
|
||||
|
||||
@Scheduled(cron = "0 0/10 * * * ?")
|
||||
public void Sha3xBlockInfoToDB(){
|
||||
BlockInfo xtmBlockInfoForXml = getSha3xBlockInfoForXml();
|
||||
//入库
|
||||
int i = poolMapper.insertXtmBlockInfo(xtmBlockInfoForXml);
|
||||
if (i > 0){
|
||||
System.out.println("sha3x信息入库成功");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.m2pool.pool.utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class XtmPoolInfo {
|
||||
private int id;
|
||||
private String name;
|
||||
private String icon_class;
|
||||
private int block_total;
|
||||
private Object rewards;
|
||||
private int isolated_block_total;
|
||||
private String network_hashrate;
|
||||
private String pool_hashrate;
|
||||
private int miner_count;
|
||||
private String coin_price;
|
||||
private Object lucky_3d;
|
||||
private Object lucky_7d;
|
||||
private Object lucky_30d;
|
||||
private int status;
|
||||
private int default_fee;
|
||||
private String explore_url;
|
||||
private String calculator;
|
||||
private int rank;
|
||||
private String algorithm;
|
||||
private int time;
|
||||
private String tutorial_address;
|
||||
private String pay_method;
|
||||
private Object merge_mining;
|
||||
private Object max_supply;
|
||||
private Object circulating_supply;
|
||||
private String address;
|
||||
private String mining_address;
|
||||
private int min_withdraw_amount;
|
||||
private String base_reward;
|
||||
private double block_time;
|
||||
private String suitable_unit;
|
||||
private long height;
|
||||
private String created_at;
|
||||
private String updated_at;
|
||||
private int new_;
|
||||
private String location;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.m2pool.pool.utils;
|
||||
|
||||
import com.alibaba.nacos.shaded.com.google.gson.Gson;
|
||||
import com.alibaba.nacos.shaded.com.google.gson.reflect.TypeToken;
|
||||
import com.m2pool.pool.entity.BlockInfo;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @Description TODO
|
||||
* @Date 2025/9/28 09:24
|
||||
* @Author yyb
|
||||
*/
|
||||
public class dome4j {
|
||||
public static void main(String[] args) throws Exception {
|
||||
getSha3xBlockInfoForXml();
|
||||
}
|
||||
|
||||
|
||||
public static BlockInfo getSha3xBlockInfoForXml() {
|
||||
try {
|
||||
// 从指定 URL 获取 XML 数据
|
||||
String xmlData = fetchXmlData("https://www.dxpool.com/api/address-mining/pools");
|
||||
// 移除提示信息
|
||||
BlockInfo blockInfo = extractXtmBlockInfo(xmlData);
|
||||
System.out.println(blockInfo);
|
||||
return blockInfo;
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从 JSON 数据中提取 id 为 30 的节点信息到 BlockInfo 中
|
||||
* @param jsonData JSON 数据字符串
|
||||
* @return BlockInfo 对象,若未找到则返回 null
|
||||
*/
|
||||
private static BlockInfo extractXtmBlockInfo(String jsonData) {
|
||||
Gson gson = new Gson();
|
||||
List<XtmPoolInfo> xtmPoolInfoList = gson.fromJson(jsonData, new TypeToken<List<XtmPoolInfo>>() {}.getType());
|
||||
for (XtmPoolInfo xtmPoolInfo : xtmPoolInfoList) {
|
||||
if (xtmPoolInfo.getId() == 30) {
|
||||
BlockInfo blockInfo = new BlockInfo();
|
||||
blockInfo.setDifficulty(BigDecimal.ZERO);
|
||||
blockInfo.setHeight(xtmPoolInfo.getHeight());
|
||||
blockInfo.setPrice(new BigDecimal(xtmPoolInfo.getCoin_price()));
|
||||
// 转换单位为 H/s
|
||||
BigDecimal powerInHPerSecond = convertToHPerSecond(xtmPoolInfo.getNetwork_hashrate());
|
||||
blockInfo.setPower(powerInHPerSecond);
|
||||
|
||||
blockInfo.setReward(new BigDecimal(xtmPoolInfo.getBase_reward()));
|
||||
blockInfo.setFees(new BigDecimal(xtmPoolInfo.getDefault_fee()));
|
||||
blockInfo.setProfit(BigDecimal.ZERO);
|
||||
return blockInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 从指定 URL 获取 XML 数据
|
||||
* @param urlStr 目标 URL
|
||||
* @return XML 数据字符串
|
||||
* @throws IOException 网络请求异常
|
||||
*/
|
||||
public static String fetchXmlData(String urlStr) throws IOException {
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
|
||||
//// 配置 HTTP 代理信息,需将代理地址和端口替换为实际值
|
||||
//String proxyHost = "127.0.0.1";
|
||||
//int proxyPort = 7897;
|
||||
//Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
|
||||
//
|
||||
//URL url = new URL(urlStr);
|
||||
//// 使用代理创建连接
|
||||
//HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
|
||||
//connection.setRequestMethod("GET");
|
||||
|
||||
try (InputStream inputStream = connection.getInputStream();
|
||||
ByteArrayOutputStream result = new ByteArrayOutputStream()) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = inputStream.read(buffer)) != -1) {
|
||||
result.write(buffer, 0, length);
|
||||
}
|
||||
return result.toString(String.valueOf(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将带单位的哈希率转换为 H/s
|
||||
* @param hashrateStr 带单位的哈希率字符串,例如 "28.28 TH/s"
|
||||
* @return 转换为 H/s 后的 BigDecimal 数值
|
||||
*/
|
||||
private static BigDecimal convertToHPerSecond(String hashrateStr) {
|
||||
// 定义正则表达式,用于匹配数值和单位
|
||||
Pattern pattern = Pattern.compile("([0-9.]+)\\s*([KMGTPEZY]?)H/s");
|
||||
Matcher matcher = pattern.matcher(hashrateStr);
|
||||
|
||||
if (matcher.find()) {
|
||||
BigDecimal value = new BigDecimal(matcher.group(1));
|
||||
String unit = matcher.group(2);
|
||||
|
||||
// 根据单位计算换算系数
|
||||
BigInteger multiplier;
|
||||
switch (unit) {
|
||||
case "K":
|
||||
multiplier = BigInteger.valueOf(1000);
|
||||
break;
|
||||
case "M":
|
||||
multiplier = BigInteger.valueOf(1000000);
|
||||
break;
|
||||
case "G":
|
||||
multiplier = BigInteger.valueOf(1000000000);
|
||||
break;
|
||||
case "T":
|
||||
multiplier = BigInteger.valueOf(1000000000000L);
|
||||
break;
|
||||
case "P":
|
||||
multiplier = BigInteger.valueOf(1000000000000000L);
|
||||
break;
|
||||
case "E":
|
||||
multiplier = new BigInteger("1000000000000000000");
|
||||
break;
|
||||
case "Z":
|
||||
multiplier = new BigInteger("1000000000000000000000");
|
||||
break;
|
||||
case "Y":
|
||||
multiplier = new BigInteger("1000000000000000000000000");
|
||||
break;
|
||||
default:
|
||||
multiplier = BigInteger.ONE;
|
||||
}
|
||||
|
||||
return value.multiply(new BigDecimal(multiplier));
|
||||
}
|
||||
|
||||
// 如果未匹配到有效数据,返回 0
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.m2pool.pool.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description
|
||||
* @Date 2025/9/05 14:05
|
||||
* @Author yyb
|
||||
*/
|
||||
@Data
|
||||
public class DataSupplementVo {
|
||||
private String coin;
|
||||
private String date;
|
||||
// key值为 dsadasdwfddasdfsafadsfs
|
||||
private String key;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.m2pool.pool.mapper.IncomeMapper">
|
||||
|
||||
|
||||
<select id="getMinerAvgPower" resultType="com.m2pool.pool.dto.MinerIncomeDto">
|
||||
select `user`,miner,avg(mhs30m) as avgPower from ${coin}_mhsv2
|
||||
where `date` >= #{start} and `date` <![CDATA[ <= ]]> #{end}
|
||||
group by `user`,miner
|
||||
</select>
|
||||
<select id="getVaildBlcoks" resultType="java.math.BigDecimal">
|
||||
select count(*) from ${coin}_blkreportprofitv2 where state = 1 and `date` >= #{start} and `date` <![CDATA[ <= ]]> #{end}
|
||||
</select>
|
||||
|
||||
|
||||
<insert id="batchInsertHourIncomes">
|
||||
INSERT INTO ${coin}_hour_income (user, miner, income, usdt_income)
|
||||
VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.user}, #{item.miner}, #{item.income}, #{item.usdtIncome})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user