Мы реализуем длинный опрос в нашем приложении Symfony, поэтому controller1 обновляет некоторый член экземпляра класса User
$dm = $this->get('doctrine_mongodb')->getManager();
...
$User->setSomeValue($value);
$dm->persist($User);
$dm->flush();
Другой контроллер2, который содержит длинный цикл опроса первым
извлекает $ user и значение из базы данных, затем с некоторым интервалом
выполняет $ dm-> refresh ($ User) и извлекает значение.
$dm = $this->get('doctrine_mongodb')->getManager();
...
$User=$userRepo->findOneBy(array('id' => $userId));
$value = $User->getSomeValue();
...
while(...){
sleep(1);
$iteration++;
$dm->refresh($User);
$value = $User->getSomeValue();
...
}
Если controller1 обновляет значение во время выполнения цикла, старое значение выбирается контроллером 2 внутри цикла, но не обновляется.
В чем проблема?
Я не могу воспроизвести проблему, которую вы описываете, с помощью следующих сценариев CLI. Они смоделированы после tools/sandbox/index.php
пример (включен в репозиторий ODM) и выполняются из того же каталога.
Первый сценарий, poll.php
, обновляет конкретный документ раз в секунду и печатает строковое поле:
<?php
require_once __DIR__ . '/config.php';
$id = new MongoId('5432e4e6e84df199228b4567');
$repo = $dm->getRepository('Documents\User');
$user = $repo->findOneBy(['_id' => $id]);
$iteration = 0;
printf("%d: %s\n", $iteration, $user->getUsername());
poll: {
sleep(1);
$iteration++;
$dm->refresh($user);
printf("%d: %s\n", $iteration, $user->getUsername());
}
goto poll;
Второй сценарий, modify.php
, изменяет поле того же документа на случайную строку.
<?php
require_once __DIR__ . '/config.php';
use Documents\User;
$id = new MongoId('5432e4e6e84df199228b4567');
$user = new User();
$user->setId($id);
$user->setUsername(md5(rand()));
$dm->persist($user);
$dm->flush();
printf("Changed username to: %s\n", $user->getUsername());
Я сделал одно небольшое изменение в tools/sandbox/Documents/User.php
модель и добавил setId()
метод. Это позволяет modify.php
скрипт для выполнения upsert при первом запуске и создания документа, который мы позже изменим.
С этими двумя файлами я начал с создания документа:
$ php modify.php
Changed username to: 9bdfab05b06306e97d2f63c9bc0a34ef
Я тогда начал poll.php
во втором терминале и приступил к запуску modify.php
несколько раз:
$ php poll.php
0: 9bdfab05b06306e97d2f63c9bc0a34ef
1: 9bdfab05b06306e97d2f63c9bc0a34ef
2: 8420c8ef0ee7194624fead56585e8be5
3: 8420c8ef0ee7194624fead56585e8be5
4: bf2ec4bafae4cf47e3162ce857e861e7
5: bf2ec4bafae4cf47e3162ce857e861e7
6: bf2ec4bafae4cf47e3162ce857e861e7
7: 2051dd54bc2883f6c11e6c2bbfdfd13e
8: 2051dd54bc2883f6c11e6c2bbfdfd13e
9: 2051dd54bc2883f6c11e6c2bbfdfd13e
Если вы отслеживаете звонки внутри DocumentManager::refresh()
вы увидите, что это в конечном итоге вызывает DocumentPersister::refresh()
, который очень просто запрашивает необработанные данные документа через Doctrine\MongoDB\Collection
класс-обертка, гидратирует эти данные и сбрасывает исходные данные документа (используется для вычисления набора изменений). Отладка необработанных данных (из MongoDB), которые гидратируются и переназначаются для моментального снимка, было бы хорошим началом, если вы не видите новые данные.
Других решений пока нет …