BaseJob.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. declare(strict_types=1);
  3. namespace SixShop\Core\Job;
  4. use Closure;
  5. use think\facade\Log;
  6. use think\queue\Job;
  7. use function Opis\Closure\{serialize, unserialize};
  8. /**
  9. * @template T
  10. */
  11. abstract class BaseJob
  12. {
  13. // 最大重试次数
  14. protected int $maxAttempts = 3;
  15. // 重试延迟时间(秒)
  16. protected int $retryDelay = 60;
  17. // 是否启用失败回调
  18. protected bool $enableFailedCallback = true;
  19. // 是否闭包
  20. protected bool $isClosure = false;
  21. /**
  22. * 分发任务
  23. *
  24. * @param T $data 任务数据
  25. * @param int $delay 延迟时间
  26. * @param string|null $queue 队列名称
  27. */
  28. public static function dispatch(mixed $data = '', int $delay = 0, ?string $queue = null): JobDispatcher
  29. {
  30. if ($data instanceof Closure) {
  31. $data = serialize($data);
  32. }
  33. return new JobDispatcher(static ::class, $data, $delay, $queue);
  34. }
  35. /**
  36. * 主要的处理方法 - 不需要子类重写
  37. *
  38. * @param Job $job 队列任务对象
  39. * @param T $data 任务数据
  40. */
  41. public function fire(Job $job, mixed $data): void
  42. {
  43. try {
  44. if ($this->isClosure) {
  45. $data = unserialize($data);
  46. }
  47. // 前置处理
  48. if (!$this->beforeExecute($data)) {
  49. $job->delete();
  50. return;
  51. }
  52. if (method_exists($this, 'execute')) {
  53. // 执行任务
  54. $result = $this->execute($data);
  55. }
  56. // 后置处理
  57. $this->afterExecute($data, $result);
  58. // 标记任务完成
  59. $job->delete();
  60. } catch (\Exception|\Throwable $e) {
  61. $this->handleException($job, $data, $e);
  62. }
  63. }
  64. /**
  65. * 任务前置处理 - 子类可重写
  66. *
  67. * @param T $data 任务数据
  68. * @return bool 是否继续执行
  69. */
  70. protected function beforeExecute(mixed $data): bool
  71. {
  72. return true;
  73. }
  74. /**
  75. * 任务后置处理 - 子类可重写
  76. *
  77. * @param T $data 任务数据
  78. * @param mixed $result 执行结果
  79. */
  80. protected function afterExecute(mixed $data, mixed $result): void
  81. {
  82. // 可以在这里添加通用的后置处理逻辑
  83. }
  84. /**
  85. * 异常处理
  86. *
  87. * @param Job $job 队列任务对象
  88. * @param T $data 任务数据
  89. * @param \Throwable|\Exception $exception 异常对象
  90. */
  91. protected function handleException(Job $job, mixed $data, \Throwable|\Exception $exception): void
  92. {
  93. Log::error('队列任务执行异常: ' . static::class . ' - ' . $exception->getMessage(), [
  94. 'data' => is_array($data) ? $data : ['data' => $data],
  95. 'trace' => $exception->getTraceAsString()
  96. ]);
  97. // 判断是否需要重试
  98. if ($job->attempts() < $this->maxAttempts) {
  99. // 重新发布任务
  100. $job->release($this->retryDelay);
  101. } else {
  102. // 标记任务失败
  103. $job->failed($exception);
  104. // 执行失败回调
  105. if ($this->enableFailedCallback) {
  106. try {
  107. $this->onFailed($data);
  108. } catch (\Exception $e) {
  109. Log::error('任务失败回调执行异常: ' . $e->getMessage());
  110. }
  111. }
  112. }
  113. }
  114. /**
  115. * 任务失败处理方法 - 子类可重写
  116. *
  117. * @param T $data 任务数据
  118. */
  119. protected function onFailed(mixed $data): void
  120. {
  121. // 默认失败处理逻辑
  122. Log::error('队列任务执行失败: ' . static::class, (array)$data);
  123. }
  124. /**
  125. * 设置最大重试次数
  126. *
  127. * @param int $attempts
  128. * @return $this
  129. */
  130. protected function setMaxAttempts(int $attempts): static
  131. {
  132. $this->maxAttempts = $attempts;
  133. return $this;
  134. }
  135. /**
  136. * 设置重试延迟时间
  137. *
  138. * @param int $delay
  139. * @return $this
  140. */
  141. protected function setRetryDelay(int $delay): static
  142. {
  143. $this->retryDelay = $delay;
  144. return $this;
  145. }
  146. /**
  147. * 禁用失败回调
  148. *
  149. * @return $this
  150. */
  151. protected function disableFailedCallback(): static
  152. {
  153. $this->enableFailedCallback = false;
  154. return $this;
  155. }
  156. }