feat: 增加任务模板的增删改查
This commit is contained in:
@@ -2,6 +2,7 @@ package com.lanyuanxiaoyao.leopard.server.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||
import com.lanyuanxiaoyao.leopard.server.service.StockService;
|
||||
import com.lanyuanxiaoyao.service.template.controller.GlobalResponse;
|
||||
import java.util.Arrays;
|
||||
@@ -106,6 +107,11 @@ public class CommonOptionsController {
|
||||
new Option("已退市", false)
|
||||
)
|
||||
);
|
||||
case "task_template_type" -> GlobalResponse.responseSuccess(
|
||||
Arrays.stream(TaskTemplate.Type.values())
|
||||
.map(type -> new Option(type.getChineseName(), type.name()))
|
||||
.toList()
|
||||
);
|
||||
default -> GlobalResponse.responseSuccess(List.of());
|
||||
};
|
||||
}
|
||||
@@ -132,6 +138,12 @@ public class CommonOptionsController {
|
||||
.toList(),
|
||||
field
|
||||
));
|
||||
case "task_template_type" -> GlobalResponse.responseSuccess(buildMapping(
|
||||
Arrays.stream(TaskTemplate.Type.values())
|
||||
.map(type -> new Mapping(type.name(), type.getChineseName()))
|
||||
.toList(),
|
||||
field
|
||||
));
|
||||
default -> GlobalResponse.responseSuccess(Map.of());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.templates.ClassTaskTemplate;
|
||||
import com.lanyuanxiaoyao.leopard.server.service.TaskTemplateService;
|
||||
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
|
||||
import java.util.function.Function;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("task_template")
|
||||
public class TaskTemplateController extends SimpleControllerSupport<TaskTemplate, TaskTemplateController.Item, TaskTemplateController.Item, TaskTemplateController.Item> {
|
||||
public TaskTemplateController(TaskTemplateService service) {
|
||||
super(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Item, TaskTemplate> saveItemMapper() {
|
||||
return item -> {
|
||||
return switch (item.type) {
|
||||
case CLASS -> {
|
||||
var template = new ClassTaskTemplate();
|
||||
template.setName(item.name());
|
||||
template.setDescription(item.description());
|
||||
template.setClazz(item.clazz());
|
||||
yield template;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
private Item convert(TaskTemplate template) {
|
||||
return switch (template.getType()) {
|
||||
case CLASS -> {
|
||||
ClassTaskTemplate classTaskTemplate = (ClassTaskTemplate) template;
|
||||
yield new Item(classTaskTemplate.getId(), classTaskTemplate.getName(), classTaskTemplate.getDescription(), classTaskTemplate.getType(), classTaskTemplate.getClazz());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<TaskTemplate, Item> listItemMapper() {
|
||||
return this::convert;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<TaskTemplate, Item> detailItemMapper() {
|
||||
return this::convert;
|
||||
}
|
||||
|
||||
public record Item(
|
||||
Long id,
|
||||
String name,
|
||||
String description,
|
||||
TaskTemplate.Type type,
|
||||
String clazz
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.entity;
|
||||
|
||||
import com.lanyuanxiaoyao.leopard.server.Constants;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.base.SimpleEnum;
|
||||
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.Inheritance;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.hibernate.annotations.SoftDelete;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@Entity
|
||||
@SoftDelete
|
||||
@DynamicUpdate
|
||||
@DynamicInsert
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
@Table(name = Constants.DATABASE_PREFIX + "task_template")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public abstract class TaskTemplate extends SimpleEntity {
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
@Column(nullable = false, length = 500)
|
||||
private String description;
|
||||
|
||||
public abstract Type getType();
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Type implements SimpleEnum {
|
||||
CLASS("类任务");
|
||||
|
||||
private final String chineseName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.entity.templates;
|
||||
|
||||
import com.lanyuanxiaoyao.leopard.server.Constants;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.hibernate.annotations.SoftDelete;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@Entity
|
||||
@SoftDelete
|
||||
@DynamicUpdate
|
||||
@DynamicInsert
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
@Table(name = Constants.DATABASE_PREFIX + "task_template_class")
|
||||
public class ClassTaskTemplate extends TaskTemplate {
|
||||
@Column(nullable = false)
|
||||
private String clazz;
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.CLASS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||
import com.lanyuanxiaoyao.service.template.repository.SimpleRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface TaskTemplateRepository extends SimpleRepository<TaskTemplate> {
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.service;
|
||||
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
||||
import com.lanyuanxiaoyao.leopard.server.repository.StockRepository;
|
||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -18,58 +15,13 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class StockService extends SimpleServiceSupport<Stock> {
|
||||
private final StockRepository stockRepository;
|
||||
private final TuShareService tuShareService;
|
||||
private final TaskService taskService;
|
||||
|
||||
public StockService(StockRepository repository, TuShareService tuShareService, TaskService taskService) {
|
||||
public StockService(StockRepository repository) {
|
||||
super(repository);
|
||||
this.stockRepository = repository;
|
||||
this.tuShareService = tuShareService;
|
||||
this.taskService = taskService;
|
||||
}
|
||||
|
||||
public List<String> findDistinctIndustries() {
|
||||
return stockRepository.findDistinctIndustries();
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
taskService.startTask(
|
||||
"股票列表刷新",
|
||||
"股票列表刷新",
|
||||
() -> {
|
||||
var stocks = list();
|
||||
var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock));
|
||||
tuShareService.stockList()
|
||||
.data()
|
||||
.items()
|
||||
.forEach(item -> {
|
||||
var code = item.get(0);
|
||||
var name = item.get(1);
|
||||
var fullname = item.get(2);
|
||||
var market = EnumUtil.fromString(Stock.Market.class, item.get(3));
|
||||
var industry = item.get(4);
|
||||
var listed = StrUtil.equals("L", item.get(5));
|
||||
if (stocksMap.containsKey(code)) {
|
||||
var stock = stocksMap.get(code);
|
||||
stock.setName(name);
|
||||
stock.setFullname(fullname);
|
||||
stock.setMarket(market);
|
||||
stock.setIndustry(industry);
|
||||
stock.setListed(listed);
|
||||
} else {
|
||||
var stock = new Stock();
|
||||
stock.setCode(code);
|
||||
stock.setName(name);
|
||||
stock.setFullname(fullname);
|
||||
stock.setMarket(market);
|
||||
stock.setIndustry(industry);
|
||||
stock.setListed(listed);
|
||||
stocks.add(stock);
|
||||
}
|
||||
});
|
||||
repository.saveOrUpdateAllByNotNullProperties(stocks);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
||||
import com.lanyuanxiaoyao.leopard.server.repository.TaskRepository;
|
||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.function.Supplier;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
@@ -17,36 +13,7 @@ import org.springframework.transaction.support.TransactionTemplate;
|
||||
@Slf4j
|
||||
@Service
|
||||
public class TaskService extends SimpleServiceSupport<Task> {
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
|
||||
public TaskService(TaskRepository repository, TransactionTemplate transactionTemplate) {
|
||||
public TaskService(TaskRepository repository) {
|
||||
super(repository);
|
||||
this.transactionTemplate = transactionTemplate;
|
||||
}
|
||||
|
||||
public void startTask(String name, String description, Supplier<String> executor) {
|
||||
var task = new Task();
|
||||
task.setName(name);
|
||||
task.setDescription(description);
|
||||
task.setStatus(Task.Status.RUNNING);
|
||||
task.setLaunchedTime(LocalDateTime.now());
|
||||
repository.save(task);
|
||||
transactionTemplate.execute(status -> {
|
||||
try {
|
||||
var result = executor.get();
|
||||
task.setStatus(Task.Status.SUCCESS);
|
||||
if (StrUtil.isNotBlank(result)) {
|
||||
task.setResult(result);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
task.setStatus(Task.Status.FAILURE);
|
||||
task.setError(e.getMessage());
|
||||
status.setRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
task.setFinishedTime(LocalDateTime.now());
|
||||
repository.save(task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.service;
|
||||
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||
import com.lanyuanxiaoyao.leopard.server.repository.TaskTemplateRepository;
|
||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class TaskTemplateService extends SimpleServiceSupport<TaskTemplate> {
|
||||
public TaskTemplateService(TaskTemplateRepository repository) {
|
||||
super(repository);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.service.task;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.Task;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.TaskTemplate;
|
||||
import com.lanyuanxiaoyao.leopard.server.service.TaskService;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public abstract class TaskRunner {
|
||||
private final TaskService taskService;
|
||||
|
||||
protected TaskRunner(TaskService taskService) {
|
||||
this.taskService = taskService;
|
||||
}
|
||||
|
||||
public void runTask(TaskTemplate template, Map<String, Object> params) {
|
||||
var task = new Task();
|
||||
task.setName(template.getName());
|
||||
task.setDescription(template.getDescription());
|
||||
task.setStatus(Task.Status.RUNNING);
|
||||
task.setLaunchedTime(LocalDateTime.now());
|
||||
task.setId(taskService.save(task));
|
||||
try {
|
||||
var result = run(params);
|
||||
task.setStatus(Task.Status.SUCCESS);
|
||||
if (StrUtil.isNotBlank(result)) {
|
||||
task.setResult(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
task.setStatus(Task.Status.FAILURE);
|
||||
task.setError(e.getMessage());
|
||||
}
|
||||
task.setFinishedTime(LocalDateTime.now());
|
||||
taskService.save(task);
|
||||
}
|
||||
|
||||
abstract String run(Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.lanyuanxiaoyao.leopard.server.service.task;
|
||||
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.lanyuanxiaoyao.leopard.server.entity.Stock;
|
||||
import com.lanyuanxiaoyao.leopard.server.service.StockService;
|
||||
import com.lanyuanxiaoyao.leopard.server.service.TaskService;
|
||||
import com.lanyuanxiaoyao.leopard.server.service.TuShareService;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class UpdateStockInformationTask extends TaskRunner {
|
||||
private final StockService stockService;
|
||||
private final TuShareService tuShareService;
|
||||
|
||||
public UpdateStockInformationTask(TaskService taskService, StockService stockService, TuShareService tuShareService) {
|
||||
super(taskService);
|
||||
this.stockService = stockService;
|
||||
this.tuShareService = tuShareService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String run(Map<String, Object> params) {
|
||||
var stocks = stockService.list();
|
||||
var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock));
|
||||
tuShareService.stockList()
|
||||
.data()
|
||||
.items()
|
||||
.forEach(item -> {
|
||||
var code = item.get(0);
|
||||
var name = item.get(1);
|
||||
var fullname = item.get(2);
|
||||
var market = EnumUtil.fromString(Stock.Market.class, item.get(3));
|
||||
var industry = item.get(4);
|
||||
var listed = StrUtil.equals("L", item.get(5));
|
||||
if (stocksMap.containsKey(code)) {
|
||||
var stock = stocksMap.get(code);
|
||||
stock.setName(name);
|
||||
stock.setFullname(fullname);
|
||||
stock.setMarket(market);
|
||||
stock.setIndustry(industry);
|
||||
stock.setListed(listed);
|
||||
} else {
|
||||
var stock = new Stock();
|
||||
stock.setCode(code);
|
||||
stock.setName(name);
|
||||
stock.setFullname(fullname);
|
||||
stock.setMarket(market);
|
||||
stock.setIndustry(industry);
|
||||
stock.setListed(listed);
|
||||
stocks.add(stock);
|
||||
}
|
||||
});
|
||||
stockService.save(stocks);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user