|
@@ -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.stereotype.Service;
|
|
|
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
|
|
@@ -75,6 +77,9 @@ public class CompanyWorkflowEngineImpl implements CompanyWorkflowEngine {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
CompanyWxClientMapper companyWxClientMapper;
|
|
CompanyWxClientMapper companyWxClientMapper;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private RedisCache redisCache;
|
|
|
|
|
+
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private CloudHostProper cloudHostProper;
|
|
private CloudHostProper cloudHostProper;
|
|
|
|
|
|
|
@@ -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();
|
|
@@ -572,35 +575,44 @@ 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()) {
|
|
if (callConfigVo.getExtensionList() != null && !callConfigVo.getExtensionList().isEmpty()) {
|
|
@@ -628,9 +640,12 @@ 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;
|
|
|
}
|
|
}
|