Несколько окон с одним идентификатором: как получаются и как бороться

mars37

Новичок
Несколько окон с одним идентификатором: как получаются и как бороться

Когда java-script создаёт окно методом window.open(url, id, params), и этот-же браузер с той-же сессионной кукой уже создал окно с таким-же id, то новый экземпляр окна не создаётся, правильно? Возвращается ид уже созданного окна.
Например есть два окна, открытых в рамках одной сессии. Одно окно выполняет код:
var my_win = window.open(myurl, "mywin_168", params);
my_win.focus();
Появляется новое окно. Дальше пользователь что-то делает, и затем второе окно выполняет точно-такой-же код. Новое окно не появляется, "всплывает" уже созданное. И это правильно, это гуд.

Но почему-то у пользователей изредка стало открываться по 2 а иногда и больше окон в одной сессии, и с одним id!
Запросы от этих вновь созданных окон приходят на сервер в одну секунду.

Вопрос: как такое вообще возможно? Локально я пытался по разному смоделировать ситуацию, открывал кучу окон, извращался по всякому... Но открыть два окна с одним id, одним видом браузера у меня получается только с разными сессионными куками.
И "зависимый" от предыдущего вопрос: как с этим бороться?
 

ksnk

прохожий
Но открыть два окна с одним id, одним видом браузера у меня получается только с разными сессионными куками
Вот и ответ! Ушлые юзеры сидят не двигаясь и не дыша до полного пропадания сессионной куки (минут 10-20), а потом злорадно нажимают "Исчо окно..."
 

mars37

Новичок
Нет. Прежде чем написать здесь вопрос, я убедился неоднократно, что запросы идут в рамках одной сессии. Сессионные куки одинаковые. Предыдущие запросы по времени недалеко.
 

dimagolov

Новичок
mars37, как у тебя В РЕАЛЬНОСТИ формируется 2-й параметр для window.open?
 

mars37

Новичок
Открываемые окна - это окна support-чата для пользователей.
Приходит ajax-команда "открой окно чата для визитёра с номером (идентификатором) NNN". Фактически вызывается js-функция с одним параметром - visiter_id. Она и делает:

var WindowName = 'admchat'+visiter_id;
window.open("http://domain.com/admchat.php?visiter_id="+visiter_id, WindowName, params);

Скрипт http://domain.com/admchat.php отдаёт окно чата, причём title этого окна жёстко связан с get-параметром visiter_id, так что даже визуально, по title можно судить об ид. окон.
Т.е. например, пришла команда открыть окно для визитёра 6180. Ид. окна будет admchat6180, и полученный контент будет содержать "<title>Visitor 6180</title>".
Проблема как раз в том, что у саппорта иногда, ИЗРЕДКА открывается по несколько окон с одним заголовком, и с одной и той-же перепиской. Все запросы от двойных окон, которые удалось отследить - в одну секунду.
 

dimagolov

Новичок
начинай выяснять не почему два окна открывается, а почему два запроса идентичных шлется.

потому что два окна видать от того, что содержимое его не успело загрузиться и, видимо, это мешает броузеру перегрузить его содержимое вместо открытия нового.
 

mars37

Новичок
Автор оригинала: dimagolov
начинай выяснять не почему два окна открывается, а почему два запроса идентичных шлется.
Тут-то ничего загадочного нет. Два идентичных запроса идут как раз от этих двойных окон. Они-же запрашивают один и тот-же url.
Работники саппорта открывают при своей работе несколько окон, каждое из них периодически запрашивает у сервера наличие новых сообщений. На сервере: если сообщение от нового человека, то в сессию пишется признак, что этот visiter_id "в общении", и посылается та самая команда "открыть окно чата для visiter_id". Если в сессии уже есть visiter_id, то команда на открытие чата не посылается.
Но всё-же иногда перед тем, как скрипт определил, что человек новый, и записал в сессию его ид, другой скрипт может сделать то-же самое. Поэтому окнам браузера могут уходить дублирующиеся команды открытия. Но дело-то не в этом!
Если даже ВСЕГДА слать команду открытия окна чата, двойных окон не возникает, просто окно перегружается часто, что неприятно. Но двойных окон не возникает от таких двойных команд. Однин экземпляр браузера создаст окно, другое его использует. Обычно. Но изредка почему-то создаётся новое окно-дубль. "Изредка" - это примерно раз в сутки-двое.

Локально я пробовал смоделировать открытие таких двойных окон. Я специально слал одновременно (насколько мог одновременно) запросы на открытие, держал открытыми по 20 админ-окон браузеров, чат-боты пачками слали сообщения ... словом извращался по всякому. Но двойных окон не получалось ни разу! Интересно, как вообще можно такое сделать?
Придумайте способ в одной сессии открыть два окна с одним ид!
 

