diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/TingyunService.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/TingyunService.java new file mode 100644 index 00000000..61e52419 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/TingyunService.java @@ -0,0 +1,153 @@ +package cn.axzo.msg.center.inside.notices.service.impl; + +import cn.axzo.msg.center.dal.TingyunInterfaceListDao; +import cn.axzo.msg.center.dal.mapper.TingyunInterfaceListMapper; +import cn.axzo.msg.center.domain.entity.TingyunInterfaceList; +import cn.axzo.msg.center.inside.notices.utils.Queries; +import cn.axzo.msg.center.notices.manager.api.dto.request.plat.TingyunInterfaceListRequest; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.util.concurrent.Uninterruptibles; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import okhttp3.FormBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import org.apache.commons.collections4.CollectionUtils; +import org.joda.time.DateTime; +import org.springframework.stereotype.Service; + +import java.time.Duration; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import static java.util.stream.Collectors.toSet; + +/** + * @author yanglin + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class TingyunService { + + private final TingyunInterfaceListDao tingyunInterfaceListDao; + private final TingyunInterfaceListMapper tingyunInterfaceListMapper; + private final ExecutorService scheduler = Executors.newSingleThreadExecutor(); + private volatile boolean isRunning = false; + private volatile boolean aborted = false; + + public String interfaceList(TingyunInterfaceListRequest request) { + synchronized (this) { + if (isRunning) + return "前面一个操作正在执行中.."; + isRunning = true; + } + scheduler.execute(() -> { + try { + interfaceListImpl(request); + } catch (Exception e) { + log.error("执行失败", e); + } finally { + synchronized (this) { + isRunning = false; + aborted = false; + } + } + }); + return "scheduled..."; + } + + public synchronized void abort() { + aborted = true; + } + + private void interfaceListImpl(TingyunInterfaceListRequest request) throws Exception { + log.info("开始执行, request={}", request); + Set applicationIds = request.getActions().stream() + .map(TingyunInterfaceListRequest.ActionInfo::getApplicationId) + .collect(toSet()); + tingyunInterfaceListMapper.delete(Queries.query(TingyunInterfaceList.class) + .in(TingyunInterfaceList::getApplicationId, applicationIds)); + OkHttpClient httpClient = httpClient(); + DateTime startDate = new DateTime(request.determineStartDate()); + DateTime endDate = new DateTime(request.determineEndDate()); + outer: + for (TingyunInterfaceListRequest.ActionInfo action : request.getActions()) { + for (DateTime date = startDate; + date.isBefore(endDate) || date.isEqual(endDate); + date = date.plusDays(1)) { + + if (aborted) { + log.info("中断执行, request={}", request); + break outer; + } + + FormBody formBody = new FormBody.Builder() + .add("timePeriod", "1440") + .add("endTime", date.toString("yyyy-MM-dd 00:00")) + .add("bizSystemId", request.getBizSystemId() + "") + .add("sortField", "response") + .add("sortDirection", "DESC") + .add("actionName", action.getActionName()) + .add("applicationId", action.getApplicationId() + "") + .build(); + + Request httpRequest = new Request.Builder() + .post(formBody) + .header("accept", "application/json, text/plain, */*") + .header("authorization", request.getAuth()) + .url("https://wukong1.tingyun.com/server-api/webaction/list/interfaceList") + .build(); + + String responseBody = httpClient.newCall(httpRequest).execute().body().string(); + JSONObject resp = JSON.parseObject(responseBody); + if (resp.getIntValue("code") != 200) + throw new RuntimeException("请求失败: " + responseBody); + List content = resp.getObject("data", InterfaceListData.class).getContent(); + if (CollectionUtils.isNotEmpty(content)) { + Date d = date.toDate(); + content.forEach(c -> c.setDate(d)); + tingyunInterfaceListDao.saveBatch(content); + } else { + TingyunInterfaceList empty = TingyunInterfaceList.emptyResponse( + action.getApplicationId(), action.getActionName(), date.toDate()); + tingyunInterfaceListMapper.insert(empty); + } + + Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + } + } + log.info("结束执行, request={}", request); + } + + private OkHttpClient httpClient() { + return new OkHttpClient.Builder() + // 设置连接超时时间 + .connectTimeout(Duration.ofSeconds(30)) + // 设置读超时时间 + .readTimeout(Duration.ofSeconds(60)) + // 设置写超时时间 + .writeTimeout(Duration.ofSeconds(60)) + // 设置完整请求超时时间 + .callTimeout(Duration.ofSeconds(120)) + .build(); + } + + @Data + public static class TingyunResponse { + private int code; + private T date; + } + + @Data + public static class InterfaceListData { + private int totalElements; + private List content; + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/PrivateMessageController.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/PrivateMessageController.java index 14e79a3e..6723c448 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/PrivateMessageController.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/PrivateMessageController.java @@ -8,6 +8,7 @@ import cn.axzo.msg.center.api.request.v3.SearchTodoLogReq; import cn.axzo.msg.center.api.request.v3.SetImSendPriorityRequest; import cn.axzo.msg.center.api.request.v3.UpdateMnsChannelTemplateRequest; import cn.axzo.msg.center.im.service.IMService; +import cn.axzo.msg.center.inside.notices.service.impl.TingyunService; import cn.axzo.msg.center.inside.notices.service.impl.TodoSearchService; import cn.axzo.msg.center.inside.notices.service.impl.v3.MessageRecordServiceV3; import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam; @@ -17,6 +18,7 @@ import cn.axzo.msg.center.message.service.todo.manage.TodoManager; import cn.axzo.msg.center.message.xxl.MigrateOldMsgHotDataJob; import cn.axzo.msg.center.notices.manager.api.MessageTemplateManager; import cn.axzo.msg.center.notices.manager.api.dto.request.plat.CreateTemplateRequestDto; +import cn.axzo.msg.center.notices.manager.api.dto.request.plat.TingyunInterfaceListRequest; import cn.axzo.msg.center.notices.service.api.PlatService; import cn.axzo.trade.web.annotation.EnableResponseAdvice; import com.fasterxml.jackson.databind.ObjectMapper; @@ -33,11 +35,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.LoaderOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.SafeConstructor; -import org.yaml.snakeyaml.nodes.Tag; -import org.yaml.snakeyaml.representer.Representer; import javax.validation.Valid; import java.util.Map; @@ -64,6 +61,7 @@ public class PrivateMessageController { private final MessageTemplateManager messageTemplateManager; private final PlatService platService; private final ConfigurableEnvironment configurableEnvironment; + private final TingyunService tingyunService; @PostMapping("/sendPendingMessage") @EnableResponseAdvice(enable = false) @@ -156,14 +154,29 @@ public class PrivateMessageController { @PostMapping("/createMnsTemplate") @EnableResponseAdvice(enable = false) - public String createMnsTemplate(@RequestBody CreateTemplateRequestDto request){ + public String createMnsTemplate(@RequestBody CreateTemplateRequestDto request) { platService.createTemplate(request); return "created"; } @PostMapping("/listMnsApps") @EnableResponseAdvice(enable = false) - public Object listMnsApps(){ + public Object listMnsApps() { return platService.listAllApps(); } + + @PostMapping("/tingyun/interfaceList") + @EnableResponseAdvice(enable = false) + public Object tingyunInterfaceList(@RequestBody @Valid TingyunInterfaceListRequest request) { + return tingyunService.interfaceList(request); + } + + @PostMapping("/tingyun/abort") + @EnableResponseAdvice(enable = false) + public Object tingyunAbort() { + tingyunService.abort(); + return "ok"; + } + + } \ No newline at end of file diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/TingyunInterfaceListDao.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/TingyunInterfaceListDao.java new file mode 100644 index 00000000..7271f158 --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/TingyunInterfaceListDao.java @@ -0,0 +1,15 @@ +package cn.axzo.msg.center.dal; + +import cn.axzo.msg.center.dal.mapper.TingyunInterfaceListMapper; +import cn.axzo.msg.center.domain.entity.TingyunInterfaceList; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author yanglin + */ +@Slf4j +@Component +public class TingyunInterfaceListDao extends ServiceImpl { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/TingyunInterfaceListMapper.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/TingyunInterfaceListMapper.java new file mode 100644 index 00000000..f2d1217c --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/TingyunInterfaceListMapper.java @@ -0,0 +1,10 @@ +package cn.axzo.msg.center.dal.mapper; + +import cn.axzo.msg.center.domain.entity.TingyunInterfaceList; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @author yanglin + */ +public interface TingyunInterfaceListMapper extends BaseMapper { +} diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/TingyunInterfaceList.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/TingyunInterfaceList.java new file mode 100644 index 00000000..594063e3 --- /dev/null +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/TingyunInterfaceList.java @@ -0,0 +1,43 @@ +package cn.axzo.msg.center.domain.entity; + +import cn.axzo.msg.center.service.enums.YesOrNo; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author yanglin + */ +@Setter +@Getter +@TableName(value = "tingyun_interface_list", autoResultMap = true) +public class TingyunInterfaceList { + private Long id; + private Date date; + private Long applicationId; + private String applicationName; + private String actionName; + private String actionAlias; + private Integer response; + private BigDecimal throught; + private BigDecimal maxThrought; + private BigDecimal error; + private BigDecimal timePercentage; + private Integer errorCount; + private Integer slowCount; + private Integer totalResponse; + private Integer count; + private YesOrNo responseEmpty = YesOrNo.NO; + + public static TingyunInterfaceList emptyResponse(Long applicationId, String action, Date date) { + TingyunInterfaceList list = new TingyunInterfaceList(); + list.setResponseEmpty(YesOrNo.YES); + list.setApplicationId(applicationId); + list.setActionName(action); + list.setDate(date); + return list; + } +} diff --git a/msg-notices/msg-notices-manager-api/src/main/java/cn/axzo/msg/center/notices/manager/api/dto/request/plat/TingyunInterfaceListRequest.java b/msg-notices/msg-notices-manager-api/src/main/java/cn/axzo/msg/center/notices/manager/api/dto/request/plat/TingyunInterfaceListRequest.java new file mode 100644 index 00000000..602fff8e --- /dev/null +++ b/msg-notices/msg-notices-manager-api/src/main/java/cn/axzo/msg/center/notices/manager/api/dto/request/plat/TingyunInterfaceListRequest.java @@ -0,0 +1,55 @@ +package cn.axzo.msg.center.notices.manager.api.dto.request.plat; + +import com.alibaba.fastjson.JSON; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.joda.time.DateTime; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.List; + +/** + * @author yanglin + */ +@Data +public class TingyunInterfaceListRequest { + + @NotBlank + private String auth; + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date startDate; + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date endDate; + private Long bizSystemId = 4449L; + @NotEmpty + private List actions; + + public Date determineStartDate() { + if (startDate != null) + return startDate; + return new DateTime(determineEndDate()).minusDays(60).toDate(); + } + + public Date determineEndDate() { + if (endDate != null) + return endDate; + return new Date(); + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } + + @Data + public static class ActionInfo { + @NotNull + private Long applicationId; + @NotBlank + private String actionName; + } + +} \ No newline at end of file diff --git a/start/src/test/java/cn/axzo/msg/center/inside/notices/service/impl/TingyunServiceTest.java b/start/src/test/java/cn/axzo/msg/center/inside/notices/service/impl/TingyunServiceTest.java new file mode 100644 index 00000000..a80c6480 --- /dev/null +++ b/start/src/test/java/cn/axzo/msg/center/inside/notices/service/impl/TingyunServiceTest.java @@ -0,0 +1,36 @@ +package cn.axzo.msg.center.inside.notices.service.impl; + +import cn.axzo.msg.center.MsgCenterApplication; +import cn.axzo.msg.center.notices.manager.api.dto.request.plat.TingyunInterfaceListRequest; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Collections; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author yanglin + */ +@SpringBootTest(classes = MsgCenterApplication.class) +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class TingyunServiceTest { + + private final TingyunService tingyunService; + + @Test + void foo() { + TingyunInterfaceListRequest request = new TingyunInterfaceListRequest(); + request.setAuth("Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxOGM0M2IzZS0yZTdmLTQzOTMtODBiZS04MjVhZDJlYTlkNmYiLCJpZCI6ImYxYTQxNDdmLWNjNmEtNGNlMC04OGYyLWI4NmViMWU5ZWYzMiIsIm5hbWUiOiJkYmIwNThlMy1jZjhkLTQ0NjQtOTU4My02NjA5ZTBiY2VlMDEiLCJjb2RlIjoiNTNlYTE5ZTItMWI2NS00YTUyLTg5ZmUtN2NmNjAzZWE5NTg5IiwiYWdyZWVtZW50SWQiOiJjNDBlY2UzZS1jZTUzLTQ0NDgtODUzOC02N2NjOWU4OTkzOTMiLCJ0eXBlIjoiMWJmM2M0NWEtMTk3ZC00YzdiLTlhMWItOWEyNzlhOGYyMWM2IiwicmlnaHRSYW5nZSI6IjJlOTQxODQzLWYwZTQtNGIxZC1iNjQ1LTRlNjRhZTRjNWUyMyIsInJhbmRvbSI6ImZiMzczNjE5LTBkYWEtNDY4ZS1iOTM1LWUzYWZiYjMxNGRjMSJ9.OWTE9F0hBn1jJDukLoON3exQZuHVk16bGqo4dDnfQz5xytZiOWvnI9iUIopKjsv9nh4NkQC2h10sSTwFHpFpf31J-aNi112bc69nYvnTI-5NHs8gWywYJ3kSUB8tGobtQC4nWlMKHb1fdiS-0pO-FI8fYkI1c580ULdvP15IUESYW6rueNr-IcmV87XVVNWqrUm7jWP8vmpzI6_10MBUTp2uZD889e1mD_XHBErV_-h93GaNc_2Bluke1LizeNHGx5F1QU0ZGkzQWsst9trlGwvJWLYlJtsKlQPfBftGmkuDfPmp3QJPseWQPXtTcfA9xGvsxIaf3M9Rva7RRfCcFw"); + request.setEndDate(new Date()); + TingyunInterfaceListRequest.ActionInfo action = new TingyunInterfaceListRequest.ActionInfo(); + action.setApplicationId(64254L); + action.setActionName("groupStatisticV2"); + request.setActions(Collections.singletonList(action)); + tingyunService.interfaceList(request); + } + +} \ No newline at end of file