|
|
|
@@ -0,0 +1,148 @@
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace App\Command;
|
|
|
|
|
|
|
|
|
|
use App\Entity\Database\Comments\Comment;
|
|
|
|
|
use App\Entity\Database\Posts\Post;
|
|
|
|
|
use App\Entity\Database\Users\User;
|
|
|
|
|
use App\Repository\Users\CompanyRepository;
|
|
|
|
|
use App\Service\Persist\RemoteCommentConvertor;
|
|
|
|
|
use App\Service\Persist\RemotePostsConvertor;
|
|
|
|
|
use App\Service\Persist\RemoteUsersConvertor;
|
|
|
|
|
use App\Service\Remote\BriloApiComments;
|
|
|
|
|
use App\Service\Remote\BriloApiPosts;
|
|
|
|
|
use App\Service\Remote\BriloApiUsers;
|
|
|
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
|
use Symfony\Component\Console\Command\Command;
|
|
|
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
|
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
|
|
|
use Symfony\Component\Lock\LockFactory;
|
|
|
|
|
use Symfony\Component\Lock\SharedLockInterface;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Download new data from Brilo API and import it into the database.
|
|
|
|
|
*/
|
|
|
|
|
final class RefreshDatabaseCommand extends Command
|
|
|
|
|
{
|
|
|
|
|
private readonly SharedLockInterface $lock;
|
|
|
|
|
|
|
|
|
|
public function __construct(
|
|
|
|
|
?string $name,
|
|
|
|
|
private readonly BriloApiComments $remoteComments,
|
|
|
|
|
private readonly BriloApiPosts $remotePosts,
|
|
|
|
|
private readonly BriloApiUsers $remoteUsers,
|
|
|
|
|
private readonly LoggerInterface $logger,
|
|
|
|
|
private readonly RemoteUsersConvertor $remoteUsersConvertor,
|
|
|
|
|
private readonly RemotePostsConvertor $remotePostsConvertor,
|
|
|
|
|
private readonly RemoteCommentConvertor $remoteCommentsConvertor,
|
|
|
|
|
private readonly CompanyRepository $companyRepository,
|
|
|
|
|
private readonly EntityManagerInterface $em,
|
|
|
|
|
LockFactory $lock,
|
|
|
|
|
) {
|
|
|
|
|
$this->lock = $lock->createLock('refresh-database');
|
|
|
|
|
parent::__construct($name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function configure(): void
|
|
|
|
|
{
|
|
|
|
|
$this->setHelp('Refresh the database from the Brilo API');
|
|
|
|
|
$this->setDescription('Import new data from Brilo API and import it into the database.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
|
|
|
{
|
|
|
|
|
$this->lock->acquire(true);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
return $this->runImport();
|
|
|
|
|
} finally {
|
|
|
|
|
$this->lock->release();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* @return int
|
|
|
|
|
* @throws \Exception
|
|
|
|
|
*/
|
|
|
|
|
private function runImport(): int
|
|
|
|
|
{
|
|
|
|
|
$returnCode = 0;
|
|
|
|
|
|
|
|
|
|
// First import users, then posts and finally comments
|
|
|
|
|
|
|
|
|
|
$data = $this->remoteUsersConvertor->convert($this->remoteUsers->getUsers());
|
|
|
|
|
|
|
|
|
|
$code = $this->runGeneratorInTransaction($data, function (User $user) {
|
|
|
|
|
$this->logger->info("Processing user: {$user->id}");
|
|
|
|
|
$this->em->persist($user->address);
|
|
|
|
|
$this->em->persist($user->company);
|
|
|
|
|
$this->em->persist($user);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if ($code != 0) {
|
|
|
|
|
$returnCode = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$data = $this->remotePostsConvertor->convert($this->remotePosts->getPosts());
|
|
|
|
|
|
|
|
|
|
$code = $this->runGeneratorInTransaction($data, function (Post $post) {
|
|
|
|
|
$this->logger->info("Processing post: {$post->id}");
|
|
|
|
|
$this->em->persist($post);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if ($code != 0) {
|
|
|
|
|
$returnCode = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$data = $this->remoteCommentsConvertor->convert($this->remoteComments->getComments());
|
|
|
|
|
|
|
|
|
|
$code = $this->runGeneratorInTransaction($data, function (Comment $comment) {
|
|
|
|
|
$this->logger->info("Processing comment: {$comment->id}");
|
|
|
|
|
$this->em->persist($comment);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if ($code != 0) {
|
|
|
|
|
$returnCode = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->companyRepository->deleteOrphanRecords();
|
|
|
|
|
$this->logger->info("Refreshing database completed");
|
|
|
|
|
return $returnCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Run every yielded item from generator in separate transaction and call $callback with item from generator
|
|
|
|
|
* @param \Generator $data
|
|
|
|
|
* @param callable $callback
|
|
|
|
|
* @return int
|
|
|
|
|
*/
|
|
|
|
|
private function runGeneratorInTransaction(\Generator $data, callable $callback): int
|
|
|
|
|
{
|
|
|
|
|
$returnCode = 0;
|
|
|
|
|
|
|
|
|
|
while ($data->valid()) { /* normalni foreach nepouzivam kvuli microtranskaci ...
|
|
|
|
|
v tomhle pripade mi prijde lepsi mit v databazi neco nez nic (nebo stara data) v pripade jakekoliv chyby,
|
|
|
|
|
navic "velke" transkace nejsou dobre pro databazi a tohle je api 3-ti strany...
|
|
|
|
|
ale finalni slovo by mel mit zadavatel, ktereho "nemam" */
|
|
|
|
|
$this->em->beginTransaction();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$callback($data->current());
|
|
|
|
|
$this->em->flush();
|
|
|
|
|
$this->em->commit();
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
$returnCode = 1;
|
|
|
|
|
$this->em->rollback();
|
|
|
|
|
$this->logger->error("Database transaction failed", ['exception' => $e]);
|
|
|
|
|
continue;
|
|
|
|
|
} finally {
|
|
|
|
|
$data->next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $returnCode;
|
|
|
|
|
}
|
|
|
|
|
}
|