Рабочая функция php gearman не синхронизирована с доктриной

Я заметил странное поведение моего объекта доктрины. В моем проекте Symfony я использую ORM с доктриной для сохранения своих данных в базе данных mysql. Это нормально работает в большинстве ситуаций. Я также использую gearman в своем проекте, это фреймворк, который позволяет приложениям выполнять задачи параллельно. У меня есть сервер заданий Gearman, работающий на той же машине, где также работает мой Apache, и я зарегистрировал работника Gearman. на той же машине в отдельном сеансе screen с помощью оконного менеджера screen. По этому методу у меня всегда есть доступ к штатной консоли из функции, прописанной для шестерёнки-рабочей.

В функции gearman-worker, которую я вызываю, у меня есть доступ к объекту доктрины через $doctrine = $this->getContainer()->get('doctrine'), и он работает почти нормально. Но когда я изменил некоторые данные в своей базе данных, доктрина продолжает использовать старые данные, которые ранее хранились в базе данных. Я полностью сбит с толку, потому что ожидал этого, позвонив:

$repo = $doctrine->getRepository("PackageManagerBundle:myRepo"); $dbElement = $repo->findOneById($Id);

Я всегда получаю текущие записи данных из моей базы данных. Это похоже на странное поведение кэширования, но я понятия не имею, что я сделал не так.

Я могу решить эту проблему, зарегистрировав рабочего механизма и новую функцию:

$worker = new \GearmanWorker(); $worker->addServer(); $worker->addFunction

После этого я вернул текущее состояние моей базы данных, пока не изменю что-то еще. Я наблюдаю такое поведение только в моей рабочей функции Gearman. В остальном приложение все синхронизируется с моей базой данных и нормально.


person Ole    schedule 21.05.2018    source источник
comment
попробуйте обновить ссылку на объект перед его использованием, например $doctrine->refresh($object)   -  person Matteo    schedule 21.05.2018


Ответы (1)


Это то, что я думаю, может происходить. Хотя может ошибся.

Gearman worker будет длительным процессом, который подбирает работу для выполнения. Первое задание, которое он получит, приведет к тому, что доктрина загрузит сущность в свою карту объектов из базы данных. Но для второго задания, которое получает работник, доктрина не будет выполнять поиск в базе данных, вместо этого она проверит свою карту идентичности и обнаружит, что объект уже загружен, и поэтому просто вернет его из памяти. Если что-то еще, внешнее по отношению к рабочему процессу, изменило запись базы данных, вы получите устаревший объект.

Вы можете указать доктрине удалить объекты из своей карты идентификации, после чего она выполнит поиск в базе данных. Чтобы снова принудительно загрузить объекты из базы данных, а не обслуживать их из карты идентификаторов, вы должны использовать EntityManager#clear().

Подробнее здесь: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-objects.html#entities-and-the-identity-map< /а>

person Peter Belgrove    schedule 21.05.2018
comment
Спасибо большое, ваше предположение было правильным. Моя проблема была решена путем обновления объекта $repo с помощью функции clear(): $repo = $doctrine->getRepository(PackageManagerBundle:myRepo); $repo-›clear(); $dbElement = $repo-›findOneById($Id); - person Ole; 22.05.2018