我需要频繁地执行Symfony命令(比如每5-10秒),但是我的运行环境限制了cron触发的最低时间为1分钟。所以,我想出了一个非常讨厌的解决方案,看起来像这样。我已经创建了 AbstractRepetitiveCommand
类,然后我对其进行了扩展,提供了对 workToExecute
的方法。
abstract class AbstractRepetitiveCommand extends Command
{
protected int $overallMinutes = 1;
protected int $timesPerMinute = 60;
protected function execute(InputInterface $input, OutputInterface $output)
{
$startTime = microtime(true);
while (microtime(true) < $startTime + 60 * $this->overallMinutes - 60 / $this->timesPerMinute) {
if (isset($last) && microtime(true) < $last + 60 / $this->timesPerMinute) {
continue;
}
$last = microtime(true);
$this->workToExecute($input, $output);
}
}
protected function workToExecute(InputInterface $input, OutputInterface $output)
{
return;
}
}
class DoChecksCommand extends AbstractRepetitiveCommand
{
protected int $overallMinutes = 5;
protected int $timePerMinute = 4;
protected static $defaultName = 'checks:do';
/**
* @var InvestmentCheckerService
*/
private InvestmentCheckerService $checkerService;
/**
* @var EntityManagerInterface
*/
private EntityManagerInterface $entityManager;
public function __construct(InvestmentCheckerService $checkerService, EntityManagerInterface $entityManager)
{
parent::__construct('DoChecks');
$this->checkerService = $checkerService;
$this->entityManager = $entityManager;
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @throws \Exception
*/
protected function workToExecute(InputInterface $input, OutputInterface $output)
{
/** @var ArrayCollection | Pair[] $pairs */
$pairs = $this->entityManager->getRepository(Pair::class)->findAll();
foreach ($pairs as $pair) {
$this->checkerService->processChecks($pair);
$this->entityManager->persist($pair);
$this->entityManager->flush();
}
}
}
这种方法有两个问题。
目前我已经尝试使用 clear()
方式 EntityManager
在每个循环的开始,但它没有任何改变。 我想过关闭连接,但又看不到关闭后有什么简单的方法可以重新连接。 谢谢你的帮助。
目前,我已经尝试在每个循环的开始使用EntityManager的clear()方法,但它没有任何改变。
这正是你需要做的。当EntityManager被清空后,Doctrine会发出数据库查询来获取新的数据,所以你在其他命令请求中所做的任何改变都会对你有用。唯一不会是真的情况是未关闭的事务,但我看到你的代码中没有明确的事务,所以一切都应该是好的。