mars37

Новичок
Автор оригинала: Mols
А какой браузер это делает?
Что "это"? Двойные окна? Они наблюдались в разных FireFox 3.xxxxx
Но это возможно только потому, что саппорт работает в этих браузерах. Если бы они работали в IE, возможно двойные окна возникали бы и там. А может нет...
 

Mols

Новичок
Ну конечно "это" = двойные окна)) Проблема же вроде в этом.

И .... двойные онка кто-нибудь видел? глазами я имею в виду... а не по запросам на сервер.
 

dimagolov

Новичок
mars37, я вообще нифига не понял теперь.
1. при чем тут сессия вообще? в имя окна пишется visitor_id, а не она. id сессии пиши себе в лог, чтобы отловить момент, что сессионная кука не передалась и сессия стартовала по-новому
2. не понял зачем сервер посылает запрос на открытие клиентом окна. обычно все наоборот - клиенту нужен чат с посетителем, он запрашивает данные для чата у сервера и по setInterval дергает сервер на предмет обновлений. а раз это отдельное окно то это даже может быть тупая ссылка с id клиента в url и target=visitor_id, которая откроет окошко без вмешательства JS-а.

-~{}~ 03.02.09 08:19:

стоп. это часом не mod_rewrite и не favicon ли запрашивается при открытии окошка, а реврайт его кидет "не туда"?
 

mars37

Новичок
Автор оригинала: Mols
А есть уверенность, что это происходит именно в ФФ?
И ещё. Посмотрите как в "этом" случае передаётся идентификатор сессии? В адресной строке или нет?
И .... двойные онка кто-нибудь видел? глазами я имею в виду... а не по запросам на сервер.
Двойные окна конечно видели. Саппорт жалуется на них. Присылали скриншоты, там они видны, видна адресная строка, заголовок, серверное время, содержание переписки. На сервере есть табличка, куда записываются все хиты. Там есть поле, куда пишется дебажная инфа. И там виден и ид. сессии, и теперь куки, и сами сессионные данные. Была версия, что "срывается" сессия, после этого в get-запросе стали передавать и ид. сессии. Так вот sid в куках, в адресной строке, и записанный непосредственно с помощью session_id, - все они совпадают. Сессия одна. И то, что происходит это в FireFox - точно: видно и на скриншотах, и user_agent в серверной табличке соответствующий.

Автор оригинала: dimagolov
1. при чем тут сессия вообще? в имя окна пишется visitor_id, а не она. id сессии пиши себе в лог, чтобы отловить момент, что сессионная кука не передалась и сессия стартовала по-новому
Сессия может и совсем не при чём. Просто представления не имею, как получаются окна с одним ид, и это получалось у меня локально сделать только при разных сессиях. Но, как я уже написал выше, у саппорта двойные окна появляются в рамках одной сессии.

Автор оригинала: dimagolov
не понял зачем сервер посылает запрос на открытие клиентом окна. обычно все наоборот - клиенту нужен чат с посетителем, он запрашивает данные для чата у сервера и по setInterval дергает сервер на предмет обновлений.
Это support-чат. Посетители некоторого сайта конечно сами начинают чат. Я говорю о стороне саппорта. Саппорт работает в админке, и когда кто-то из посетителей сайта отправит сообщение, у выбранного сервером работника саппорта должно появиться окно переписки с этим клиентом. Саппорт естественно работает не с одним окном админки, а окно чата должно всплыть только одно для одного человека - посетителя. Что успешно и работает. Но изредка вместо одного окна появляется два, а иногда и больше. Были скриншоты с тремя и даже один раз с пятью окнами!
Можно конечно просто закрыть все окна кроме одного, обновить оставшееся и дальше работать. Но это "не есть хорошо".
 

dimagolov

Новичок
mars37, ну сервер же не может ничего послать суппорту так? то есть JS на стороне суппорта периодически опрашивает сервер "а нет ли кастомеров для чата". Так?
Раз так, то список "вакантных" кастомеров ты кладешь в БД, пишешь хранимую процедуру, которая:
1. выбирает кастомера из "вакантных"
2. прописывает в строчку клиента ID суппорта, которому пошлется кастомер и время запроса.
Процедура выполняется в транзакции, чем гарантируется то, что два суппорта не получат одного и того же кастомера.
После чего ID кастомера отправляется суппорту и уже броузер суппорта запрашивает окно чата с кастомером с полученным ID. Вот в этот момент сервер берет и прибивает запись из базы вакантных кастомеров, но только если ID суппорта совпало с тем, что в базе, если нет (или запись отсутствовала) - отлуп. Время нужно чтобы в случае нежданной кончины суппорта очистить блокировку с кастомера и как резултат он перекинется другому суппорту (делается по крону).
Одновременно можно писать пару суппорт-кастомер в таблицу активных чатов, чтобы там перекидывать кастомера на другого суппорта если текущий пропал.

