如何在一个脚本执行期间多次刷新学说连接?

how to refresh doctrine connection multiple times during one script execution?


我需要非常频繁地执行 Symfony 命令(比如每 5-10 秒),但是我的 运行time 环境将 cron 触发的最短时间限制为 1 分钟。所以,我想出了一个非常糟糕的解决方案,看起来像这样。我已经创建了 AbstractRepetitiveCommand class,然后对其进行了扩展,提供了 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();
        }
    }
}

这种方法有两个问题:

  1. 当2个这样的命令同时运行时,它们不会 识别彼此通过 flush 所做的更改。有没有办法 刷新连接,所以每个 运行 数据都是从 数据库?
  2. 这个解决方案整体来说真的很难看。我大概 overthinking/overcomplicating 它,所以请告知您是否看到任何 更好地实现我想要实现的目标。

现在我尝试在每个循环开始时使用 EntityManagerclear() 方法,但它没有改变任何东西。
我考虑过关闭连接,但是我没有看到任何简单的方法可以在关闭后重新连接。
感谢您的帮助。

For now I've tried to use clear() method of EntityManager at the start of every loop but it didn't change anything.

这正是您需要做的。清除 EntityManager 后,Doctrine 将发出数据库查询以获取新数据,因此您在其他 commands/request 中所做的任何更改都将对您可用。唯一不真实的情况是未关闭的交易,但我在您的代码中没有看到明确的交易,所以一切都应该没问题。