Davidliu 1 ماه پیش
والد
کامیت
a9129dc4f3
2فایلهای تغییر یافته به همراه66 افزوده شده و 35 حذف شده
  1. 54 33
      src/core/callcenter/agent.py
  2. 12 2
      src/core/callcenter/esl/handler/channel_hangup_handler.py

+ 54 - 33
src/core/callcenter/agent.py

@@ -890,10 +890,27 @@ class AgentStateService:
                 return choose_phone_num
             choose_phone_num = self._choose_max_idle_time(idle_agents)
             self.handle_assign_time(saas_id, service_id, choose_phone_num)
+            self.handle_lock_agent(choose_phone_num, saas_id, service_id)
         finally:
             lock.release()
         return choose_phone_num
 
+    def handle_check_agent_lock(self, choose_phone_num, saas_id, service_id='00000000000000000'):
+        key = self._lock_key(saas_id, service_id, choose_phone_num)
+        res = self.redis_handler.redis.get(key)
+        self.logger.info('checkAgent %s %s %s %s'% (saas_id, service_id, choose_phone_num, res))
+        return False if res else True
+
+    def handle_lock_agent(self, choose_phone_num, saas_id, service_id='00000000000000000'):
+        key = self._lock_key(saas_id, service_id, choose_phone_num)
+        self.redis_handler.redis.set(key, 1, nx=True, expire=self._get_expire_time())
+        self.logger.info('lockAgent %s %s %s'% (saas_id, service_id, choose_phone_num))
+
+    def handle_release_agent_lock(self, choose_phone_num, saas_id, service_id='00000000000000000'):
+        key = self._lock_key(saas_id, service_id, choose_phone_num)
+        self.redis_handler.redis.delete(key)
+        self.logger.info('releaseAgent %s %s %s'% (saas_id, service_id, choose_phone_num))
+
     def handle_assign_time(self, saas_id, service_id, choose_phone_num):
         key = self._key(saas_id, service_id)
         cache_agent_map = self.get_cache_agent_map(saas_id, service_id)
@@ -964,13 +981,14 @@ class AgentStateService:
         return free_agents
 
     def get_idle_agents(self,cache_agent_list):
-        current_time =int(datetime.now().timestamp() * 1000)  # 获取当前时间的毫秒级时间戳
+        # current_time =int(datetime.now().timestamp() * 1000)  # 获取当前时间的毫秒级时间戳
         idle_agents = [
             agent for agent in cache_agent_list
-            if agent.status == 1 and (
-                    agent.assign_time == 0 or
-                    agent.assign_time + self.assigned_recycle_millisecond < current_time
-            )
+            if agent.status == 1 and self.handle_check_agent_lock(agent.phone_num, SAAS_ID)
+               #and (
+               #     agent.assign_time == 0 or
+               #     agent.assign_time + self.assigned_recycle_millisecond < current_time
+            #)
         ]
         return idle_agents
 
@@ -991,34 +1009,34 @@ class AgentStateService:
             busy_agents_size = len(busy_agents)  # 获取忙碌代理的数量
         return busy_agents_size
 
