table = $resource->getTableName('esun_lingxing_order_sync'); } public function enqueue(OrderInterface $order): void { $connection = $this->resource->getConnection(); $exists = $connection->fetchOne( $connection->select()->from($this->table, ['entity_id'])->where('order_id = ?', (int)$order->getEntityId()) ); if ($exists) { return; } $now = gmdate('Y-m-d H:i:s'); $connection->insert($this->table, [ 'order_id' => (int)$order->getEntityId(), 'increment_id' => (string)$order->getIncrementId(), 'platform_order_no' => (string)$order->getIncrementId(), 'status' => 'pending', 'created_at' => $now, 'updated_at' => $now, ]); } public function getDue(int $limit): array { $connection = $this->resource->getConnection(); return $connection->fetchAll($connection->select()->from($this->table) ->where('status IN (?)', ['pending', 'retrying']) ->where('next_retry_at IS NULL OR next_retry_at <= ?', gmdate('Y-m-d H:i:s')) ->order('entity_id ASC')->limit($limit)); } public function claim(int $entityId): bool { return $this->resource->getConnection()->update( $this->table, ['status' => 'processing', 'last_attempt_at' => gmdate('Y-m-d H:i:s')], ['entity_id = ?' => $entityId, 'status IN (?)' => ['pending', 'retrying']] ) === 1; } public function markSuccess(int $entityId, string $globalOrderNo, string $requestId, string $payloadHash): void { $now = gmdate('Y-m-d H:i:s'); $this->resource->getConnection()->update($this->table, [ 'global_order_no' => $globalOrderNo, 'status' => 'success', 'request_id' => $requestId ?: null, 'payload_hash' => $payloadHash, 'last_error_code' => null, 'last_error_message' => null, 'next_retry_at' => null, 'synced_at' => $now, 'updated_at' => $now, ], ['entity_id = ?' => $entityId]); } public function markCreationCanceled(int $entityId): void { $now = gmdate('Y-m-d H:i:s'); $this->resource->getConnection()->update($this->table, [ 'status' => 'canceled', 'next_retry_at' => null, 'updated_at' => $now, ], ['entity_id = ?' => $entityId]); } public function markFailure(int $entityId, int $attemptCount, int $maxAttempts, string $code, string $message, string $requestId = ''): string { $attemptCount++; $status = $attemptCount >= $maxAttempts ? 'failed' : 'retrying'; $delay = min(3600, 30 * (2 ** min(7, max(0, $attemptCount - 1)))); $this->resource->getConnection()->update($this->table, [ 'status' => $status, 'attempt_count' => $attemptCount, 'next_retry_at' => $status === 'retrying' ? gmdate('Y-m-d H:i:s', time() + $delay) : null, 'last_error_code' => $code ?: null, 'last_error_message' => mb_substr($message, 0, 65535), 'request_id' => $requestId ?: null, 'updated_at' => gmdate('Y-m-d H:i:s'), ], ['entity_id = ?' => $entityId]); return $status; } public function findByGlobalOrderNo(string $globalOrderNo): ?array { $connection = $this->resource->getConnection(); $row = $connection->fetchRow($connection->select()->from($this->table) ->where('global_order_no = ?', $globalOrderNo)->limit(1)); return is_array($row) ? $row : null; } public function findByIncrementId(string $incrementId): ?array { $connection = $this->resource->getConnection(); $row = $connection->fetchRow($connection->select()->from($this->table) ->where('increment_id = ?', $incrementId)->limit(1)); return is_array($row) ? $row : null; } /** @return string[] */ public function getTrackablePlatformOrderNos(): array { $connection = $this->resource->getConnection(); $salesOrderTable = $this->resource->getTableName('sales_order'); $select = $connection->select() ->from(['sync' => $this->table], ['platform_order_no']) ->joinInner(['sales_order' => $salesOrderTable], 'sales_order.entity_id = sync.order_id', []) ->where('sync.status = ?', 'success') ->where('sync.platform_order_no <> ?', '') ->where('sales_order.state NOT IN (?)', [ Order::STATE_COMPLETE, Order::STATE_CLOSED, Order::STATE_CANCELED, ]) ->order('sync.entity_id ASC'); return array_values(array_unique(array_map('strval', $connection->fetchCol($select)))); } public function retry(int $entityId): bool { return $this->resource->getConnection()->update($this->table, [ 'status' => 'pending', 'attempt_count' => 0, 'next_retry_at' => null, 'last_error_code' => null, 'last_error_message' => null, 'updated_at' => gmdate('Y-m-d H:i:s'), ], ['entity_id = ?' => $entityId, 'status IN (?)' => ['failed', 'retrying']]) === 1; } }