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(); } }