-    def update_report_state(self, saas_id, service_id):
-        key = self._key(saas_id, service_id)
-        # data_map 这个地方有疑问
-        data_map = self.state_service_id_data_map[key]
-        idle = HumanState.IDLE
-        if idle.value not in data_map:
-            data_map[idle.code] = threading.Lock()
-            self.executor.submit(self.do_report_real_time_human_service_id, saas_id, service_id, idle)
-            # data_map[idle.code] = self.do_report_real_time_human_service_id(saas_id, service_id, idle)
-        busy = HumanState.BUSY
-        if busy.value not in data_map:
-            data_map[busy.code] = threading.Lock()
-            self.executor.submit(self.do_report_real_time_human_service_id, saas_id, service_id, busy)
-            # data_map[busy.code] = self.do_report_real_time_human_service_id(saas_id, service_id, busy)
-
-    def do_report_real_time_human_service_id(self, saas_id, service_id, human_state):
-        name = "cti_center_real_time_human_service_state"
-        tag_list = {
-            "vcc_id": saas_id,
-            "service_id": service_id,
-            "state": human_state.code,
-        }
-        if human_state == HumanState.IDLE:
-            # meter_registry 这块疑问
-            self.meter_registry.gauge(name, tag_list, self, lambda ctx: ctx.get_agent_service_busy_size(saas_id, service_id))
-        elif human_state == HumanState.BUSY:
-            self.meter_registry.gauge(name, tag_list, self, lambda ctx: ctx.get_agent_service_idle_size(saas_id, service_id))
-        return 0
+    # def update_report_state(self, saas_id, service_id):
+    #     key = self._key(saas_id, service_id)
+    #     # data_map 这个地方有疑问
+    #     data_map = self.state_service_id_data_map[key]
+    #     idle = HumanState.IDLE
+    #     if idle.value not in data_map:
+    #         data_map[idle.code] = threading.Lock()
+    #         self.executor.submit(self.do_report_real_time_human_service_id, saas_id, service_id, idle)
+    #         # data_map[idle.code] = self.do_report_real_time_human_service_id(saas_id, service_id, idle)
+    #     busy = HumanState.BUSY
+    #     if busy.value not in data_map:
+    #         data_map[busy.code] = threading.Lock()
+    #         self.executor.submit(self.do_report_real_time_human_service_id, saas_id, service_id, busy)
+    #         # data_map[busy.code] = self.do_report_real_time_human_service_id(saas_id, service_id, busy)
+    #
+    # def do_report_real_time_human_service_id(self, saas_id, service_id, human_state):
+    #     name = "cti_center_real_time_human_service_state"
+    #     tag_list = {
+    #         "vcc_id": saas_id,
+    #         "service_id": service_id,
+    #         "state": human_state.code,
+    #     }
+    #     if human_state == HumanState.IDLE:
+    #         # meter_registry 这块疑问
+    #         self.meter_registry.gauge(name, tag_list, self, lambda ctx: ctx.get_agent_service_busy_size(saas_id, service_id))
+    #     elif human_state == HumanState.BUSY:
+    #         self.meter_registry.gauge(name, tag_list, self, lambda ctx: ctx.get_agent_service_idle_size(saas_id, service_id))
+    #     return 0
 
     def _check_in_key(self, saas_id):
         return "CTI:%s:HUMAN:AGENT"%(saas_id.upper())
@@ -1026,6 +1044,9 @@ class AgentStateService:
     def _key(self, saas_id, service_id):
         return "CTI:%s:HUMAN:%s"%(saas_id.upper(), service_id)
 
+    def _lock_key(self, saas_id, service_id, choose_phone_num):
+        return "CTI:%s:HUMAN:%s:%s:LOCK"%(saas_id.upper(), service_id, choose_phone_num)
+
     def _get_expire_time(self):
         now = datetime.now()
         end_of_day = now.replace(hour=23, minute=59, second=59, microsecond=0)

+ 12 - 2
src/core/callcenter/esl/handler/channel_hangup_handler.py

@@ -8,7 +8,9 @@ import traceback
 from pydub import AudioSegment
 import threading
 from src.core.callcenter.acd import AcdService
+from src.core.callcenter.agent import AgentStateService
 from src.core.callcenter.call import CallService
+from src.core.callcenter.constant import SAAS_ID
 from src.core.callcenter.enumeration import CallType, DeviceType, AnswerFlag, NextType, CdrType, HangupDir, \
     CallCause,AgentServiceState,AgentScene, WorkStatus
 from src.core.callcenter.esl.annotation import EslEventName
@@ -29,6 +31,8 @@ class ChannelHangupHandler(EslEventHandler):
         self.call_service = CallService(inbound_client,inbound_client.app)
         self.push_handler = PushHandler(inbound_client.logger)
         self.dataHandleServer=DataHandleServer(inbound_client.app)
+        self.agent_state_service = AgentStateService(inbound_client.app)
+
 
     def handle(self, address, event, coreUUID):
         # self.logger.info(json.loads(event.serialize('json')))
@@ -130,7 +134,7 @@ class ChannelHangupHandler(EslEventHandler):
             # 全部挂机以后推送挂机状态
             # self.logger.info('yushanghui::call_info.device_list %s', call_info.device_list)
             if call_info.hangup_count >= call_info.answer_count:
-            # if len(call_info.device_list) == 0:
+                # if len(call_info.device_list) == 0:
                 self.get_call_info_record(call_info)
 
             # 连续报警判断
@@ -138,6 +142,8 @@ class ChannelHangupHandler(EslEventHandler):
             # 判断挂机方向 && 更新缓存
             self.hangup_dir(call_info, device_info, cause)
             self.cache.add_call_info(call_info, persistent=True)
+            # 释放坐席接听锁
+            self.agent_state_service.handle_release_agent_lock(call_info.agent_key, SAAS_ID)
 
         except:
             traceback.print_exc()
@@ -225,7 +231,11 @@ class ChannelHangupHandler(EslEventHandler):
         if not audio_files:
             self.logger.info("没有可合并的音频文件")
             return
-            # 初始化第一个音频文件
+        if not os.path.exists(audio_files[0]):
+            self.logger.info("没有可合并的音频文件")
+            return
+
+        # 初始化第一个音频文件
         combined = AudioSegment.from_file(audio_files[0])
         # 循环添加其余的音频文件
         for audio_file in audio_files[1:]: