REQ-3057: 备份

This commit is contained in:
yanglin 2024-11-05 18:52:22 +08:00
parent 820259c4cd
commit 7bc09c5c82
27 changed files with 482 additions and 92 deletions

View File

@ -6,9 +6,11 @@ import cn.axzo.im.center.api.vo.req.CustomMessageInfo;
import cn.axzo.im.center.api.vo.req.MessageInfo; import cn.axzo.im.center.api.vo.req.MessageInfo;
import cn.axzo.im.center.api.vo.req.SendMessageParam; import cn.axzo.im.center.api.vo.req.SendMessageParam;
import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam; import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam;
import cn.axzo.im.center.api.vo.req.UpdateMessageRequest;
import cn.axzo.im.center.api.vo.resp.MessageCustomResp; import cn.axzo.im.center.api.vo.resp.MessageCustomResp;
import cn.axzo.im.center.api.vo.resp.MessageDispatchResp; import cn.axzo.im.center.api.vo.resp.MessageDispatchResp;
import cn.axzo.im.center.api.vo.resp.MessageTaskResp; import cn.axzo.im.center.api.vo.resp.MessageTaskResp;
import cn.axzo.im.center.api.vo.resp.MessageUpdateResp;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -54,6 +56,12 @@ public interface MessageApi {
@PostMapping("/api/im/template-message/async/send") @PostMapping("/api/im/template-message/async/send")
ApiResult<MessageTaskResp> sendTemplateMessageAsync(@RequestBody @Validated SendTemplateMessageParam sendMessageParam); ApiResult<MessageTaskResp> sendTemplateMessageAsync(@RequestBody @Validated SendTemplateMessageParam sendMessageParam);
/**
* 更新消息
*/
@PostMapping("/api/im/template-message/updateMessage")
ApiResult<MessageUpdateResp> updateMessage(@RequestBody @Validated UpdateMessageRequest request);
/** /**
* *
* 接口已经作废可以使用sendTemplateMessage来替换 * 接口已经作废可以使用sendTemplateMessage来替换

View File

@ -0,0 +1,46 @@
package cn.axzo.im.center.api.vo;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author yanglin
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
// IMPORTANT: 不要删除这个注解, 避免@Data被@Setter, @Getter取代
@EqualsAndHashCode
public class PersonAccountAttribute {
/**
* 接收消息的personId
*/
@NotBlank(message = "personId不能为空")
private String personId;
/**
* appType = AppTypeEnum.CMP时因为网易云信无法对同一个账号做企业隔离只能一个企业一个账号
* 所以需要根据organizationalUnitId获取账号
*/
private Long ouId;
/**
* 发送消息到App端
* 工人端企业端服务器
* CMCMPSYSTEM
*
* @See cn.axzo.im.center.common.enums.AppTypeEnum
*/
@NotNull(message = "appType不能为空")
private AppTypeEnum appType;
}

View File

@ -1,18 +1,19 @@
package cn.axzo.im.center.api.vo.req; package cn.axzo.im.center.api.vo.req;
import cn.axzo.im.center.common.enums.AppTypeEnum; import cn.axzo.im.center.api.vo.PersonAccountAttribute;
import cn.axzo.im.center.common.enums.TemplatedMsgType;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.NonNull;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
@Data @Data
@Builder @Builder
@ -25,7 +26,7 @@ public class SendTemplateMessageParam {
*/ */
@NotEmpty(message = "消息接收用户信息不能为空") @NotEmpty(message = "消息接收用户信息不能为空")
@Valid @Valid
private List<ReceivePerson> receivePersons; private List<PersonAccountAttribute> receivePersons;
/** /**
* 消息标题 * 消息标题
@ -63,32 +64,16 @@ public class SendTemplateMessageParam {
private Integer sendPriority; private Integer sendPriority;
@Data private TemplatedMsgType templatedMsgType = TemplatedMsgType.TEMPLATE;
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ReceivePerson {
/** private String updatableRefTemplateId;
* 接收消息的personId
*/
@NotBlank(message = "personId不能为空")
private String personId;
/** public boolean isUpdatable() {
* appType = AppTypeEnum.CMP时因为网易云信无法对同一个账号做企业隔离只能一个企业一个账号 return templatedMsgType.isUpdatable();
* 所以需要根据organizationalUnitId获取账号
*/
private Long ouId;
/**
* 发送消息到App端
* 工人端企业端服务器
* CMCMPSYSTEM
*
* @See cn.axzo.im.center.common.enums.AppTypeEnum
*/
@NotNull(message = "appType不能为空")
private AppTypeEnum appType;
} }
public Set<PersonAccountAttribute> uniqueReceivePersons() {
return new HashSet<>(receivePersons);
}
} }

