Особенности приготовления PtokaX, Некоторые особенности работы скриптов на данном хабе |
Здравствуйте, гость ( Вход | Регистрация )
Особенности приготовления PtokaX, Некоторые особенности работы скриптов на данном хабе |
19.1.2012, 2:36
Сообщение
#1
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Итак. Вводная:
HubVersion = 0.4.1.1 LuaVersion = Lua 5.1 OS = Windows_NT Теперь по порядку.
Думаю эта информция будет не лишней для разработчиков скриптов. |
|
|
22.1.2012, 22:58
Сообщение
#2
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Продолжая тему. Предлагаю вашему вниманию простой скрипт:
Код local iCheckInterval = 1 function OnStartup() TmrMan.AddTimer(iCheckInterval, "CheckPtokaX") end function CheckPtokaX() local sReport = "" local iDelta = 0 local iCount = Core.GetUsersCount() local tUsers = Core.GetOnlineUsers() iDelta = iCount for _, _ in ipairs(tUsers) do iDelta = iDelta - 1 end if iDelta ~= 0 then sReport = sReport.."ipairs = "..iDelta.."\n" end iDelta = iCount for _, _ in pairs(tUsers) do iDelta = iDelta - 1 end if iDelta ~= 0 then sReport = sReport.."pairs = "..iDelta.."\n" end iDelta = iCount - #tUsers if iDelta ~= 0 then sReport = sReport.."# = "..iDelta.."\n" end if sReport ~= "" then Core.SendToOps(sReport) end end Суть проста, собрать всех пользователей через Core.GetOnlineUsers(), а потом сравнить число полученных пользователей с числом, возвращаемым Core.GetUsersCount(). Как уже было сказано, эти два числа не всегда могут быть одинаковыми. Но на одном хабе я обнаружил что второе количество (Core.GetUsersCount()) ПОСТОЯННО больше первого. "Постоянно" это значит, в рамках достаточно длительного интервала времени. Думаю что после старта хаба все нормально. |
|
|
23.1.2012, 9:09
Сообщение
#3
|
|
RusHub team lead Группа: Модераторы Сообщений: 4 030 Регистрация: 20.6.2008 Из: г. Королёв (Моск. обл.) Пользователь №: 46 Спасибо сказали: 1708 раз |
Тут всё дело в том, что функция Core.GetUsersCount() возвращает полностью вошедших юзеров, то есть тех, кто прошёл все стадии входа, в отличие от функции Core.GetOnlineUsers(), которая возвращает всех пользователей, даже тех, которые только входят (находятся на какой-то стадии входа).
Кстати, в русхабе для этого сделана такая фишка: Core.GetUsers() - таблица со всеми вошедшими пользователями хаба. Core.GetUsers(true) - таблица со всеми пользователями хаба, даже которые только входят и ещё не вошли. |
|
|
23.1.2012, 9:14
Сообщение
#4
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Нет.
Core.GetUsersCount() - возвращает общее число юзеров завершивших вход + число юзеров, находящихся на разных этапах входа. Core.GetOnlineUsers() - Возвращает "виртуальную" таблицу пользователей tAllUsers, в которой содержатся пользователи прошедшие процедуру входа. Фишка в том, что вызов UserConnected и подобных их функций происходит ДО завершения процедуры входа. После возврата из нее проходит некоторое время и только потом этот пользователь появляется в отдаче Core.GetOnlineUsers(). |
|
|
23.1.2012, 9:19
Сообщение
#5
|
|
RusHub team lead Группа: Модераторы Сообщений: 4 030 Регистрация: 20.6.2008 Из: г. Королёв (Моск. обл.) Пользователь №: 46 Спасибо сказали: 1708 раз |
Ну да, я это и имел ввиду. Только немного наоборот написал
|
|
|
23.1.2012, 11:13
Сообщение
#6
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Кстати, из этого следует:
К слову Disconnected функции вызываются ДО удаления этого пользователя из виртуальной таблицы tAllUsers. ADD: Провел дополнительные тесты. Все не так уж плохо, как кажется на первый взгляд. Все намного хуже. Итак. Процедура входа пользователя:
CallTimer означает что здесь успела вызваться функция таймера с минимальным интервалом. Если в это время будет запущена какая либо-функция, то в ее коде будет выполнятся следующее условие: Код #Core.GetOnlineUsers() ~= Core.GetUsersCount() Так что вношу поправку к предыдущему посту: Core.GetUsersCount() - возвращает общее число юзеров завершивших вход + число юзеров, находящихся на конечном этапе процедуры входа (после вызова Connected функции). ADD: Последствия вышесказанного: Используя код, наподобие: Код function OnStartup() for _, tUser in ipairs(Core.GetOnlineUsers()) do -- do something end end Вы рискуете потерять всех пользователей "находящихся на конечном этапе процедуры входа (после вызова Connected функции)", если ваш скрипт будет стартовать в какой-то из промежутков CallTimer. Для маленьких хабов это не особо актуально, но для больших хабов это проблема. И да, то что CallTimer у меня всего 7, это не значит что их не может быть больше или меньше. ADD: Еще одно дополнение. Если вызвать Core.Disconnect в UserConnected, то вызова UserDisconnected не будет! Общее утверждение: Пока не завершена процедура входа, юзер не считается вошедшим и для него не вызывается UserDisconnected. Теперь интересный момент. Это когда Core.Disconnect вызывается между Core.GetUsersCount = Core.GetUsersCount + 1 и table.insert(tAllUsers, tUser). Ничего криминального не происходит, однако UserDisconnected вызывается. После вызова выполняется: Core.GetUsersCount = Core.GetUsersCount - 1 и все живет как жило. |
|
|
23.1.2012, 16:40
Сообщение
#7
|
|
RusHub team lead Группа: Модераторы Сообщений: 4 030 Регистрация: 20.6.2008 Из: г. Королёв (Моск. обл.) Пользователь №: 46 Спасибо сказали: 1708 раз |
Итог - очень не удобно. И это далеко не все недостатки птохи
|
|
|
23.1.2012, 16:42
Сообщение
#8
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Теперь если посмотреть процедуру входа, то там будет такая картина:
|
|
|
28.1.2012, 23:13
Сообщение
#9
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Теперь немного о вещах, которые проистекают из вышеописанного.
Как уже было сказано, если выполняется отключение юзера, не важно сам он это сделал или скрипт, во время UserConnected, то UserDisconnected вызвано не будет. Это может создавать несовместимость скриптов. Допустим у нас есть два скрипта. Скрипт А - реализует защиту и выполняет какие-то проверки для пользователя в UserConnected. При не прохождении попытки вызывается Core.Disconnect. Скрипт Б - занимается чем-то с учетом ников пользователей. т. е. он содержит таблицу пользователей, пополняемую при входе и сокращаемую при выходе. Допустим у нас есть две версии этого скрипта: Б1 - выше А и Б2 - ниже А. Теперь рассмотрим ситуацию, когда пользователь будет отключен в скрипте А:
Обработка завершена. Оба скрипта и Б1 и Б2 имеют фейкового юзера, который был добавлен в таблицу, но которого нет на хабе. UserDisconnected для него вызвано не будет. Т. е. этому багу подвержены все скрипты, как выше, так и ниже отключающего скрипта А. |
|
|
28.1.2012, 23:22
Сообщение
#10
|
|
RusHub team lead Группа: Модераторы Сообщений: 4 030 Регистрация: 20.6.2008 Из: г. Королёв (Моск. обл.) Пользователь №: 46 Спасибо сказали: 1708 раз |
Могу ещё добавить до кучи, что возможен случай, когда при входе не будет выполняться скриптовая функция ValidateNickArrival.
Происходить это будет в том случае, если клиент поддерживает характеристику QuickList |
|
|
29.1.2012, 0:10
Сообщение
#11
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Кстати, насчет функций. KeyArrival не вызывается на Win версии, даже если в командной строке НЕ указано /nokeycheck. Пытался отследить это через исходники - ничего не нашел.
|
|
|
29.1.2012, 0:38
Сообщение
#12
|
|
RusHub team lead Группа: Модераторы Сообщений: 4 030 Регистрация: 20.6.2008 Из: г. Королёв (Моск. обл.) Пользователь №: 46 Спасибо сказали: 1708 раз |
Ага этот недочёт тянется ещё с ранних версий, то есть эта функция никогда не работала)))
|
|
|
29.1.2012, 9:07
Сообщение
#13
|
|
Белый Волк Группа: Пользователи Сообщений: 1 723 Регистрация: 11.9.2008 Из: г.Томск Пользователь №: 516 Спасибо сказали: 657 раз |
Цитата UserDisconnected для него вызвано не будет. Т. е. этому багу подвержены все скрипты, как выше, так и ниже отключающего скрипта А. Получается, что в скрипте А желательно после дисконнекта юзера провести операцию чистки таблицы юзеров хаба (попросту говоря, удалить юзера)? Это прокатит при случае, когда скрипт Б стоит выше. Но прокатит ли, когда он ниже? Не останется ли юзер в таблице, потому что в табицу занесёт скрипт Б? Тут же есть нюансы одновременности/неодновременности операций в разных скриптах при выполнении функции UserConnected или есть однозначный ответ? А ведь может быть больше одного скрипта, заносящего каких-то юзеров в свою таблицу по своим категориям, в которые может попасть юзер, скинутый скриптом А. Наверно, надо проверить это. PS: Кстати, я тоже замечал, что один скрипт скидывает юзера при входе (ну так ему велено по условию) и сообщает мне, а другой стоит ниже и мне тоже сообщает, что зашёл такой-то юзер (выполняется другое условие ). Хорошо, что я помню, что юзер уже скинут..Хотя вообще вначале я надеялся (ну логично же), что второй скрипт в таком случае уже не получит вхождение. |
|
|
29.1.2012, 11:37
Сообщение
#14
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Нет, юзера в таблице не будет. Между UserConnected и появлением юзера в списке пользователей происходит какое-то время, а если в каком-то скрипте вызвано Disconnect, во время того, как идет это время, или в коде UserConnected, то юзер вообще не появляется в общей таблице юзеров.
Когда я говорил что скрипты Б1 и Б2 заносят юзера в таблицу, я имел в виду занесение пользователей во внутренние таблицы этих скриптов. Они не доступны из скрипта А. так что там ничего сделать нельзя. и сделать скрипт А не подверженным этому багу можно только в одном случае - вызывать Disconnect, или до UserСonnected, или после, когда пользователь появится в общем списке пользователей. Реализацию можно сделать через таблицу ников которые нужно отключить и таймер, который получает таблицу со всеми юзерами и смотрит, есть ли там нужный ник, если есть, то скрипт его отключает. Для скриптов Б1 и Б2 нужно предусматривать свою защиту. У меня, например, в User Mode Fixer проверяется на соответствие число юзеров на хабе и число юзеров во внутренней таблице. Все это в таймере главного цикла. Если происходит расхождение этих двух чисел, то стартует очистка, все юзеры которые есть на хабе - добавляются ко мне, путем прямого вызова UserConnected для них, а все юзеры, которые есть у меня, но хаб на них возвращает nil, вместо таблицы пользователя - удаляются вызовом функции очистки. По хорошему там надо было бы вызвать UserDisconnected, но у меня нет таблицы юзера, которая нужна, чтобы передать в эту функцию (юзер то вышел уже). Насчет PS - в этом случае багу подвержены были бы все скрипты, находящиеся выше, отключающего скрипта. Что, конечно, лучше, чем все скрипты, но все равно не самая лучшая ситуация. Самым идеальным вариантом было бы сделать межскриптовое взаимодействие. Т. е. возможность передать из одного скрипта что-то другому, без завязки на внутреннюю архитектуру. ADD: Чтобы было понятнее работа скриптов сделал диаграмму. PtokaX.png ( 83.91 килобайт ) Кол-во скачиваний: 142 |
|
|
29.1.2012, 12:57
Сообщение
#15
|
|
RusHub team lead Группа: Модераторы Сообщений: 4 030 Регистрация: 20.6.2008 Из: г. Королёв (Моск. обл.) Пользователь №: 46 Спасибо сказали: 1708 раз |
А что за "обычная работа скрипта" ?
Это что-то непонятное, ибо все работы скриптов являются событийными, то есть порождаются каким-то событием. Там должна стоять просто внутренняя обработка безо всяких обычных работ скрипта. Или под обычной работой скрипта подразумевается работа таймерных функций? |
|
|
29.1.2012, 13:02
Сообщение
#16
|
|
Освоившийся участник Группа: Пользователи Сообщений: 391 Регистрация: 4.11.2009 Из: Дом Пользователь №: 4 923 Спасибо сказали: 239 раз |
Ну там таймеры и прочее. Если говорить в контексте данного пользователя, то это будут таймеры + Arrival'ы остальных команд данного пользователя.
Не захотел расписывать, ибо это не критично для рассматриваемой ситуации. ADD: Можно добавить туда блок "есть события?" -> "вызываем обработчиков событий скрипта" или что-то подобное. Имхо, это не важно в данном контексте. |
|
|
Похожие темы
|
Сейчас: 26.11.2024, 22:10 |