237 lines
6.7 KiB
PHP
Executable File
237 lines
6.7 KiB
PHP
Executable File
<?php
|
|
|
|
namespace JR\NetSuite\Queue;
|
|
|
|
use JR\NetSuite\Lib\NetSuiteAPI;
|
|
use Magento\Framework\Serialize\SerializerInterface;
|
|
|
|
abstract class AbstractQueueManager {
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $name = 'Abstract';
|
|
|
|
/**
|
|
* @var \JR\NetSuite\Helper\Data
|
|
*/
|
|
protected $helper;
|
|
|
|
/**
|
|
* @var \JR\NetSuite\Logger\Logger
|
|
*/
|
|
protected $logger;
|
|
|
|
/**
|
|
* @var SerializerInterface
|
|
*/
|
|
protected $serializer;
|
|
|
|
/**
|
|
* @var NetSuiteAPI
|
|
*/
|
|
protected $netSuiteAPI;
|
|
|
|
/**
|
|
* AbstractQueueManager constructor.
|
|
*
|
|
* @param \JR\NetSuite\Helper\Data $helper
|
|
* @param \JR\NetSuite\Logger\Logger $logger
|
|
* @param SerializerInterface $serializer
|
|
* @param NetSuiteAPI $netSuiteAPI
|
|
* @return void
|
|
*/
|
|
public function __construct(
|
|
\JR\NetSuite\Helper\Data $helper,
|
|
\JR\NetSuite\Logger\Logger $logger,
|
|
SerializerInterface $serializer,
|
|
NetSuiteAPI $netSuiteAPI
|
|
) {
|
|
$this->helper = $helper;
|
|
$this->logger = $logger;
|
|
$this->serializer = $serializer;
|
|
$this->netSuiteAPI = $netSuiteAPI;
|
|
}
|
|
|
|
/**
|
|
* Fetch data from NetSuite and add it to the queue.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function fetchAndEnqueue($fetchAll = false) {
|
|
$this->logger->info("[$this->name" . "QueueManager] fetchAndEnqueue(" . ($fetchAll ? "true" : "false") . ") started.");
|
|
// max page to fetch and loop to fetch all pages
|
|
$maxPage = 1;
|
|
$page = 1;
|
|
$pageSize = $this->getPageSize();
|
|
$importSize = 0;
|
|
|
|
// Fetch data from NetSuite
|
|
while ($maxPage >= $page) {
|
|
$result = $this->fetch($pageSize, $page);
|
|
if (isset($result['error'])) {
|
|
$this->logger->error($result['message']);
|
|
return [
|
|
'error' => true,
|
|
'message' => $result['message']
|
|
];
|
|
}
|
|
$data = $this->convertToMagentoFormat($result['data']);
|
|
|
|
try {
|
|
$this->enqueue($data);
|
|
} catch (\Exception $e) {
|
|
$this->logger->error("[$this->name" . "QueueManager] " . $e->getMessage());
|
|
throw $e;
|
|
}
|
|
|
|
$importSize += count($data);
|
|
if ($fetchAll) {
|
|
$maxPage = $result['totalPages'];
|
|
}
|
|
$page++;
|
|
sleep(30);
|
|
}
|
|
$this->logger->info("[$this->name" . "QueueManager] fetchAndEnqueue(" . ($fetchAll ? "true" : "false") . ") completes with " . $maxPage . " page(s), pageSize = " . $pageSize . ". " . $this->name);
|
|
|
|
return [
|
|
'error' => false,
|
|
'message' => 'Imported ' . $importSize . ' ' . $this->name . ' records.'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Fetch data from NetSuite
|
|
*
|
|
* @param int $pageSize
|
|
* @param int $page
|
|
* @return array
|
|
*/
|
|
abstract public function fetch($pageSize = 50, $page = 1);
|
|
|
|
/**
|
|
* get the page size for each fetch.
|
|
*
|
|
* @return int
|
|
*/
|
|
abstract public function getPageSize();
|
|
|
|
/**
|
|
* Convert NetSuite data to Magento format
|
|
*
|
|
* @param array $data
|
|
* @return array
|
|
*/
|
|
abstract public function convertToMagentoFormat($data);
|
|
|
|
/**
|
|
* adds data to the queue.
|
|
*
|
|
* @param array $data
|
|
* @return void
|
|
*/
|
|
abstract public function enqueue($data);
|
|
|
|
/**
|
|
* Process batch of queue items
|
|
*
|
|
* @param int $pageSize
|
|
* @param int $page
|
|
* @return
|
|
*/
|
|
public function processBatch($batchSize = 50) {
|
|
$this->logger->info("[$this->name" . "QueueManager] processBatch: batch size -> " . $batchSize);
|
|
$queueItems = $this->dequeue($batchSize);
|
|
$this->logger->info("[$this->name" . "QueueManager] processBatch: queue item size -> " . count($queueItems));
|
|
$totalProcessed = 0;
|
|
if (count($queueItems) == 0) {
|
|
return $totalProcessed;
|
|
}
|
|
|
|
$memoryStart = memory_get_usage();
|
|
$startTime = microtime(true);
|
|
$queueKey = $this->helper->nDigitRandom(5);
|
|
$this->logger->info("# " . $queueKey . " | (Starting " . $this->name . " Queue) | Batch : " . $batchSize);
|
|
|
|
foreach ($queueItems as $item) {
|
|
$i = 50;
|
|
while ($i-- && $item->getStatus() == 'pending') {
|
|
// if ($item->getStatus() != 'pending') {
|
|
// continue; // we do this to make sure this isn't being consumed by another parallel cron processes
|
|
// }
|
|
|
|
$error = false;
|
|
$status = 'success';
|
|
$errorMessage = '';
|
|
|
|
try {
|
|
$item->setStatus('processing')->save();
|
|
$result = $this->processQueueItem($item);
|
|
sleep(1);
|
|
$totalProcessed++;
|
|
} catch (\Throwable $e) {
|
|
$error = true;
|
|
$errorMessage = $e->getMessage();
|
|
$this->logger->error('------------------------' . $this->name);
|
|
$this->logger->error('Queue ID# ' . $item->getId());
|
|
$this->logger->error($e->getMessage());
|
|
$status = 'error';
|
|
if ($e->getMessage() == 'The requested qty is not available') {
|
|
$status = 'pending';
|
|
} else if ($e->getMessage() == 'The requested sku is not assigned to given stock') {
|
|
$status = 'pending';
|
|
} else if (str_starts_with($e->getMessage(), 'No such entity with email')){
|
|
$status = 'pending';
|
|
} else if (str_starts_with($e->getMessage(), 'SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock;')){
|
|
$status = 'pending';
|
|
} else if ($e->getMessage() == 'Product that you are trying to add is not available.') {
|
|
$status = 'pending';
|
|
}
|
|
if ($status == 'error' && ($e->getMessage() != 'Email is required.')) {
|
|
$this->logger->error($e->getTraceAsString());
|
|
}
|
|
}
|
|
|
|
try {
|
|
if ($error) {
|
|
$item->setMessages($errorMessage);
|
|
} else if (isset($result['data'])) {
|
|
$item->setMessages(($result['is_new'] ?? false ? '' : 'Existing ') . 'ID: ' . $result['data']->getId() ?? '');
|
|
}
|
|
$item->setStatus($status);
|
|
$item->save();
|
|
} catch (\Throwable $e) {
|
|
$this->logger->error('Failed update queue item status: ' . $e->getTraceAsString());
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
$memoryEnd = memory_get_usage();
|
|
$endTime = microtime(true);
|
|
$timeSpent = $this->helper->secondsToTime($endTime - $startTime);
|
|
$memoryUsed = $this->helper->formatBytes($memoryEnd - $memoryStart);
|
|
$this->logger->info("[$this->name" . "QueueManager] de-queue, # " . $queueKey . " | (Ending " . $this->name . " Queue) | Batched: " . $batchSize . " | # Processed: " . $totalProcessed . " | Memory Used: " . $memoryUsed . ' | Time: ' . $timeSpent);
|
|
|
|
return $totalProcessed;
|
|
}
|
|
|
|
/**
|
|
* Get next queue items to process
|
|
*
|
|
* @param int $batchSize
|
|
* @return array
|
|
*/
|
|
abstract public function dequeue($batchSize = 50);
|
|
|
|
/**
|
|
* Process queue item
|
|
*
|
|
* @param $queueItem
|
|
* @return mixed
|
|
*/
|
|
abstract public function processQueueItem($queueItem);
|
|
|
|
}
|
|
|