#add jira & message sync
This commit is contained in:
271
app/Services/EventConsumerSyncService.php
Normal file
271
app/Services/EventConsumerSyncService.php
Normal file
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class EventConsumerSyncService
|
||||
{
|
||||
/**
|
||||
* Agent监听的所有topic列表
|
||||
*/
|
||||
private const AGENT_LISTENED_TOPICS = [
|
||||
// Case
|
||||
'CASE_CREATE',
|
||||
'CASE_FILE',
|
||||
'CASE_3D_SEND',
|
||||
'CASE_3D_CONFIRM',
|
||||
'CASE_3D_CANCEL_CONFIRM',
|
||||
'CASE_STAGE_FINISH',
|
||||
'CASE_STAGE_CREATE',
|
||||
'CASE_FINISH',
|
||||
'CASE_PAUSE',
|
||||
'CASE_DELETED',
|
||||
'CASE_CONTINUE',
|
||||
'CASE_MONEY_IN',
|
||||
'CASE_BASIC_INFO_CHANGE',
|
||||
'CASE_REFERRAL',
|
||||
'CASE_TAGS_CHANGE',
|
||||
'CASE_RECOVER',
|
||||
'CASE_PRODUCT_WAIT_CONFIRM',
|
||||
'CASE_PRODUCT_CONFIRM',
|
||||
'CASE_PRODUCT_CANCEL_CONFIRM',
|
||||
'CASE_START_DESIGN',
|
||||
'CASE_NOT_TREATED',
|
||||
'CASE_REOPEN',
|
||||
'MEDICAL_DESIGN_EVENT',
|
||||
// Production
|
||||
'PRODUCTION_CREATE',
|
||||
'PRODUCTION_DELIVER',
|
||||
'SHIPPING_STATUS',
|
||||
'PRODUCTION_INFO_CHANGE',
|
||||
// Doctor
|
||||
'DOCTOR_CREATE',
|
||||
'DOCTOR_INFO_CHANGE',
|
||||
'DOCTOR_STATUS_CHANGE',
|
||||
'DOCTOR_DELETE',
|
||||
// Hospital
|
||||
'ACCOUNT_CREATE',
|
||||
'ACCOUNT_INFO_CHANGE',
|
||||
'ACCOUNT_AUTH_CHANGE',
|
||||
'ACCOUNT_STATUS_CHANGE',
|
||||
// BA
|
||||
'BA_CREATE',
|
||||
'BA_INFO_CHANGE',
|
||||
// Business Document
|
||||
'BUSINESS_ORDER_CREATE',
|
||||
'BUSINESS_ORDER_DATA_CHANGE',
|
||||
'BUSINESS_ORDER_STATUS_CHANGE',
|
||||
'BUSINESS_ORDER_CHECK',
|
||||
// Sale Document
|
||||
'SALES_ORDER_CREATE',
|
||||
'SALES_ORDER_DATA_CHANGE',
|
||||
'SALES_ORDER_STATUS_CHANGE',
|
||||
// Contract
|
||||
'CONTRACT_CREATE',
|
||||
'CONTRACT_INFO_CHANGE',
|
||||
// Lead Hospital
|
||||
'LEAD_HOSPITAL_CREATE',
|
||||
'LEAD_HOSPITAL_CHANGE',
|
||||
// Lead Doctor
|
||||
'CREATE_LEADS',
|
||||
'LEAD_UPDATE',
|
||||
// GROUP
|
||||
'GROUP_CREATE',
|
||||
'GROUP_INFO_CHANGE',
|
||||
// Hospital Enter
|
||||
'ACCOUNT_ENTER_INFO_REJECT',
|
||||
// Orthodontic
|
||||
'APPLIANCE_CREATE',
|
||||
'APPLIANCE_CHANGE',
|
||||
'RETAINER_CHANGE',
|
||||
'SET_MENU_CHANGE',
|
||||
];
|
||||
|
||||
/**
|
||||
* 查询CRM事件消费者表的消息数据
|
||||
* 只查询Agent监听的topic
|
||||
*/
|
||||
public function getCrmEventConsumers(
|
||||
?Carbon $startTime = null,
|
||||
?Carbon $endTime = null,
|
||||
array $excludeMessages = []
|
||||
): array {
|
||||
try {
|
||||
$query = DB::connection('crmslave')
|
||||
->table('crm_api.crm_event_consumer');
|
||||
|
||||
// 只查询Agent监听的topic
|
||||
$query->whereIn('event_name', self::AGENT_LISTENED_TOPICS);
|
||||
|
||||
if ($startTime) {
|
||||
$query->where('created', '>=', $startTime);
|
||||
}
|
||||
|
||||
if ($endTime) {
|
||||
$query->where('created', '<=', $endTime);
|
||||
}
|
||||
|
||||
if (!empty($excludeMessages)) {
|
||||
$query->whereNotIn('event_name', $excludeMessages);
|
||||
}
|
||||
|
||||
$messages = $query->select([
|
||||
'msg_id',
|
||||
'event_name',
|
||||
'msg_body',
|
||||
'created',
|
||||
'updated'
|
||||
])->get();
|
||||
|
||||
return $messages->map(function ($msg) {
|
||||
return [
|
||||
'msg_id' => $msg->msg_id,
|
||||
'event_name' => $msg->event_name,
|
||||
'msg_body' => $msg->msg_body,
|
||||
'created' => $msg->created,
|
||||
'updated' => $msg->updated,
|
||||
];
|
||||
})->toArray();
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException('查询CRM事件消费者表失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询Agent事件消费者表的消息数据(通过msg_id列表,分批查询)
|
||||
* @param array $msgIds msg_id列表
|
||||
* @param int $batchSize 每批查询的数量,默认1000
|
||||
*/
|
||||
public function getAgentEventConsumersByMsgIds(array $msgIds, int $batchSize = 1000): array {
|
||||
try {
|
||||
if (empty($msgIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
|
||||
// 分批查询,避免一次性查询过多数据导致慢查询
|
||||
$batches = array_chunk($msgIds, $batchSize);
|
||||
|
||||
foreach ($batches as $batch) {
|
||||
$batchMessages = DB::connection('agentslave')
|
||||
->table('crm_event_consumer')
|
||||
->whereIn('msg_id', $batch)
|
||||
->select([
|
||||
'msg_id',
|
||||
'event_name',
|
||||
'msg_body',
|
||||
'created',
|
||||
'updated'
|
||||
])->get();
|
||||
|
||||
foreach ($batchMessages as $msg) {
|
||||
$messages[] = [
|
||||
'msg_id' => $msg->msg_id,
|
||||
'event_name' => $msg->event_name,
|
||||
'msg_body' => $msg->msg_body,
|
||||
'created' => $msg->created,
|
||||
'updated' => $msg->updated,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException('查询Agent事件消费者表失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对比CRM和Agent的消息,找出缺失的消息
|
||||
* 策略:先查CRM的msg_id,然后用这些msg_id到Agent中查询,避免时间差异导致的缺失
|
||||
*/
|
||||
public function compareSyncStatus(
|
||||
?Carbon $startTime = null,
|
||||
?Carbon $endTime = null,
|
||||
array $excludeMessages = [],
|
||||
?string $messageName = null
|
||||
): array {
|
||||
// 1. 先查询CRM中的所有消息
|
||||
$crmMessages = $this->getCrmEventConsumers($startTime, $endTime, $excludeMessages);
|
||||
|
||||
// 如果指定了消息名称,则进一步过滤
|
||||
if ($messageName) {
|
||||
$crmMessages = array_filter($crmMessages, function ($msg) use ($messageName) {
|
||||
return $msg['event_name'] === $messageName;
|
||||
});
|
||||
}
|
||||
|
||||
$crmMsgIds = array_column($crmMessages, 'msg_id');
|
||||
|
||||
// 2. 用CRM的msg_id到Agent中查询(不受时间限制)
|
||||
$agentMessages = $this->getAgentEventConsumersByMsgIds($crmMsgIds);
|
||||
$agentMsgIds = array_column($agentMessages, 'msg_id');
|
||||
|
||||
// 3. 找出在CRM中但不在Agent中的消息
|
||||
$missingMsgIds = array_diff($crmMsgIds, $agentMsgIds);
|
||||
|
||||
$missingMessages = array_filter($crmMessages, function ($msg) use ($missingMsgIds) {
|
||||
return in_array($msg['msg_id'], $missingMsgIds);
|
||||
});
|
||||
|
||||
// 4. 按topic统计缺失消息数量
|
||||
$missingByTopic = $this->groupMissingMessagesByTopic($missingMessages);
|
||||
|
||||
return [
|
||||
'crm_total' => count($crmMessages),
|
||||
'agent_total' => count($agentMessages),
|
||||
'missing_count' => count($missingMessages),
|
||||
'sync_rate' => count($crmMessages) > 0
|
||||
? round((count($crmMessages) - count($missingMessages)) / count($crmMessages) * 100, 2)
|
||||
: 100,
|
||||
'missing_messages' => array_values($missingMessages),
|
||||
'missing_by_topic' => $missingByTopic,
|
||||
'summary' => [
|
||||
'start_time' => $startTime?->toDateTimeString(),
|
||||
'end_time' => $endTime?->toDateTimeString(),
|
||||
'message_name' => $messageName,
|
||||
'excluded_messages' => $excludeMessages,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Agent监听的所有topic列表
|
||||
*/
|
||||
public function getAgentListenedTopics(): array {
|
||||
return self::AGENT_LISTENED_TOPICS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按topic统计缺失消息数量
|
||||
*/
|
||||
private function groupMissingMessagesByTopic(array $missingMessages): array {
|
||||
$grouped = [];
|
||||
|
||||
foreach ($missingMessages as $msg) {
|
||||
$topic = $msg['event_name'] ?? 'unknown';
|
||||
|
||||
if (!isset($grouped[$topic])) {
|
||||
$grouped[$topic] = [
|
||||
'topic' => $topic,
|
||||
'count' => 0,
|
||||
'messages' => []
|
||||
];
|
||||
}
|
||||
|
||||
$grouped[$topic]['count']++;
|
||||
$grouped[$topic]['messages'][] = $msg['msg_id'];
|
||||
}
|
||||
|
||||
// 按缺失数量降序排序
|
||||
uasort($grouped, function ($a, $b) {
|
||||
return $b['count'] - $a['count'];
|
||||
});
|
||||
|
||||
return array_values($grouped);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user