REQ-2752: 刷审批流程按钮
This commit is contained in:
parent
ad31d3feba
commit
4e92024d56
@ -1,12 +1,16 @@
|
||||
package cn.axzo.msg.center.message.controller;
|
||||
|
||||
import cn.axzo.msg.center.dal.MessageTemplateButtonV3Dao;
|
||||
import cn.axzo.msg.center.dal.MessageTemplateV3Dao;
|
||||
import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3;
|
||||
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
|
||||
import cn.axzo.msg.center.service.domain.UrlConfig;
|
||||
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
|
||||
import cn.axzo.msg.center.service.pending.client.WorkflowButtonSyncClient;
|
||||
import cn.axzo.msg.center.service.pending.request.WorkflowSyncButtonsRequest;
|
||||
import cn.axzo.msg.center.service.pending.request.WorkflowSyncButtonsRequest.WorkflowButton;
|
||||
import cn.axzo.msg.center.utils.AsyncRunTasks;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -14,6 +18,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import static java.util.function.Function.identity;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
@ -26,31 +32,59 @@ import static java.util.stream.Collectors.toMap;
|
||||
@RequiredArgsConstructor
|
||||
public class WorkflowButtonSyncClientController implements WorkflowButtonSyncClient {
|
||||
|
||||
private final MessageTemplateV3Dao messageTemplateV3Dao;
|
||||
private final MessageTemplateButtonV3Dao messageTemplateButtonV3Dao;
|
||||
|
||||
@Override
|
||||
public CommonResponse<Void> syncButtons(WorkflowSyncButtonsRequest request) {
|
||||
public CommonResponse<Void> syncButtons(WorkflowSyncButtonsRequest request) throws Exception {
|
||||
Map<String, MessageTemplateV3> code2Template = messageTemplateV3Dao.lambdaQuery()
|
||||
.list().stream()
|
||||
.collect(toMap(MessageTemplateV3::getCode, identity()));
|
||||
Map<String, WorkflowButton> code2FlowButton =
|
||||
request.getButtons().stream()
|
||||
.collect(toMap(WorkflowButton::getCode, identity(),
|
||||
(oldValue, newValue) -> oldValue));
|
||||
List<MessageTemplateButtonV3> buttons =
|
||||
messageTemplateButtonV3Dao.lambdaQuery().list();
|
||||
|
||||
int nThreads = 10;
|
||||
AsyncRunTasks tasks = new AsyncRunTasks(Executors.newFixedThreadPool(nThreads));
|
||||
Semaphore semaphore = new Semaphore(nThreads);
|
||||
for (MessageTemplateButtonV3 button : buttons) {
|
||||
WorkflowButton workflowButton = code2FlowButton.get(button.getCode());
|
||||
if (workflowButton == null) continue;
|
||||
MessageTemplateButtonV3 update = new MessageTemplateButtonV3();
|
||||
update.setId(button.getId());
|
||||
if (button.getCategory() == RouterCategoryEnum.JUMP) {
|
||||
UrlConfig urlConfig = new UrlConfig();
|
||||
urlConfig.applyUrlAsDefaults(workflowButton.getUrl());
|
||||
update.setUrlConfig(urlConfig);
|
||||
} else {
|
||||
update.setApiUrl(workflowButton.getUrl());
|
||||
}
|
||||
messageTemplateButtonV3Dao.updateById(update);
|
||||
semaphore.acquire();
|
||||
tasks.runAsync(() -> {
|
||||
try {
|
||||
sync(code2Template, code2FlowButton, button);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
}
|
||||
tasks.awaitTermination();
|
||||
return CommonResponse.success();
|
||||
}
|
||||
|
||||
private void sync(Map<String, MessageTemplateV3> code2Template,
|
||||
Map<String, WorkflowButton> code2FlowButton,
|
||||
MessageTemplateButtonV3 button) {
|
||||
MessageTemplateV3 template = code2Template.get(button.getTemplateCode());
|
||||
if (template.getMsgCategory() != MessageCategoryEnum.APPROVAL_PENDING_MESSAGE)
|
||||
return;
|
||||
|
||||
WorkflowButton workflowButton = code2FlowButton.get(button.getCode());
|
||||
if (workflowButton == null) return;
|
||||
MessageTemplateButtonV3 update = new MessageTemplateButtonV3();
|
||||
update.setId(button.getId());
|
||||
if (button.getCategory() == RouterCategoryEnum.JUMP) {
|
||||
UrlConfig urlConfig = new UrlConfig();
|
||||
urlConfig.applyUrlAsDefaults(workflowButton.getUrl());
|
||||
update.setUrlConfig(urlConfig);
|
||||
} else {
|
||||
update.setApiUrl(workflowButton.getUrl());
|
||||
}
|
||||
messageTemplateButtonV3Dao.updateById(update);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.axzo.msg.center.utils;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public class AsyncRunTasks extends AsyncTasks<Void> {
|
||||
|
||||
private final ExecutorService executor;
|
||||
|
||||
/**
|
||||
* use common pool
|
||||
*/
|
||||
public AsyncRunTasks() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public AsyncRunTasks(ExecutorService executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public void runAsync(Runnable runnable) {
|
||||
CompletableFuture<Void> future = executor == null
|
||||
? CompletableFuture.runAsync(runnable)
|
||||
: CompletableFuture.runAsync(runnable, executor);
|
||||
add(future);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package cn.axzo.msg.center.utils;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public class AsyncSupplyTasks extends AsyncTasks<Object> {
|
||||
|
||||
private final ExecutorService executor;
|
||||
|
||||
/**
|
||||
* use common pool
|
||||
*/
|
||||
public AsyncSupplyTasks() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public AsyncSupplyTasks(ExecutorService executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public <U> FutureWrapper<U> supplyAsync(Supplier<U> supplier) {
|
||||
CompletableFuture<U> future = executor == null
|
||||
? CompletableFuture.supplyAsync(supplier)
|
||||
: CompletableFuture.supplyAsync(supplier, executor);
|
||||
//noinspection unchecked
|
||||
add((CompletableFuture<Object>) future);
|
||||
return new FutureWrapper<>(future);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package cn.axzo.msg.center.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public class AsyncTasks<T> {
|
||||
|
||||
private final List<CompletableFuture<T>> futures = Collections.synchronizedList(new ArrayList<>());
|
||||
private final boolean removeFutureWhenComplete;
|
||||
|
||||
public AsyncTasks() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
AsyncTasks(boolean removeFutureWhenComplete) {
|
||||
this.removeFutureWhenComplete = removeFutureWhenComplete;
|
||||
}
|
||||
|
||||
public void add(CompletableFuture<T> future) {
|
||||
futures.add(future);
|
||||
if (removeFutureWhenComplete)
|
||||
future.whenComplete((unused, throwable) -> futures.remove(future));
|
||||
}
|
||||
|
||||
CompletableFuture<T> getFuture(int index) {
|
||||
return futures.get(index);
|
||||
}
|
||||
|
||||
public void awaitTermination() {
|
||||
collectAll().join();
|
||||
}
|
||||
|
||||
public void awaitTermination(long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
collectAll().get(timeout, unit);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> collectAll() {
|
||||
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package cn.axzo.msg.center.utils;
|
||||
|
||||
import cn.axzo.basics.common.exception.ServiceException;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
public class FutureWrapper<T> {
|
||||
|
||||
private final CompletableFuture<T> future;
|
||||
|
||||
public T get() {
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
log.error("执行异常", e);
|
||||
throw new ServiceException("执行异常");
|
||||
}
|
||||
}
|
||||
|
||||
public T get(long timeout, TimeUnit unit) {
|
||||
try {
|
||||
return future.get(timeout, unit);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
log.error("执行异常", e);
|
||||
throw new ServiceException("执行异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,6 @@ import javax.validation.Valid;
|
||||
public interface WorkflowButtonSyncClient {
|
||||
|
||||
@PostMapping(value = "/pending-message/workflow/syncButtons", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
CommonResponse<Void> syncButtons(@RequestBody @Valid WorkflowSyncButtonsRequest request);
|
||||
CommonResponse<Void> syncButtons(@RequestBody @Valid WorkflowSyncButtonsRequest request) throws Exception;
|
||||
|
||||
}
|
||||
@ -23,6 +23,11 @@ public class WorkflowSyncButtonsRequest {
|
||||
private String code;
|
||||
private RouterCategoryEnum category;
|
||||
private String url;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user