Это как бы я делал такое, если у тебя не хватает где-то блокировок, то добавь.

Но все-таки мне кажется, что проблема твоя в JS. Что ты переустанавливаешь setTimeout вместо использования setInterval и в какой-то момент появляется дублирующая нитка опроса сервера, очевидно, что это связано с какими-то манипуляциями интерфейсом суппорта. Довольно гнилая ошибка, зачастую может никак визуально не проявлятся, но скорее всего приводит к memory leak, так как кол-во ниток может рости неограниченно (сам же видел 5 окон, то есть можно предполагать 5 ниток)
 

mars37

Новичок
Много написано :)
Всё нормально на стороне сервера, поверьте. И процедура выбора саппорта из доступных, и переброс другому, если первый "отвалился", и список активных разговоров. И проблема действительно на стороне JS. Т.к. повторюсь, даже если убрать вышеперечисленные механизмы, если каждый раз слать команду на открытие чата(!!!) двойных окон не наблюдается, просто окно чата перегружается, что неприятно, и неудобно саппорту, если он там уже пишет сообщение. Но нет двойных окон.

А насчёт SetInterval Вы не правы :) Мало ли какая связь, как долго будет браузер дожидаться ответа сервера.
Я делаю setTimeout, а в процедуре, которая запускается по таймеру, делаю:
clearTimeout, потом обработка, а потом опять setTimeout.

Т опять-же проблема не в этом. Все открываемые окна-дубли порождены разными окнами админки, но в пределах одной сессии.
 

dimagolov

Новичок
ответь на простой вопрос. запросы, после которых происходит открытие "двойных" окон (то есть не запросы содержимого самих окон, коню понятно, что они в дубле) тоже дублируются? если да, то они дублируются только при возникновении "двойных" окон или дублируются в принципе, только временами дают визуальный эфект "двойных" окон?

п.с. дублируются, это идентичные запросы от одного суппорта в одну и ту же секунду.
 

mars37

Новичок
Запросы "дублируются в принципе" :)
Т.е. если открыто одно окно админки у саппорта, запросы не накладываются друг на друга. Но саппорт при работе открывает несколько окон, запросы от них идентичные и в принципе могут идти секунда-в- секунду. Ответ сервера может в принципе прийти одинаковый этим окнам. И этот ответ может содержать js-команды на открытие окна чата. Но, как я писал выше, это само по себе не вызывает открытия двойных окон, происходит только перегрузка окна. Это я моделировал локально.
 

dimagolov

Новичок
Тебе было бы намного проще, если бы ты порождал все окна одним предком, то есть чтобы была одна главная страница, которая бы общалась с сервером и подчиненные, которые бы брали данные у главной.

Кстати, совсем не обязательно чтобы все порождались главной. хрен с ним, пусть открывают как попало, но давай каждой уникальный идентификатор и всю деятельность по опросу сервера пусть ведется в одной из них (в ней лови onunload или просто перекидывай главную на любую другую если главная пропустила, скажем, 3 цикла опроса сервера).
...
п.с. в этом абзаце слегка упустил, как остальные будут находить главное окно... значит так не получится

п.п.с. От повторного исполнения JS кода такие неприятные и трудно ловимые глюки получаются, что пипец. Если, конечно, у тебя код не представляет собой набор чистых функционалов :)
 

mars37

Новичок
Конечно, если можно было бы сделать одно "главное" окно, проблем таких не было бы :)

Проблема двойных окон возникает не из за "повторного выполнения js", а когда несколько окон одновременно пытаются создать окно с одним id. Чаще всего всё проходит нормально, но иногда...

Было бы проще, если бы удалось как-то съимитировать эту ситуацию, сделать её повторяемой...

Сейчас проверяю гипотезу, что возможность возникновения двойных окон зависит также от того, что открыло окно, т.е. от window.opener
 

Mols

Новичок
эм... ну в общем это не совсем по теме... Но может посмотреть немного в другую сторону? можно же "спрашивать" с сервера эти же данные о ожидающих юзерах, но не открывать стразу окно, а рисовать какую-нибудь мигающую ссылку. Кликнув на которую саппорт откроет окно. и вроде как норм. можно ещё и секундомер повесить рядом... типа если саппорт долго не "отвечает" - тогда что нить делать.
 

mars37

Новичок
Да, насчёт вывешивания мигающих ссылок уже была мысль... Предложу...
 
Сверху