View File

@ -0,0 +1,12 @@
package cn.axzo.im.center.api.vo.req;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter
@Getter
public class UpdateMessageRequest {
}

View File

@ -8,6 +8,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.Date; import java.util.Date;
import java.util.List;
@Data @Data
@Builder @Builder
@ -53,4 +54,6 @@ public class MessageTaskResp {
private Date createAt; private Date createAt;
private Date updateAt; private Date updateAt;
private List<UpdatableMessageSendResult> updatableMessageSendResults;
} }

View File

@ -0,0 +1,12 @@
package cn.axzo.im.center.api.vo.resp;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter
@Getter
public class MessageUpdateResp {
}

View File

@ -0,0 +1,15 @@
package cn.axzo.im.center.api.vo.resp;
import cn.axzo.im.center.api.vo.PersonAccountAttribute;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter
@Getter
public class UpdatableMessageSendResult {
private String bizMessageId;
private PersonAccountAttribute account;
}

View File

@ -1,5 +1,6 @@
package cn.axzo.im.center.common.enums; package cn.axzo.im.center.common.enums;
import cn.axzo.basics.common.constant.enums.CodeDefinition;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -14,7 +15,7 @@ import java.util.List;
* @date 2023/10/9 16:01 * @date 2023/10/9 16:01
*/ */
@Getter @Getter
public enum AppTypeEnum { public enum AppTypeEnum implements CodeDefinition<String> {
/** /**
* 工人端 * 工人端

View File

@ -0,0 +1,22 @@
package cn.axzo.im.center.common.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author yanglin
*/
@Getter
@RequiredArgsConstructor
public enum TemplatedMsgType {
TEMPLATE("template", "模板消息", false),
CARD("card", "卡片消息", true),
;
private final String code;
private final String message;
private final boolean isUpdatable;
}

View File

@ -11,9 +11,12 @@ import cn.axzo.im.center.api.vo.req.CustomMessageInfo;
import cn.axzo.im.center.api.vo.req.MessageInfo; import cn.axzo.im.center.api.vo.req.MessageInfo;
import cn.axzo.im.center.api.vo.req.SendMessageParam; import cn.axzo.im.center.api.vo.req.SendMessageParam;
import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam; import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam;
import cn.axzo.im.center.api.vo.req.UpdateMessageRequest;
import cn.axzo.im.center.api.vo.resp.MessageCustomResp; import cn.axzo.im.center.api.vo.resp.MessageCustomResp;
import cn.axzo.im.center.api.vo.resp.MessageDispatchResp; import cn.axzo.im.center.api.vo.resp.MessageDispatchResp;
import cn.axzo.im.center.api.vo.resp.MessageTaskResp; import cn.axzo.im.center.api.vo.resp.MessageTaskResp;
import cn.axzo.im.center.api.vo.resp.MessageUpdateResp;
import cn.axzo.im.center.api.vo.resp.UpdatableMessageSendResult;
import cn.axzo.im.center.api.vo.resp.UserAccountResp; import cn.axzo.im.center.api.vo.resp.UserAccountResp;
import cn.axzo.im.center.common.enums.AppTypeEnum; import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.entity.MessageTask; import cn.axzo.im.entity.MessageTask;
@ -25,6 +28,7 @@ import cn.axzo.im.service.CustomMessageService;
import cn.axzo.im.service.MessageHistoryService; import cn.axzo.im.service.MessageHistoryService;
import cn.axzo.im.service.MessageTaskService; import cn.axzo.im.service.MessageTaskService;
import cn.axzo.im.service.RobotMsgTemplateService; import cn.axzo.im.service.RobotMsgTemplateService;
import cn.axzo.im.updatable.UpdatableMessageManager;
import cn.axzo.pokonyan.exception.Aassert; import cn.axzo.pokonyan.exception.Aassert;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
@ -38,10 +42,12 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -75,6 +81,8 @@ public class MessageController implements MessageApi {
private MessageHistoryService messageHistoryService; private MessageHistoryService messageHistoryService;
@Autowired @Autowired
private CustomMessageService customMessageService; private CustomMessageService customMessageService;
@Autowired
private UpdatableMessageManager updatableMessageManager;
@Override @Override
@ -149,18 +157,22 @@ public class MessageController implements MessageApi {
} }
@Override @Override
@Transactional
public ApiResult<MessageTaskResp> sendTemplateMessageAsync(SendTemplateMessageParam sendMessageParam) { public ApiResult<MessageTaskResp> sendTemplateMessageAsync(SendTemplateMessageParam sendMessageParam) {
String sendImAccount = check(sendMessageParam); String sendImAccount = check(sendMessageParam);
MessageTask.BizData bizData = MessageTask.BizData.builder() MessageTask.BizData bizData = MessageTask.BizData.builder()
.msgTemplateContent(sendMessageParam.getMsgTemplateContent()) .msgTemplateContent(sendMessageParam.getMsgTemplateContent())
.msgTemplateId(sendMessageParam.getMsgTemplateId()) .msgTemplateId(sendMessageParam.getMsgTemplateId())
.templatedMsgType(sendMessageParam.getTemplatedMsgType())
.build(); .build();
Date now = new Date(); Date now = new Date();
List<MessageTask.ReceivePerson> receivePersons = JSONArray.parseArray(
JSONObject.toJSONString(sendMessageParam.uniqueReceivePersons()), MessageTask.ReceivePerson.class);
MessageTask messageTask = messageTaskService.create(MessageTask.builder() MessageTask messageTask = messageTaskService.create(MessageTask.builder()
.bizId(sendMessageParam.getBizId()) .bizId(sendMessageParam.getBizId())
.sendImAccount(sendImAccount) .sendImAccount(sendImAccount)
.receivePersons(JSONArray.parseArray(JSONObject.toJSONString(sendMessageParam.getReceivePersons()), MessageTask.ReceivePerson.class)) .receivePersons(receivePersons)
.status(MessageTaskStatus.PENDING) .status(MessageTaskStatus.PENDING)
.title(sendMessageParam.getMsgHeader()) .title(sendMessageParam.getMsgHeader())
.content(sendMessageParam.getMsgContent()) .content(sendMessageParam.getMsgContent())
@ -172,7 +184,19 @@ public class MessageController implements MessageApi {
.determinePriority(sendMessageParam.getSendPriority())) .determinePriority(sendMessageParam.getSendPriority()))
.apiChannel(ApiChannel.COMMON_MESSAGE) .apiChannel(ApiChannel.COMMON_MESSAGE)
.build()); .build());
return ApiResult.ok(toMessageTaskResp(messageTask)); List<UpdatableMessageSendResult> updatableMessageSendResults = Collections.emptyList();
if (sendMessageParam.isUpdatable()) {
updatableMessageSendResults = updatableMessageManager.createUpdatableMessage(messageTask, sendMessageParam, receivePersons);
}
MessageTaskResp messageTaskResp = toMessageTaskResp(messageTask);
messageTaskResp.setUpdatableMessageSendResults(updatableMessageSendResults);
return ApiResult.ok(messageTaskResp);
}
@Override
public ApiResult<MessageUpdateResp> updateMessage(UpdateMessageRequest request) {
MessageUpdateResp resp = updatableMessageManager.updateMessage(request);
return ApiResult.ok(resp);
} }
private void check(SendMessageParam sendMessageParam) { private void check(SendMessageParam sendMessageParam) {

View File

@ -1,11 +0,0 @@
package cn.axzo.im.dao.mapper;
import cn.axzo.im.entity.BizData;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
/**
* @author yanglin
*/
public interface BizDataMapper extends BaseMapper<BizData> {
}

View File

@ -1,10 +0,0 @@
package cn.axzo.im.dao.mapper;
import cn.axzo.im.entity.BizLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author yanglin
*/
public interface BizLogMapper extends BaseMapper<BizLog> {
}

View File

@ -0,0 +1,10 @@
package cn.axzo.im.dao.mapper;
import cn.axzo.im.entity.UpdatableMessageLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author yanglin
*/
public interface UpdatableMessageLogMapper extends BaseMapper<UpdatableMessageLog> {
}

View File

@ -0,0 +1,10 @@
package cn.axzo.im.dao.mapper;
import cn.axzo.im.entity.UpdatableMessage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author yanglin
*/
public interface UpdatableMessageMapper extends BaseMapper<UpdatableMessage> {
}

View File

@ -1,13 +0,0 @@
package cn.axzo.im.dao.repository;
import cn.axzo.im.dao.mapper.BizDataMapper;
import cn.axzo.im.entity.BizData;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Repository;
/**
* @author yanglin
*/
@Repository("bizDataDao")
public class BizDataDao extends ServiceImpl<BizDataMapper, BizData> {
}

View File

@ -1,13 +0,0 @@
package cn.axzo.im.dao.repository;
import cn.axzo.im.dao.mapper.BizLogMapper;
import cn.axzo.im.entity.BizLog;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Repository;
/**
* @author yanglin
*/
@Repository("bizLogDao")
public class BizLogDao extends ServiceImpl<BizLogMapper, BizLog> {
}

View File

@ -0,0 +1,26 @@
package cn.axzo.im.dao.repository;
import cn.axzo.im.dao.mapper.UpdatableMessageMapper;
import cn.axzo.im.entity.UpdatableMessage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Repository;
import java.util.Collections;
import java.util.List;
/**
* @author yanglin
*/
@Repository("updatableMessageDao")
public class UpdatableMessageDao extends ServiceImpl<UpdatableMessageMapper, UpdatableMessage> {
public List<UpdatableMessage> getByTaskIds(List<Long> taskIds) {
if (CollectionUtils.isEmpty(taskIds))
return Collections.emptyList();
return lambdaQuery()
.in(UpdatableMessage::getTaskId, taskIds)
.list();
}
}

View File

@ -0,0 +1,13 @@
package cn.axzo.im.dao.repository;
import cn.axzo.im.dao.mapper.UpdatableMessageLogMapper;
import cn.axzo.im.entity.UpdatableMessageLog;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Repository;
/**
* @author yanglin
*/
@Repository("updatableMessageLogDao")
public class UpdatableMessageLogDao extends ServiceImpl<UpdatableMessageLogMapper, UpdatableMessageLog> {
}

View File

@ -1,10 +1,11 @@
package cn.axzo.im.entity; package cn.axzo.im.entity;
import cn.axzo.im.center.api.vo.ApiChannel;
import cn.axzo.im.center.api.vo.req.SendMessageParam; import cn.axzo.im.center.api.vo.req.SendMessageParam;
import cn.axzo.im.center.common.enums.AppTypeEnum; import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.center.common.enums.BizTypeEnum; import cn.axzo.im.center.common.enums.BizTypeEnum;
import cn.axzo.im.center.common.enums.TemplatedMsgType;
import cn.axzo.im.config.BaseListTypeHandler; import cn.axzo.im.config.BaseListTypeHandler;
import cn.axzo.im.center.api.vo.ApiChannel;
import cn.axzo.im.enums.MessageTaskStatus; import cn.axzo.im.enums.MessageTaskStatus;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
@ -17,6 +18,7 @@ import com.google.common.collect.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -115,6 +117,9 @@ public class MessageTask {
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public static class BizData { public static class BizData {
private TemplatedMsgType templatedMsgType = TemplatedMsgType.TEMPLATE;
private String msgTemplateId; private String msgTemplateId;
/** /**
@ -151,12 +156,17 @@ public class MessageTask {
* @See cn.axzo.im.center.common.enums.AppTypeEnum * @See cn.axzo.im.center.common.enums.AppTypeEnum
*/ */
private List<AppTypeEnum> appTypes; private List<AppTypeEnum> appTypes;
public TemplatedMsgType determineTemplatedMsgType() {
return templatedMsgType == null ? TemplatedMsgType.TEMPLATE : templatedMsgType;
}
} }
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@EqualsAndHashCode
public static class ReceivePerson { public static class ReceivePerson {
/** /**

View File

@ -1,7 +1,8 @@
package cn.axzo.im.entity; package cn.axzo.im.entity;
import cn.axzo.im.center.api.vo.PersonAccountAttribute;
import cn.axzo.im.center.common.enums.AppTypeEnum; import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.utils.YesNo; import cn.axzo.im.enums.UpdatableMessageState;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter; import lombok.Getter;
@ -14,16 +15,19 @@ import java.util.Date;
*/ */
@Setter @Setter
@Getter @Getter
@TableName(value = "im_biz_data", autoResultMap = true) @TableName(value = "im_updatable_message", autoResultMap = true)
public class BizData { public class UpdatableMessage {
private Long id; private Long id;
private String batchNo;
private String templateId;
private String refTemplateId;
private String bizId; private String bizId;
private Long taskId; private Long taskId;
private Long receiverPersonId; private String receiverPersonId;
private Long receiverOuId; private Long receiverOuId;
private AppTypeEnum appType; private AppTypeEnum appType;
private YesNo valid; private UpdatableMessageState state;
private String bizMessageId; private String bizMessageId;
private Long initHistoryId; private Long initHistoryId;
private Long updateHistoryId; private Long updateHistoryId;
@ -39,6 +43,14 @@ public class BizData {
private Date createAt; private Date createAt;
private Date updateAt; private Date updateAt;
public PersonAccountAttribute parsePersonAccount() {
PersonAccountAttribute person = new PersonAccountAttribute();
person.setPersonId(receiverPersonId);
person.setOuId(receiverOuId);
person.setAppType(appType);
return person;
}
@Getter @Getter
@Setter @Setter
public static class RecordExt { public static class RecordExt {

View File

@ -1,5 +1,7 @@
package cn.axzo.im.entity; package cn.axzo.im.entity;
import cn.axzo.im.enums.UpdatableMessageLogLogType;
import cn.axzo.im.enums.UpdatableMessageState;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter; import lombok.Getter;
@ -12,11 +14,13 @@ import java.util.Date;
*/ */
@Setter @Setter
@Getter @Getter
@TableName(value = "im_biz_log", autoResultMap = true) @TableName(value = "im_updatable_message_log", autoResultMap = true)
public class BizLog { public class UpdatableMessageLog {
private Long id; private Long id;
private UpdatableMessageLogLogType type;
private String bizId; private String bizId;
private String bizMessageId; private String bizMessageId;
private UpdatableMessageState messageState;
private Long initHistoryId; private Long initHistoryId;
private Long updateHistoryId; private Long updateHistoryId;
private JSONObject messageBody; private JSONObject messageBody;

View File

@ -0,0 +1,11 @@
package cn.axzo.im.enums;
/**
* @author yanglin
*/
public enum UpdatableMessageLogLogType {
CREATE,
UPDATE
}

View File

@ -0,0 +1,10 @@
package cn.axzo.im.enums;
/**
* @author yanglin
*/
public enum UpdatableMessageState {
CREATED,
INVALID,
VALID
}

View File

@ -34,7 +34,8 @@ public class CreateMessageHistoryJob extends IJobHandler {
@Autowired @Autowired
private MessageTaskService messageTaskService; private MessageTaskService messageTaskService;
private static final Integer DEFAULT_PAGE_SIZE = 500; // 有数据量放大的可能, 设置小一些
private static final Integer DEFAULT_PAGE_SIZE = 100;
@Override @Override
@XxlJob("createMessageHistoryJob") @XxlJob("createMessageHistoryJob")

View File

@ -4,11 +4,9 @@ import cn.axzo.im.center.api.vo.req.SendMessageParam;
import cn.axzo.im.center.common.enums.AccountTypeEnum; import cn.axzo.im.center.common.enums.AccountTypeEnum;
import cn.axzo.im.center.common.enums.AppTypeEnum; import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.channel.IMChannelProvider; import cn.axzo.im.channel.IMChannelProvider;
import cn.axzo.im.channel.netease.NimMsgTypeEnum;
import cn.axzo.im.channel.netease.dto.MessageBody; import cn.axzo.im.channel.netease.dto.MessageBody;
import cn.axzo.im.dao.mapper.MessageTaskMapper; import cn.axzo.im.dao.mapper.MessageTaskMapper;
import cn.axzo.im.entity.AccountRegister; import cn.axzo.im.entity.AccountRegister;
import cn.axzo.im.entity.HistoryRecordExt;
import cn.axzo.im.entity.MessageHistory; import cn.axzo.im.entity.MessageHistory;
import cn.axzo.im.entity.MessageTask; import cn.axzo.im.entity.MessageTask;
import cn.axzo.im.enums.MessageHistoryStatus; import cn.axzo.im.enums.MessageHistoryStatus;
@ -17,6 +15,7 @@ import cn.axzo.im.service.AccountRegisterService.AccountRegisterDTO;
import cn.axzo.im.service.AccountService; import cn.axzo.im.service.AccountService;
import cn.axzo.im.service.MessageHistoryService; import cn.axzo.im.service.MessageHistoryService;
import cn.axzo.im.service.MessageTaskService; import cn.axzo.im.service.MessageTaskService;
import cn.axzo.im.updatable.UpdatableMessageManager;
import cn.axzo.im.utils.UUIDUtil; import cn.axzo.im.utils.UUIDUtil;
import cn.axzo.maokai.api.client.OrganizationalTeamOuRelationApi; import cn.axzo.maokai.api.client.OrganizationalTeamOuRelationApi;
import cn.axzo.maokai.api.vo.request.OrganizationalTeamOuRelationReq; import cn.axzo.maokai.api.vo.request.OrganizationalTeamOuRelationReq;
@ -64,6 +63,8 @@ public class MessageTaskServiceImpl extends ServiceImpl<MessageTaskMapper, Messa
private MessageHistoryService messageHistoryService; private MessageHistoryService messageHistoryService;
@Autowired @Autowired
private OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi; private OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi;
@Autowired
private UpdatableMessageManager updatableMessageManager;
private static final Integer DEFAULT_PAGE_SIZE = 500; private static final Integer DEFAULT_PAGE_SIZE = 500;
@ -88,6 +89,7 @@ public class MessageTaskServiceImpl extends ServiceImpl<MessageTaskMapper, Messa
} }
@Override @Override
@Transactional
public void createMessageHistory(MessageTask messageTask) { public void createMessageHistory(MessageTask messageTask) {
this.update(UpdateMessageTaskParam.builder() this.update(UpdateMessageTaskParam.builder()
@ -190,6 +192,7 @@ public class MessageTaskServiceImpl extends ServiceImpl<MessageTaskMapper, Messa
.map(receivePerson -> resolveMessageHistory(batchNo, messageTask, receivePerson, imAccounts, accountRegisters, ouIdMap)) .map(receivePerson -> resolveMessageHistory(batchNo, messageTask, receivePerson, imAccounts, accountRegisters, ouIdMap))
.collect(Collectors.toList()); .collect(Collectors.toList());
messageHistoryService.createBatch(messageHistories); messageHistoryService.createBatch(messageHistories);
updatableMessageManager.onHistoryCreated(messageHistories);
} }
private MessageHistory resolveMessageHistory(String batchNo, private MessageHistory resolveMessageHistory(String batchNo,
@ -325,14 +328,14 @@ public class MessageTaskServiceImpl extends ServiceImpl<MessageTaskMapper, Messa
} }
private String resolveBody(MessageTask.ReceivePerson receivePerson, MessageTask messageTask, String appType) { private String resolveBody(MessageTask.ReceivePerson receivePerson, MessageTask messageTask, String appType) {
MessageTask.BizData bizData = messageTask.getBizData();
MessageBody messageBody = new MessageBody(); MessageBody messageBody = new MessageBody();
messageBody.setMsgType(NimMsgTypeEnum.TEMPLATE.getCode()); messageBody.setMsgType(bizData.determineTemplatedMsgType().getCode());
messageBody.setMsgContent(messageTask.getContent()); messageBody.setMsgContent(messageTask.getContent());
messageBody.setMsgHeader(messageTask.getTitle()); messageBody.setMsgHeader(messageTask.getTitle());
Map<String, String> defaultExtMap = Maps.newHashMap(); Map<String, String> defaultExtMap = Maps.newHashMap();
MessageTask.BizData bizData = messageTask.getBizData();
if (StringUtils.isNotBlank(bizData.getMsgTemplateContent())) { if (StringUtils.isNotBlank(bizData.getMsgTemplateContent())) {
messageBody.setMsgBody(bizData.getMsgTemplateContent()); messageBody.setMsgBody(bizData.getMsgTemplateContent());
defaultExtMap.put("msgTemplateId", bizData.getMsgTemplateId()); defaultExtMap.put("msgTemplateId", bizData.getMsgTemplateId());

View File

@ -0,0 +1,60 @@
package cn.axzo.im.updatable;
import cn.axzo.basics.common.constant.enums.CodeDefinition;
import cn.axzo.im.center.api.vo.PersonAccountAttribute;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.entity.MessageHistory;
import cn.axzo.im.entity.UpdatableMessage;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
/**
* @author yanglin
*/
class InitHistories {
private final Map<HistoryTaskAccount, MessageHistory> account2histories;
InitHistories(List<MessageHistory> histories) {
this.account2histories = histories.stream()
.filter(history -> {
AppTypeEnum appType = CodeDefinition.findByCode(
AppTypeEnum.class, history.getAppType()).orElse(null);
return appType != null;
})
.collect(toMap(history -> {
PersonAccountAttribute person = new PersonAccountAttribute();
person.setPersonId(history.getReceivePersonId());
person.setOuId(history.getReceiveOuId());
person.setAppType(CodeDefinition.findByCode(
AppTypeEnum.class, history.getAppType()).orElse(null));
return new HistoryTaskAccount(history.getImMessageTaskId(), person);
}, identity(), (oldValue, newValue) -> oldValue));
}
public Optional<MessageHistory> findHistory(UpdatableMessage message) {
HistoryTaskAccount account = new HistoryTaskAccount(
message.getTaskId(), message.parsePersonAccount());
return Optional.ofNullable(account2histories.get(account));
}
@Setter
@Getter
@EqualsAndHashCode
// IMPORTANT: 不要删除这个注解
@RequiredArgsConstructor
private static class HistoryTaskAccount {
final Long taskId;
final PersonAccountAttribute person;
}
}

View File

@ -0,0 +1,139 @@
package cn.axzo.im.updatable;
import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam;
import cn.axzo.im.center.api.vo.req.UpdateMessageRequest;
import cn.axzo.im.center.api.vo.resp.MessageUpdateResp;
import cn.axzo.im.center.api.vo.resp.UpdatableMessageSendResult;
import cn.axzo.im.dao.repository.UpdatableMessageDao;
import cn.axzo.im.dao.repository.UpdatableMessageLogDao;
import cn.axzo.im.entity.MessageHistory;
import cn.axzo.im.entity.MessageTask;
import cn.axzo.im.entity.MessageTask.ReceivePerson;
import cn.axzo.im.entity.UpdatableMessage;
import cn.axzo.im.entity.UpdatableMessageLog;
import cn.axzo.im.enums.MessageHistoryStatus;
import cn.axzo.im.enums.UpdatableMessageLogLogType;
import cn.axzo.im.enums.UpdatableMessageState;
import cn.axzo.im.utils.UUIDUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* @author yanglin
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class UpdatableMessageManager {
private static final int BATCH_UPDATE_SIZE = 1000;
private final UpdatableMessageDao updatableMessageDao;
private final UpdatableMessageLogDao updatableMessageLogDao;
@Transactional
public List<UpdatableMessageSendResult> createUpdatableMessage(
MessageTask task, SendTemplateMessageParam request, List<ReceivePerson> receivePersons) {
if (CollectionUtils.isEmpty(receivePersons)) return Collections.emptyList();
String batchNo = UUIDUtil.uuidString();
ArrayList<UpdatableMessageSendResult> sendResults = new ArrayList<>();
ArrayList<UpdatableMessage> messages = new ArrayList<>();
for (ReceivePerson person : receivePersons) {
UpdatableMessage message = new UpdatableMessage();
messages.add(message);
message.setBatchNo(batchNo);
message.setTemplateId(request.getMsgTemplateId());
message.setRefTemplateId(request.getUpdatableRefTemplateId());
message.setBizId(request.getBizId());
message.setTaskId(task.getId());
message.setReceiverPersonId(person.getPersonId());
message.setReceiverOuId(person.getOuId());
message.setAppType(person.getAppType());
message.setState(UpdatableMessageState.CREATED);
message.setBizMessageId(message.getBizMessageId());
message.setDataVersion(1L);
UpdatableMessageSendResult sendResult = new UpdatableMessageSendResult();
sendResults.add(sendResult);
sendResult.setBizMessageId(message.getBizMessageId());
sendResult.setAccount(message.parsePersonAccount());
}
for (List<UpdatableMessage> batch : Lists.partition(messages, BATCH_UPDATE_SIZE))
updatableMessageDao.saveBatch(batch);
ArrayList<UpdatableMessageLog> logs = new ArrayList<>();
for (UpdatableMessage message : messages) {
UpdatableMessageLog log = new UpdatableMessageLog();
logs.add(log);
log.setType(UpdatableMessageLogLogType.CREATE);
log.setMessageState(UpdatableMessageState.CREATED);
log.setBizId(message.getBizId());
log.setBizMessageId(message.getBizMessageId());
log.setDataVersion(message.getDataVersion());
}
for (List<UpdatableMessageLog> batch : Lists.partition(logs, BATCH_UPDATE_SIZE))
updatableMessageLogDao.saveBatch(batch);
return sendResults;
}
@Transactional
public void onHistoryCreated(List<MessageHistory> histories) {
if (CollectionUtils.isEmpty(histories)) return;
List<Long> taskIds = histories.stream()
.map(MessageHistory::getImMessageTaskId)
.distinct()
.collect(toList());
List<UpdatableMessage> messages = updatableMessageDao.getByTaskIds(taskIds);
log.info("onHistoryCreated, taskIdSize={}, messageSize={}", taskIds.size(), messages.size());
InitHistories initHistories = new InitHistories(histories);
ArrayList<UpdatableMessage> messageUpdates = new ArrayList<>();
ArrayList<UpdatableMessageLog> messageLogUpdates = new ArrayList<>();
for (UpdatableMessage message : messages) {
MessageHistory history = initHistories.findHistory(message).orElse(null);
if (history == null) continue;
String msgBodyJson = message.getMessageBody().getString("msgBody");
JSONObject bizBody = JSON.parseObject(msgBodyJson);
UpdatableMessage messageUpdate = new UpdatableMessage();
messageUpdates.add(messageUpdate);
messageUpdate.setId(message.getId());
messageUpdate.setInitHistoryId(history.getImMessageTaskId());
messageUpdate.setMessageBody(message.getMessageBody());
messageUpdate.setBizBody(bizBody);
messageUpdate.setState(history.getStatus() == MessageHistoryStatus.FAILED
? UpdatableMessageState.INVALID
: UpdatableMessageState.VALID);
UpdatableMessageLog messageLogUpdate = new UpdatableMessageLog();
messageLogUpdates.add(messageLogUpdate);
messageLogUpdate.setMessageBody(message.getMessageBody());
messageLogUpdate.setBizBody(bizBody);
messageLogUpdate.setInitHistoryId(history.getImMessageTaskId());
messageLogUpdate.setMessageState(messageUpdate.getState());
}
if (CollectionUtils.isNotEmpty(messageUpdates)) {
for (List<UpdatableMessage> batch : Lists.partition(messageUpdates, BATCH_UPDATE_SIZE))
updatableMessageDao.updateBatchById(batch);
}
if (CollectionUtils.isNotEmpty(messageLogUpdates)) {
for (List<UpdatableMessageLog> batch : Lists.partition(messageLogUpdates, BATCH_UPDATE_SIZE))
updatableMessageLogDao.updateBatchById(batch);
}
}
public MessageUpdateResp updateMessage(UpdateMessageRequest request) {
return null;
}
}