|
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
+import com.fs.common.core.redis.RedisCache;
|
|
|
import com.fs.common.exception.CustomException;
|
|
import com.fs.common.exception.CustomException;
|
|
|
import com.fs.common.utils.StringUtils;
|
|
import com.fs.common.utils.StringUtils;
|
|
|
import com.fs.company.domain.*;
|
|
import com.fs.company.domain.*;
|
|
@@ -29,6 +30,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.LocalTime;
|
|
import java.time.LocalTime;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* @author MixLiu
|
|
* @author MixLiu
|
|
@@ -78,6 +80,9 @@ public class CompanyWorkflowEngineImpl implements CompanyWorkflowEngine {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private CloudHostProper cloudHostProper;
|
|
private CloudHostProper cloudHostProper;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private RedisCache redisCache;
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 初始化工作流
|
|
* 初始化工作流
|
|
|
* 创建工作流实例并保存初始状态
|
|
* 创建工作流实例并保存初始状态
|
|
@@ -102,8 +107,6 @@ public class CompanyWorkflowEngineImpl implements CompanyWorkflowEngine {
|
|
|
definition.getStartNodeKey(), context, definition);
|
|
definition.getStartNodeKey(), context, definition);
|
|
|
|
|
|
|
|
log.info("工作流初始化成功: {} -> {}", workflowInstanceId, workflowDefinitionId);
|
|
log.info("工作流初始化成功: {} -> {}", workflowInstanceId, workflowDefinitionId);
|
|
|
- //为任务创建sip任务并存入表数据
|
|
|
|
|
- createSipTask(Long.parseLong(inputVariables.get("roboticId").toString()),workflowDefinitionId);
|
|
|
|
|
return ExecutionResult.success()
|
|
return ExecutionResult.success()
|
|
|
.nextNodeKey(definition.getStartNodeKey())
|
|
.nextNodeKey(definition.getStartNodeKey())
|
|
|
.workflowInstanceId(workflowInstanceId).build();
|
|
.workflowInstanceId(workflowInstanceId).build();
|
|
@@ -570,37 +573,59 @@ public class CompanyWorkflowEngineImpl implements CompanyWorkflowEngine {
|
|
|
* @param workFlowId
|
|
* @param workFlowId
|
|
|
*/
|
|
*/
|
|
|
public Long createSipTask(Long roboticId, Long workFlowId) {
|
|
public Long createSipTask(Long roboticId, Long workFlowId) {
|
|
|
- try {
|
|
|
|
|
- List<String> nodeTypes = Arrays.asList(NodeTypeEnum.AI_CALL_TASK.getCode());
|
|
|
|
|
- CompanyVoiceRobotic robotic = companyVoiceRoboticMapper.selectCompanyVoiceRoboticById(roboticId);
|
|
|
|
|
- List<CompanyWorkflowNode> companyWorkflowNodes = companyWorkflowNodeMapper.selectNodesByWorkflowIdAndTypes(workFlowId, nodeTypes);
|
|
|
|
|
- //为所有外呼节点创建任务的对应sip外呼任务
|
|
|
|
|
- for (CompanyWorkflowNode callNode : companyWorkflowNodes) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ List<String> nodeTypes = Arrays.asList(NodeTypeEnum.AI_CALL_TASK.getCode());
|
|
|
|
|
+ CompanyVoiceRobotic robotic = companyVoiceRoboticMapper.selectCompanyVoiceRoboticById(roboticId);
|
|
|
|
|
+ List<CompanyWorkflowNode> companyWorkflowNodes = companyWorkflowNodeMapper.selectNodesByWorkflowIdAndTypes(workFlowId, nodeTypes);
|
|
|
|
|
+ for (CompanyWorkflowNode callNode : companyWorkflowNodes) {
|
|
|
|
|
+ String lockKey = "sipTask:lock:" + roboticId + ":" + callNode.getNodeKey();
|
|
|
|
|
+ boolean locked = redisCache.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
|
|
|
|
|
+ if (!locked) {
|
|
|
|
|
+ log.info("createSipTask: 其他线程正在创建SIP任务,等待后重试 - roboticId: {}, nodeKey: {}", roboticId, callNode.getNodeKey());
|
|
|
|
|
+ for (int i = 0; i < 20; i++) {
|
|
|
|
|
+ try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
|
|
|
|
|
+ CompanySiptaskInfo existing = companySiptaskInfoMapper.selectSipTaskInfoByTaskIdAndNodeKey(roboticId, callNode.getNodeKey());
|
|
|
|
|
+ if (existing != null && existing.getBatchId() != null) {
|
|
|
|
|
+ return existing.getBatchId();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ log.warn("createSipTask: 等待超时,尝试直接创建 - roboticId: {}, nodeKey: {}", roboticId, callNode.getNodeKey());
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ CompanySiptaskInfo existingSipTask = companySiptaskInfoMapper.selectSipTaskInfoByTaskIdAndNodeKey(roboticId, callNode.getNodeKey());
|
|
|
|
|
+ if (existingSipTask != null && existingSipTask.getBatchId() != null) {
|
|
|
|
|
+ log.info("createSipTask: SIP任务已存在,跳过创建 - roboticId: {}, nodeKey: {}, batchId: {}", roboticId, callNode.getNodeKey(), existingSipTask.getBatchId());
|
|
|
|
|
+ return existingSipTask.getBatchId();
|
|
|
|
|
+ }
|
|
|
String nodeConfig = callNode.getNodeConfig();
|
|
String nodeConfig = callNode.getNodeConfig();
|
|
|
AiCallConfigVO callConfigVo = JSONObject.parseObject(nodeConfig, AiCallConfigVO.class);
|
|
AiCallConfigVO callConfigVo = JSONObject.parseObject(nodeConfig, AiCallConfigVO.class);
|
|
|
EasyCallCreateTaskParam createParam = new EasyCallCreateTaskParam();
|
|
EasyCallCreateTaskParam createParam = new EasyCallCreateTaskParam();
|
|
|
- // 任务名称:使用任务名称_工作流id_节点key
|
|
|
|
|
createParam.setBatchName(cloudHostProper.getCompanyName()+"-"+robotic.getName() + "_" + workFlowId + "_" + callNode.getNodeKey());
|
|
createParam.setBatchName(cloudHostProper.getCompanyName()+"-"+robotic.getName() + "_" + workFlowId + "_" + callNode.getNodeKey());
|
|
|
if (null != callConfigVo.getMaxConcurrency()) {
|
|
if (null != callConfigVo.getMaxConcurrency()) {
|
|
|
createParam.setThreadNum(Long.valueOf(callConfigVo.getMaxConcurrency()));
|
|
createParam.setThreadNum(Long.valueOf(callConfigVo.getMaxConcurrency()));
|
|
|
} else {
|
|
} else {
|
|
|
createParam.setThreadNum(3L);
|
|
createParam.setThreadNum(3L);
|
|
|
}
|
|
}
|
|
|
- // AI 外呼模式
|
|
|
|
|
createParam.setTaskType(1);
|
|
createParam.setTaskType(1);
|
|
|
- // 外呼线路(网关)
|
|
|
|
|
createParam.setGatewayId(callConfigVo.getGatewayId());
|
|
createParam.setGatewayId(callConfigVo.getGatewayId());
|
|
|
- // 大模型底座
|
|
|
|
|
createParam.setLlmAccountId(callConfigVo.getLlmAccountId());
|
|
createParam.setLlmAccountId(callConfigVo.getLlmAccountId());
|
|
|
- // 音色编号
|
|
|
|
|
createParam.setVoiceCode(callConfigVo.getVoiceCode());
|
|
createParam.setVoiceCode(callConfigVo.getVoiceCode());
|
|
|
- // 音色来源(如未配置默认留空,由 EasyCallCenter365 使用默认值)
|
|
|
|
|
createParam.setVoiceSource(callConfigVo.getVoiceSource());
|
|
createParam.setVoiceSource(callConfigVo.getVoiceSource());
|
|
|
- // 技能组(转人工客服分组,可选)
|
|
|
|
|
createParam.setGroupId(callConfigVo.getBusiGroupId());
|
|
createParam.setGroupId(callConfigVo.getBusiGroupId());
|
|
|
- // 模型参数
|
|
|
|
|
createParam.setTtsModels(callConfigVo.getTtsModels());
|
|
createParam.setTtsModels(callConfigVo.getTtsModels());
|
|
|
|
|
|
|
|
|
|
+ if (callConfigVo.getExtensionList() != null && !callConfigVo.getExtensionList().isEmpty()) {
|
|
|
|
|
+ createParam.setAiTransferType("extension");
|
|
|
|
|
+ StringBuilder aiTransferExtNumber = new StringBuilder();
|
|
|
|
|
+ callConfigVo.getExtensionList().forEach(extension -> {
|
|
|
|
|
+ aiTransferExtNumber.append(extension.getExtensionNum()).append(" ");
|
|
|
|
|
+ });
|
|
|
|
|
+ if (null != aiTransferExtNumber && aiTransferExtNumber.length() > 0) {
|
|
|
|
|
+ aiTransferExtNumber.deleteCharAt(aiTransferExtNumber.length() - 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ createParam.setAiTransferExtNumber(aiTransferExtNumber.toString());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
EasyCallTaskVO task = easyCallService.createTask(createParam, null);
|
|
EasyCallTaskVO task = easyCallService.createTask(createParam, null);
|
|
|
if (task == null || task.getBatchId() == null) {
|
|
if (task == null || task.getBatchId() == null) {
|
|
|
log.error("createSipTask: 创建 EasyCall 任务失败 - workflowInstanceId: {}", workFlowId);
|
|
log.error("createSipTask: 创建 EasyCall 任务失败 - workflowInstanceId: {}", workFlowId);
|
|
@@ -614,11 +639,64 @@ public class CompanyWorkflowEngineImpl implements CompanyWorkflowEngine {
|
|
|
sipTaskInfo.setTaskJson(JSONObject.toJSONString(task));
|
|
sipTaskInfo.setTaskJson(JSONObject.toJSONString(task));
|
|
|
companySiptaskInfoMapper.insertCompanySiptaskInfo(sipTaskInfo);
|
|
companySiptaskInfoMapper.insertCompanySiptaskInfo(sipTaskInfo);
|
|
|
return task.getBatchId();
|
|
return task.getBatchId();
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ log.error("创建SIP任务失败:{}", ex);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ redisCache.deleteObject(lockKey);
|
|
|
}
|
|
}
|
|
|
- } catch (Exception ex) {
|
|
|
|
|
- log.error("创建SIP任务失败:{}", ex);
|
|
|
|
|
}
|
|
}
|
|
|
return null;
|
|
return null;
|
|
|
|
|
+
|
|
|
|
|
+// try {
|
|
|
|
|
+// List<String> nodeTypes = Arrays.asList(NodeTypeEnum.AI_CALL_TASK.getCode());
|
|
|
|
|
+// CompanyVoiceRobotic robotic = companyVoiceRoboticMapper.selectCompanyVoiceRoboticById(roboticId);
|
|
|
|
|
+// List<CompanyWorkflowNode> companyWorkflowNodes = companyWorkflowNodeMapper.selectNodesByWorkflowIdAndTypes(workFlowId, nodeTypes);
|
|
|
|
|
+// //为所有外呼节点创建任务的对应sip外呼任务
|
|
|
|
|
+// for (CompanyWorkflowNode callNode : companyWorkflowNodes) {
|
|
|
|
|
+// String nodeConfig = callNode.getNodeConfig();
|
|
|
|
|
+// AiCallConfigVO callConfigVo = JSONObject.parseObject(nodeConfig, AiCallConfigVO.class);
|
|
|
|
|
+// EasyCallCreateTaskParam createParam = new EasyCallCreateTaskParam();
|
|
|
|
|
+// // 任务名称:使用任务名称_工作流id_节点key
|
|
|
|
|
+// createParam.setBatchName(cloudHostProper.getCompanyName()+"-"+robotic.getName() + "_" + workFlowId + "_" + callNode.getNodeKey());
|
|
|
|
|
+// if (null != callConfigVo.getMaxConcurrency()) {
|
|
|
|
|
+// createParam.setThreadNum(Long.valueOf(callConfigVo.getMaxConcurrency()));
|
|
|
|
|
+// } else {
|
|
|
|
|
+// createParam.setThreadNum(3L);
|
|
|
|
|
+// }
|
|
|
|
|
+// // AI 外呼模式
|
|
|
|
|
+// createParam.setTaskType(1);
|
|
|
|
|
+// // 外呼线路(网关)
|
|
|
|
|
+// createParam.setGatewayId(callConfigVo.getGatewayId());
|
|
|
|
|
+// // 大模型底座
|
|
|
|
|
+// createParam.setLlmAccountId(callConfigVo.getLlmAccountId());
|
|
|
|
|
+// // 音色编号
|
|
|
|
|
+// createParam.setVoiceCode(callConfigVo.getVoiceCode());
|
|
|
|
|
+// // 音色来源(如未配置默认留空,由 EasyCallCenter365 使用默认值)
|
|
|
|
|
+// createParam.setVoiceSource(callConfigVo.getVoiceSource());
|
|
|
|
|
+// // 技能组(转人工客服分组,可选)
|
|
|
|
|
+// createParam.setGroupId(callConfigVo.getBusiGroupId());
|
|
|
|
|
+// // 模型参数
|
|
|
|
|
+// createParam.setTtsModels(callConfigVo.getTtsModels());
|
|
|
|
|
+//
|
|
|
|
|
+// EasyCallTaskVO task = easyCallService.createTask(createParam, null);
|
|
|
|
|
+// if (task == null || task.getBatchId() == null) {
|
|
|
|
|
+// log.error("createSipTask: 创建 EasyCall 任务失败 - workflowInstanceId: {}", workFlowId);
|
|
|
|
|
+// throw new RuntimeException("EasyCallCenter365 创建任务失败");
|
|
|
|
|
+// }
|
|
|
|
|
+// CompanySiptaskInfo sipTaskInfo = new CompanySiptaskInfo();
|
|
|
|
|
+// sipTaskInfo.setTaskId(roboticId);
|
|
|
|
|
+// sipTaskInfo.setWorkflowId(workFlowId);
|
|
|
|
|
+// sipTaskInfo.setNodeKey(callNode.getNodeKey());
|
|
|
|
|
+// sipTaskInfo.setBatchId(task.getBatchId());
|
|
|
|
|
+// sipTaskInfo.setTaskJson(JSONObject.toJSONString(task));
|
|
|
|
|
+// companySiptaskInfoMapper.insertCompanySiptaskInfo(sipTaskInfo);
|
|
|
|
|
+// return task.getBatchId();
|
|
|
|
|
+// }
|
|
|
|
|
+// } catch (Exception ex) {
|
|
|
|
|
+// log.error("创建SIP任务失败:{}", ex);
|
|
|
|
|
+// }
|
|
|
|
|
+// return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|