498 lines
12 KiB
PHP
498 lines
12 KiB
PHP
<?php
|
|
|
|
abstract class stTask implements stTaskInterface
|
|
{
|
|
/**
|
|
* Status "oczekuje"
|
|
*/
|
|
const STATUS_PENDING = 0;
|
|
|
|
/**
|
|
* Status "w trakcie wykonywania"
|
|
*/
|
|
const STATUS_RUNNING = 1;
|
|
|
|
/**
|
|
* Cron job logger instance
|
|
*
|
|
* @var stTaskLoggerInterface
|
|
*/
|
|
private $logger;
|
|
|
|
/**
|
|
* Instancja modelu zadania
|
|
*
|
|
* @var Task
|
|
*/
|
|
private $task;
|
|
|
|
/**
|
|
* Undocumented variable
|
|
*
|
|
* @var stEventDispatcher
|
|
*/
|
|
private $dispatcher;
|
|
|
|
/**
|
|
* Aktualny postęp wykonywania zadania w %
|
|
*
|
|
* @var int
|
|
*/
|
|
private $progress = 0;
|
|
|
|
/**
|
|
* Task options
|
|
*
|
|
* @var array
|
|
*/
|
|
private $options = array();
|
|
|
|
/**
|
|
* Własne zdefiniowane parametry zapamietywane na czas trwania zadania
|
|
*
|
|
* @var array
|
|
*/
|
|
private $parameters = array();
|
|
|
|
private $initialized = null;
|
|
|
|
public function __toString()
|
|
{
|
|
return $this->getName();
|
|
}
|
|
|
|
public function isCLI(): bool
|
|
{
|
|
return $this->getParameter('cli', false);
|
|
}
|
|
|
|
public function __construct(Task $task, stTaskLoggerInterface $logger, stEventDispatcher $dispatcher)
|
|
{
|
|
$this->task = $task;
|
|
$this->logger = $logger;
|
|
$this->dispatcher = $dispatcher;
|
|
}
|
|
|
|
final public function doInitialize(bool $reset = false)
|
|
{
|
|
if ($reset)
|
|
{
|
|
if (null === $this->task->getLastOffset() || $this->task->getLastOffset() >= $this->task->getLastCount())
|
|
{
|
|
$this->task->setLastProgress(0);
|
|
$this->task->setLastOffset(0);
|
|
$this->task->setLastCount(null);
|
|
$this->task->save();
|
|
}
|
|
}
|
|
|
|
if (null === $this->initialized)
|
|
{
|
|
$result = $this->initialize();
|
|
$this->initialized = null !== $result ? $result : true;
|
|
}
|
|
|
|
return $this->initialized;
|
|
}
|
|
|
|
public function initialize()
|
|
{
|
|
}
|
|
|
|
final public function setLogger(stTaskLoggerInterface $logger): void
|
|
{
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
/**
|
|
* Ustawia dodatkowe opcje dla zadania
|
|
*
|
|
* @param array $options
|
|
* @return void
|
|
*/
|
|
final public function setOptions(array $options): void
|
|
{
|
|
$this->options = $options;
|
|
}
|
|
|
|
/**
|
|
* Ustawia parametr zapamiętywany na czas trwania zadania
|
|
*
|
|
* @param string $name Nazwa parametru
|
|
* @param mixed $value Wartość parametru
|
|
* @return void
|
|
*/
|
|
final public function setParameter(string $name, $value): void
|
|
{
|
|
$this->parameters[$name] = $value;
|
|
}
|
|
|
|
/**
|
|
* Pobiera parametr
|
|
*
|
|
* @param string $name Nazwa parametru
|
|
* @param mixed $default Wartość domyślna jaka ma być zwrócona w przypadku braku ustawionego parametru
|
|
* @return mixed
|
|
*/
|
|
final public function getParameter(string $name, $default = null)
|
|
{
|
|
return isset($this->parameters[$name]) ? $this->parameters[$name] : $default;
|
|
}
|
|
|
|
/**
|
|
* Zwraca tablice zapamietanych parametrów
|
|
*
|
|
* @return array
|
|
*/
|
|
final public function getParameters(): array
|
|
{
|
|
return $this->parameters;
|
|
}
|
|
|
|
/**
|
|
* Ustawia parametry do zapamietania na czas trwania zadania
|
|
*
|
|
* @param array $parameters Tablica parametrów
|
|
* @return void
|
|
*/
|
|
final public function setParameters(array $parameters): void
|
|
{
|
|
$this->parameters = $parameters;
|
|
}
|
|
|
|
/**
|
|
* Zwraca logger dla zadania
|
|
*
|
|
* @return stTaskLoggerInterface
|
|
*/
|
|
final public function getLogger(): stTaskLoggerInterface
|
|
{
|
|
return $this->logger;
|
|
}
|
|
|
|
/**
|
|
* Zwraca nazwę zadania
|
|
*
|
|
* @return string
|
|
*/
|
|
final public function getName(): string
|
|
{
|
|
return $this->task->getName();
|
|
}
|
|
|
|
/**
|
|
* Odświeża status aktywności zadania
|
|
* Status aktywności odświeżany jest średnio co 5 minut
|
|
* Jeżeli metoda execute zadania wykonuje się dłużej niż 5 minut konieczne jest wywoływanie tej metody ręcznie
|
|
* w innym wypadku zadanie zostanie uznane jako nieaktywne i będzie zostanie uruchomione ponownie
|
|
*
|
|
* @return void
|
|
*/
|
|
final public function refreshActiveStatus(): void
|
|
{
|
|
$this->task->setLastActiveAt(time());
|
|
$this->task->save();
|
|
}
|
|
|
|
/**
|
|
* Zwraca identyfikator zadania
|
|
*
|
|
* @return string
|
|
*/
|
|
final public function getId(): string
|
|
{
|
|
return $this->task->getTaskId();
|
|
}
|
|
|
|
/**
|
|
* Zwraca odstęp czasowy w sekundach co jaki będzie wykonywane zadanie
|
|
*
|
|
* @return int
|
|
*/
|
|
final public function getTimeInterval(): int
|
|
{
|
|
return $this->task->getTimeInterval();
|
|
}
|
|
|
|
/**
|
|
* Zwraca godzinę o jakiej zostanie wykonane zadanie
|
|
*
|
|
* @return string
|
|
*/
|
|
final public function getExecuteAt(): string
|
|
{
|
|
return $this->task->getExecuteAt();
|
|
}
|
|
|
|
/**
|
|
* Zwraca aktualny status zadania
|
|
*
|
|
* @return int
|
|
*/
|
|
final public function getStatus(): int
|
|
{
|
|
return $this->task->getStatus();
|
|
}
|
|
|
|
/**
|
|
* Zwraca instancje modelu zadania
|
|
*
|
|
* @return Task
|
|
*/
|
|
final public function getTask(): Task
|
|
{
|
|
return $this->task;
|
|
}
|
|
|
|
/**
|
|
* Sprawdza czy zadanie jest gotowe do wykonania
|
|
*
|
|
* @return bool
|
|
*/
|
|
final public function isReadyToExecute(bool $checkTime = true): bool
|
|
{
|
|
$ready = $this->task->getIsActive() && $this->getStatus() == self::STATUS_PENDING && (!$checkTime || null === $this->task->getLastExecutedAt() || strtotime($this->task->getNextExecuteDate()) <= time());
|
|
|
|
if (!$ready && $this->getStatus() != self::STATUS_PENDING && time() - strtotime($this->task->getLastActiveAt()) >= stTaskConfiguration::TIME_INTERVAL_10MIN)
|
|
{
|
|
$ready = true;
|
|
}
|
|
|
|
return $ready;
|
|
}
|
|
|
|
final public function getProgress(): int
|
|
{
|
|
return $this->progress;
|
|
}
|
|
|
|
final public function getLastProgress(): int
|
|
{
|
|
return $this->task->getLastProgress();
|
|
}
|
|
|
|
final public function getOffset(): int
|
|
{
|
|
return null !== $this->task->getLastOffset() ? $this->task->getLastOffset() : 0;
|
|
}
|
|
|
|
/**
|
|
* Zwraca ilość do wykonania
|
|
*
|
|
* @return int
|
|
*/
|
|
final public function doCount(bool $forceRefresh = false): int
|
|
{
|
|
try
|
|
{
|
|
if (null === $this->task->getLastCount() || false !== $forceRefresh)
|
|
{
|
|
$count = $this->count();
|
|
|
|
if (!$count)
|
|
{
|
|
$this->getLogger()->info("Zadanie nie wymagało wykonania");
|
|
$this->task->setLastExecutedAt(time());
|
|
$this->task->setLastFinishedAt(time());
|
|
$this->task->save();
|
|
$this->setParameter('clear_cache', false);
|
|
}
|
|
|
|
$this->task->setLastCount($count);
|
|
$this->task->save();
|
|
}
|
|
}
|
|
catch (Throwable $e)
|
|
{
|
|
if (!mysqli_ping(Propel::getConnection()->getResource()))
|
|
{
|
|
Propel::close();
|
|
Propel::initialize();
|
|
}
|
|
|
|
try
|
|
{
|
|
$this->getLogger()->exception($e);
|
|
return 0;
|
|
}
|
|
catch (Throwable $e)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return $this->task->getLastCount();
|
|
}
|
|
|
|
/**
|
|
* Zmienia status zadania jako "w trakcie wykonywania"
|
|
*
|
|
* @return void
|
|
*/
|
|
final private function doStart()
|
|
{
|
|
$this->task->doStart();
|
|
$this->getLogger()->info("Rozpoczęcie wykonywania");
|
|
$this->dispatcher->notify(new sfEvent($this->task, 'task.started'));
|
|
$this->started();
|
|
}
|
|
|
|
/**
|
|
* Ustawia zadanie jako zakończone
|
|
*
|
|
* @return void
|
|
*/
|
|
final public function doFinish(): void
|
|
{
|
|
$this->task->doFinish();
|
|
$this->getLogger()->info("Zakończenie wykonywania");
|
|
$this->dispatcher->notify(new sfEvent($this->task, 'task.finished'));
|
|
$this->finished();
|
|
|
|
if (false !== $this->getParameter('clear_cache'))
|
|
{
|
|
$this->clearCache();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Czyści pamięć podręczną aplikacji
|
|
*
|
|
* @return void
|
|
*/
|
|
public function clearCache()
|
|
{
|
|
stFunctionCache::clearAll();
|
|
stPartialCache::clearAll('frontend');
|
|
stFastCacheManager::clearCache();
|
|
}
|
|
|
|
/**
|
|
* This method is executed once when the task starts
|
|
*
|
|
* @return void
|
|
*/
|
|
public function started()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* This method is executed once when the task ends
|
|
*
|
|
* @return void
|
|
*/
|
|
public function finished()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Wykonuje zadanie
|
|
*
|
|
* @param integer $offset Aktualnie przesunięcie od jakiego ma być wykonuwane zadanie
|
|
* @return integer Zwraca kolejne przesunięcie od jakiego ma być wykonywane zadanie
|
|
*/
|
|
final public function doExecute(int $offset): int
|
|
{
|
|
try
|
|
{
|
|
if (!$offset)
|
|
{
|
|
$this->doStart();
|
|
}
|
|
|
|
if (isset($this->options['unexpected-terminate']))
|
|
{
|
|
exit;
|
|
}
|
|
|
|
$this->disabledCacheClear();
|
|
|
|
$offset = $this->execute($offset);
|
|
|
|
$this->enableClearCache();
|
|
|
|
$this->task->setLastOffset($offset);
|
|
|
|
if (null === $this->task->getLastActiveAt() || time() - strtotime($this->task->getLastActiveAt()) >= stTaskConfiguration::TIME_INTERVAL_5MIN)
|
|
{
|
|
$this->refreshActiveStatus();
|
|
}
|
|
|
|
/**
|
|
* Poprawka wycieku pamięci
|
|
*/
|
|
ProductOptionsValue::clearStaticPool();
|
|
stNewProductOptions::clearStaticPool();
|
|
sfAsset::clearStaticPool();
|
|
|
|
if ($offset > $this->doCount())
|
|
{
|
|
$offset = $this->doCount();
|
|
}
|
|
|
|
$this->progress = intval(($offset / $this->doCount()) * 100);
|
|
|
|
if ($this->progress >= 25 && $this->task->getLastProgress() + 25 <= $this->progress)
|
|
{
|
|
$this->task->setLastProgress($this->progress);
|
|
$this->getLogger()->info("Wykonano %progress%%", array("%progress%" => $this->progress));
|
|
$this->dispatcher->notify(new sfEvent($this, 'task.progress'));
|
|
}
|
|
|
|
if ($offset >= $this->doCount())
|
|
{
|
|
$this->doFinish();
|
|
|
|
return $this->doCount();
|
|
}
|
|
}
|
|
catch (Throwable $e)
|
|
{
|
|
if (!mysqli_ping(Propel::getConnection()->getResource()))
|
|
{
|
|
Propel::close();
|
|
Propel::initialize();
|
|
|
|
try
|
|
{
|
|
$this->doCount();
|
|
$this->getLogger()->warning("Pomyślne przywrócenie utraconego połączenia MySQL");
|
|
return $offset;
|
|
}
|
|
catch (Throwable $e)
|
|
{
|
|
Propel::close();
|
|
Propel::initialize();
|
|
$this->getLogger()->error("Wystąpił błąd podczas próby wznawiania utraconego połączenia MySQL");
|
|
}
|
|
}
|
|
|
|
$this->getLogger()->exception($e);
|
|
|
|
$this->doFinish();
|
|
|
|
return $this->doCount();
|
|
}
|
|
|
|
if (!$this->isCLI())
|
|
{
|
|
$this->task->save();
|
|
}
|
|
|
|
return $offset;
|
|
}
|
|
|
|
private function disabledCacheClear()
|
|
{
|
|
stFastCacheManager::disableClearCache();
|
|
stFunctionCache::disableClearCache(array('stTax'));
|
|
stPartialCache::disableClearCache();
|
|
}
|
|
|
|
private function enableClearCache()
|
|
{
|
|
stFastCacheManager::enableClearCache();
|
|
stFunctionCache::enableClearCache();
|
|
stPartialCache::enableClearCache();
|
|
}
|
|
} |