| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- <?php
- namespace App\Module\Transfer\Jobs;
- use App\Module\Transfer\Models\TransferOrder;
- use App\Module\Transfer\Enums\TransferStatus;
- use App\Module\Transfer\Logics\OrderLogic;
- use UCore\Queue\QueueJob;
- use Illuminate\Support\Facades\Log;
- /**
- * 重试失败订单任务
- */
- class RetryFailedOrderJob extends QueueJob
- {
- /**
- * 任务最大尝试次数
- *
- * @var int
- */
- public $tries = 3;
- /**
- * 任务超时时间(秒)
- *
- * @var int
- */
- public $timeout = 300;
- /**
- * 订单ID
- *
- * @var int
- */
- protected int $orderId;
- /**
- * 重试原因
- *
- * @var string|null
- */
- protected ?string $retryReason;
- /**
- * 创建任务实例
- *
- * @param int $orderId 订单ID
- * @param string|null $retryReason 重试原因
- */
- public function __construct(int $orderId, ?string $retryReason = null)
- {
- $this->orderId = $orderId;
- $this->retryReason = $retryReason;
- parent::__construct(['order_id' => $orderId, 'retry_reason' => $retryReason]);
- }
- /**
- * 执行任务
- *
- * @return bool
- */
- public function run(): bool
- {
- try {
- // 获取订单
- $order = TransferOrder::find($this->orderId);
- if (!$order) {
- Log::warning('Retry failed order job: Order not found', [
- 'order_id' => $this->orderId
- ]);
- return false;
- }
- // 检查订单状态是否可以重试
- if (!$order->canRetry()) {
- Log::info('Retry failed order job: Order cannot be retried', [
- 'order_id' => $this->orderId,
- 'status' => $order->status->value
- ]);
- return false;
- }
- Log::info('Retrying failed transfer order', [
- 'order_id' => $this->orderId,
- 'type' => $order->type->value,
- 'retry_reason' => $this->retryReason,
- 'attempt' => $this->attempts()
- ]);
- // 重置订单状态为已创建
- $order->updateStatus(TransferStatus::CREATED, '重试处理');
- // 根据订单类型进行重试处理
- $success = false;
- if ($order->isTransferOut()) {
- $success = OrderLogic::processTransferOut($order);
- } elseif ($order->isTransferIn()) {
- // 转入订单通常不需要重试,因为资金已经到账
- // 但可以重试回调发送
- $success = $this->retryTransferInCallback($order);
- }
- if ($success) {
- Log::info('Transfer order retry successful', [
- 'order_id' => $this->orderId,
- 'type' => $order->type->value
- ]);
- } else {
- Log::warning('Transfer order retry failed', [
- 'order_id' => $this->orderId,
- 'type' => $order->type->value,
- 'attempt' => $this->attempts()
- ]);
- // 如果是最后一次尝试,标记为最终失败
- if ($this->attempts() >= $this->tries) {
- $order->updateStatus(TransferStatus::FAILED, '重试次数已达上限');
- }
- }
- } catch (\Exception $e) {
- Log::error('Retry failed order job error', [
- 'order_id' => $this->orderId,
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString()
- ]);
- // 重新抛出异常以触发重试机制
- throw $e;
- }
- return true;
- }
- /**
- * 获取任务数据
- *
- * @return array
- */
- public function payload()
- {
- return [
- 'order_id' => $this->orderId,
- 'retry_reason' => $this->retryReason
- ];
- }
- /**
- * 重试转入订单的回调发送
- *
- * @param TransferOrder $order
- * @return bool
- */
- protected function retryTransferInCallback(TransferOrder $order): bool
- {
- try {
- // 如果应用支持回调,则发送回调
- if ($order->transferApp->supportsCallback()) {
- SendCallbackJob::dispatch($order);
- return true;
- }
- // 如果不支持回调,直接标记为完成
- $order->updateStatus(TransferStatus::COMPLETED);
- return true;
- } catch (\Exception $e) {
- Log::error('Retry transfer in callback failed', [
- 'order_id' => $order->id,
- 'error' => $e->getMessage()
- ]);
- return false;
- }
- }
- /**
- * 任务失败处理
- *
- * @param \Throwable $exception
- * @return void
- */
- public function failed(\Throwable $exception): void
- {
- Log::error('Retry failed order job finally failed', [
- 'order_id' => $this->orderId,
- 'error' => $exception->getMessage(),
- 'attempts' => $this->attempts()
- ]);
- // 尝试更新订单状态为最终失败
- try {
- $order = TransferOrder::find($this->orderId);
- if ($order && $order->canRetry()) {
- $order->updateStatus(TransferStatus::FAILED, '重试任务失败: ' . $exception->getMessage());
- }
- } catch (\Exception $e) {
- Log::error('Failed to update order status after retry job failed', [
- 'order_id' => $this->orderId,
- 'error' => $e->getMessage()
- ]);
- }
- }
- /**
- * 计算重试延迟时间
- *
- * @return int
- */
- public function backoff(): int
- {
- // 指数退避:第1次重试延迟60秒,第2次延迟120秒,第3次延迟240秒
- return 60 * pow(2, $this->attempts() - 1);
- }
- /**
- * 获取任务标识
- *
- * @return string
- */
- public function getJobIdentifier(): string
- {
- return "retry_failed_order_{$this->orderId}";
- }
- }
|