You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
8.4KB

  1. # -*- coding: utf-8 -*-
  2. import time
  3. from traceback import format_exc
  4. from multiprocessing import Process, Queue
  5. from loguru import logger
  6. from concurrency.Pull2PushStreamThread import PushSteamThread
  7. from enums.StatusEnum import PushStreamStatus, ExecuteStatus
  8. from util.LogUtils import init_log
  9. from enums.ExceptionEnum import ExceptionType
  10. from entity.FeedBack import pull_stream_feedback
  11. from exception.CustomerException import ServiceException
  12. from util.QueUtil import get_no_block_queue, put_queue
  13. class PushStreamProcess(Process):
  14. __slots__ = ('_fb_queue', 'event_queue', '_context', '_msg', '_analysisType')
  15. def __init__(self, *args):
  16. super().__init__()
  17. self._fb_queue, self._context, self._msg, self._analysisType = args
  18. self.event_queue = Queue()
  19. def sendEvent(self, eBody):
  20. try:
  21. self.event_queue.put(eBody, timeout=2)
  22. except Exception:
  23. logger.error("添加事件到队列超时异常:{}, requestId:{}", format_exc(), self._msg["request_id"])
  24. raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
  25. ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
  26. def run(self):
  27. msg, context = self._msg, self._context
  28. requestId, videoUrls = msg["request_id"], msg["video_urls"]
  29. base_dir, env = context['base_dir'], context['env']
  30. fb_queue = self._fb_queue
  31. task, videoStatus = {}, {}
  32. ex = None
  33. try:
  34. init_log(base_dir, env)
  35. if videoUrls is None or len(videoUrls) == 0:
  36. raise ServiceException(ExceptionType.PUSH_STREAM_URL_IS_NULL.value[0],
  37. ExceptionType.PUSH_STREAM_URL_IS_NULL.value[1])
  38. if len(videoUrls) > 5:
  39. logger.error("推流数量超过限制, 当前推流数量: {}, requestId:{}", len(videoUrls), requestId)
  40. raise ServiceException(ExceptionType.PULL_STREAM_NUM_LIMIT_EXCEPTION.value[0],
  41. ExceptionType.PULL_STREAM_NUM_LIMIT_EXCEPTION.value[1])
  42. videoInfo = [{"id": url["id"], "status": PushStreamStatus.WAITING.value[0]} for url in videoUrls if
  43. url.get("id")]
  44. put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.WAITING.value[0], "", "", videoInfo))
  45. for videoUrl in videoUrls:
  46. pushThread = PushSteamThread(videoUrl["pull_url"], videoUrl["push_url"], requestId, videoUrl["id"])
  47. pushThread.start()
  48. task[videoUrl["id"]] = pushThread
  49. enable_time = time.time()
  50. for video in videoInfo:
  51. videoStatus[video.get("id")] = video.get("status")
  52. count = 0
  53. while True:
  54. # 整个推流任务超时时间
  55. if time.time() - enable_time > 43200:
  56. logger.error("任务执行超时, requestId:{}", requestId)
  57. for t in list(task.keys()):
  58. if task[t].is_alive():
  59. task[t].status = False
  60. task[t].pushStreamUtil.close_push_stream_sp()
  61. task[t].join(120)
  62. videoStatus[t] = PushStreamStatus.TIMEOUT.value[0]
  63. videoInfo_timeout = [{"id": k, "status": v} for k, v in videoStatus.items()]
  64. put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.TIMEOUT.value[0],
  65. ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
  66. ExceptionType.TASK_EXCUTE_TIMEOUT.value[1],
  67. videoInfo_timeout))
  68. break
  69. # 接受停止指令
  70. event_result = get_no_block_queue(self.event_queue)
  71. if event_result is not None:
  72. command = event_result.get("command")
  73. videoIds = event_result.get("videoIds")
  74. if "stop" == command:
  75. # 如果videoIds是空停止所有任务
  76. if videoIds is None or len(videoIds) == 0:
  77. logger.info("停止所有执行的推流任务, requestId:{}", requestId)
  78. for t in list(task.keys()):
  79. if task[t].is_alive():
  80. task[t].status = False
  81. task[t].pushStreamUtil.close_push_stream_sp()
  82. task[t].join(120)
  83. videoStatus[t] = PushStreamStatus.SUCCESS.value[0]
  84. videoInfo_sucess = [{"id": k, "status": v} for k, v in videoStatus.items()]
  85. put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.SUCCESS.value[0], "", "",
  86. videoInfo_sucess))
  87. break
  88. else:
  89. logger.info("停止指定的推流任务, requestId:{}", requestId)
  90. alive_thread = 0
  91. for t in list(task.keys()):
  92. if task[t].is_alive():
  93. if t in videoIds:
  94. task[t].status = False
  95. task[t].pushStreamUtil.close_push_stream_sp()
  96. task[t].join(120)
  97. videoStatus[t] = PushStreamStatus.SUCCESS.value[0]
  98. else:
  99. alive_thread += 1
  100. if alive_thread == 0:
  101. videoInfo_sucess = [{"id": k, "status": v} for k, v in videoStatus.items()]
  102. put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.SUCCESS.value[0], "",
  103. "", videoInfo_sucess))
  104. break
  105. for t in list(task.keys()):
  106. if task[t].status and not task[t].is_alive():
  107. videoStatus[t] = PushStreamStatus.FAILED.value[0]
  108. logger.error("检测到推流线程异常停止!videoId:{}, requestId:{}", t, requestId)
  109. if task[t].ex:
  110. raise task[t].ex
  111. raise Exception("检测到推流线程异常停止!")
  112. if task[t].is_alive():
  113. videoStatus[t] = task[t].excute_status
  114. if count % 10 == 0:
  115. videoInfo_hb = [{"id": k, "status": v} for k, v in videoStatus.items()]
  116. put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.RUNNING.value[0], "", "",
  117. videoInfo_hb))
  118. count = 0
  119. count += 1
  120. time.sleep(1)
  121. except ServiceException as s:
  122. ex = s.code, s.msg
  123. logger.error("服务异常,异常编号:{}, 异常描述:{}, requestId: {}", s.code, s.msg, requestId)
  124. except Exception:
  125. ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
  126. logger.error("服务异常: {}, requestId: {},", format_exc(), requestId)
  127. finally:
  128. if ex:
  129. errorCode, errorMsg = ex
  130. for t in list(task.keys()):
  131. if task[t].is_alive():
  132. task[t].status = False
  133. task[t].pushStreamUtil.close_push_stream_sp()
  134. task[t].join(120)
  135. videoStatus[t] = PushStreamStatus.FAILED.value[0]
  136. videoInfo_ex = [{"id": k, "status": v} for k, v in videoStatus.items()]
  137. put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.FAILED.value[0], errorCode, errorMsg,
  138. videoInfo_ex))
  139. for t in list(task.keys()):
  140. if task[t].is_alive():
  141. task[t].status = False
  142. task[t].pushStreamUtil.close_push_stream_sp()
  143. task[t].join(120)
  144. logger.info("推流任务完成, requestId: {}", requestId)