Имеем:
Код, работающий с библиотекой facebook-php-webdriver. Работаем в много потоков, потоки друг о друге кое-что знают, но пока что предполагаем, что они не знают ничего.
Виртуальные машины, на которых запущен
Selenium (на Java, последняя версия) +
chrome-webdriver (нужная для текущей версии браузера версия) и на которые наш код ходит с запросами посетить те или иные страницы и сделать там те или иные действия.
Профили для браузера
Google Chrome, настроенные для тех или иных специфичных задач.
Ситуация:
Есть вариант, что на одну виртуальную машину в один и тот же браузер в один и тот же профиль (это важно!) придет сначала один экземпляр нашего кода с тем или иным запросом. И он там что-то попытается сделать. В этот момент может произойти две вещи: либо произошла некая ошибка работы браузера (или чего угодно еще), либо просто наш браузер просто еще не выполнил некую задачу, которую мы ему поставили.
И так или иначе мы получаем одну и ту же ситуацию - у нас есть уже открытый профиль браузера, с открытым в нем неким окном, а в нем некоей страницей. И тут к нам приходит второй экземпляр кода, который хочет в том же профиле открыть некую страницу и что-то там сделать.
Проблема:
При описанной ситуации,
webdriver не понимает, что делать, и ведет себя деструктивно, а именно открывает три раза пустую вкладку, после чего наш php-экземпляр кода сыпется с ошибкой, что не удалось запустить сессию и все такое. В итоге, как только у нас случается такая ситуация, работа с профилем просто замораживается, до вмешательства живого человека.
Уточнение:
Нам не нужно пробовать решить описанную проблему php-кодом. Понятно, что можно сделать балансировщик, который будет ограничивать работу с профилями на уровне запуска экземпляров кода, выдавая право на тот или иной "по-одному", но пока что интересны только нативные решения.
Что ищется:
Вариант, когда можно указать
Selenium'у (webdriver'у?), что нужно подвешивать очередной запрос к профилю браузера для того, чтобы он успел его обработать, и только тогда посылать очередной запрос в дело.
Получить список активных профилей / сессий, чтобы потом их как-то обработать. Сейчас мы можем получить сессию (sessionId) только после того, как у нас прошел момент создания вебдрайвера, а он не создается как раз в том случае, если в профиле уже открыто то или иное окно.
Пример кода:
который итоге не умеет работать дважды (если его запустят дважды разные процессы):
$caps = DesiredCapabilities::chrome();
$chrome_options = new ChromeOptions();
$chrome_options->addArguments([
"--user-data-dir=$user_data_dir",
"--profile-directory=$profile",
]);
$caps->setCapability(ChromeOptions::CAPABILITY, $chrome_options);
// Вот здесь, если у нас уже как и написано выше в $caps установлено
// использование определенного профиля браузера, мы не сможем еще раз
// подключиться к нему, все это вызовет описанное выше поведение
// браузера и вебдрайвера
$this->webdriver = RemoteWebDriver::create(
$service_url,
$caps,
$connection_timeout * 1000,
$request_timeout * 1000
);
return $this->webdriver->getSessionID();
PS: да, я знаю, что
подобный функционал уже когда-то запрашивался в seleniumhq и был отклонен. Но, возможно, есть какие-то обходные пути решить эту проблему. Заодно, если кому-то не слишком понятен вопрос и есть желание углубиться, по ссылке можно найти недостающую информацию.