Нет. В данном случае это интересует не изза того, что лень разбираться с кроном, или его отсутствия. И не интересует алгоритм реализующий приблизительно следующее: PHP: <?php set_time_limit (0); sleep(3600); // Выполнить через час Интересует алгоритм, напоминающий действия cron'а, а именно - запуск какого-то события в определенное время. Но время, событие и все с этим связанное должно определяться с помощью пхп-скрипта. При этом, оно должно работать независимо от наличия крона. И еще - эти события некритичны к времени. То есть, допустим, мы указываем событие и указываем, что оно должно выполниться в 2.00 ночи. Но нам не критично, чтобы это было в 2.00, главное, чтобы любой пользователь зашедший после 2 - увидел обработанный результат. Еще одно важное качество - гарантия того, что событие будет выполнено и событие будет выполнено только один раз. Может, чуть сумбурно объяснил, но думаю, на примере будет понятнее. Далее то, какой я вижу этот алгоритм. Есть таблица в базе: ID, Action, Status, Time, где Action - ссылка на событие, ну, например, какой-то аргумент для метода $eh = new EventRunner($row['Action']);, Status - tinyint поле (выполнено/выполняется/не выполнено), Time - время, когда событие нужно запустить Итак, пример. Мы хотим поздравить форумчан с Новым Годом в 00.00 1 января. Пишем сообщение "С Новым Годом всех!", ставим галочку "отправить 1 января в 00.00" и едем пить с президентом, или на речку - рыбу ловить. Стукнула полночь, наступил Новый Год, но движок пока спит. И вот в 00.27 его дёргает первый посетитель - какой то трезвенник хочет посмотреть, кто там что написал на форуме. Скрипт просыпается и смотрит: "ага. в 00.00 невыполненное событие" и выполняет его, словно оно было выполнено в полночь. Пользователь доволен - его поздравили ровно в полночь. Мне все нравится в этом алгоритме, но такие два момента. 1. Допустим в 12 часов будет большой наплыв посетителей . Первый вызов скрипта - получаются все незапущенные события с бд. Второй вызов скрипта - получаются все незапущенные события с бд (те же самые), только после этого первый скрипт закрывает доступ к запущенным событиям. Таким образом события выполнятся два раза. 2. Скрипт запущен, он блокирует нужные события, но тут происходит ребут сервера и, хотя события не выполнены - они находятся в статусе "выполняется". Каких два варианта я вижу: а) использовать таймаут для "выполняющегося" события. Если событие выполняется дольше чем, например, 30 секунд - попробовать выполнить его снова б) использовать блокировку таблиц / транзакции. Сердцем чую, что правильно использовать транзакции, но интересуют некоторые ньюансы. Если идет такая последовательность (в порядке запуска) 0. Скрипт 1 запущен 1. Скрипт 2 запущен 2. Скрипт 1 начал транзакцию 3. Скрипт 2 начал транзакцию 4. Скрипт 1 получил нужные события 5. Скрипт 2 получил нужные события 6. Скрипт 1 пометил события события как "выполняющиеся" 7. Скрипт 2 пометил события события как "выполняющиеся" ? 8. Скрипт 1 закончил транзакцию 9. Скрипт 2 закончил транзакцию Транзакция в строке 3 начнется после окончания транзакции в строке 8, или сразу же за первой? Получит ли в таком случае скрипт 2 в строке 5 события, которые скрипт 1 пометит как "выполняющиеся" в строке 6? Ну и вообще - ваше мнение по поводу данного алгоритма и предложения
Как упал? =) Локнет таблицу, проапдейтит и упадет? Но тогда другой скрипт, запущеный синхронно разлокнет тэйблы и будет таков =)
ну сервер ребутнули, или электричество выключили, или критический непойманный notice случайно вылез в скрипте. Ну всякое может быть. А таблицы локнулись.
смотри. один скрипт лочит таблицу, выполняет апдейт и тут падает. таблица залочена. все остальные скрипты встают в очередь в ожидании, пока таблицу разлочат. не?
Вообще, по мне использование транзакций самый оптимальный вариант, они, в конце концов, ради этого и придуманы. Как с анлоком таблица дела обстоят — честно не знаю как ведет себя скрипт, поскольку использовал это только в целях обучения, а в реальных проектах — транзакции. Можно это и на файлах ведь делать: fopen, flock
дык я ничего против транзакций не имею. просто не уверен, что они поведут себя как я ожидаю. потому и спрашиваю - каким алгоритмов воспользоваться правильнее всего.
Кстати, буквально сейчас я работаю над заказом скрипта для типографии, которая оптом продаёт разные открытки. Так вот у них есть разные праздники, и открытки для этих праздников в период этого праздника продаются со скидкой. Заказчит вводит период праздника и в этот период должно всё измениться: дизайн, цены, ... Практически подобная запланированность событий реализовывается при переходе от одного периода к другому: переключение может произойти только один раз и текущий праздник выбирается помеченым. =) Сделано простым транзакционным апдейтом текущих файлов шабов и конфигов (flock).
и еще вот вопрос: можно ли как-то узнать - занята ли определенная таблица? выполняются ли над ней транзакции, или заблокирована она. в данном случае достаточно проверить - занята ли и не ждать освобождения. если занята - значит все события до данного момента выполнятся и можно не ждать окончания работы с этой таблицой, а действовать себе дальше.
У меня когда-то так было сделано. Скрипт выбирает события, которые ещё не в обработке. Делает апдейт и помимо статуса обработки записывает свой id. Сразу после этого делает селект и сверяет id со своим. Если они равны, значит никто не успел вклиниться и можно обрабатывать события. В этом случае придётся использоваться таймаут, чтобы зависшие события обрабатывать.
Скрипт 1 получает данные Скрипт 2 получает данные Скрипт 1 делает апдейт Скрипт 1 проверяет, не сделал ли кто апдейт Скрипт 2 делает апдейт Скрипт 2 проверяет, не сделал ли кто апдейт. Хотя действительно. Апдейт можно делать только для тех, кому еще апдейт не сделан. Тут даже без транзакций обойдется.
Да. Апдейт таким запросом делался. PHP: <?php $query = ' UPDATE feeds SET processed = 1, procid = ' . $pid . ', updated = UNIX_TIMESTAMP() WHERE id = ' . $feed['id'] . ' AND processed = 0 ';
kas1e, что значит "выполняющиеся без умолку"? DeferredEvent при вызове родится, выполнится и умрет и для всех хостеров они совершенно неотличимы от всех остальных скриптов, таких как viewtopic.php на этом форуме, или что-либо другое. Более того, оно плавно встраивается в viewtopic.php, viewforum.php, index.php и во все-все остальное работая совершенно незаметно для остальных.
хз, когда клепал аско-бота(там был слип и цикл, крутящийся до получения команды завершения работы) - процесс вроде висел постоянно.
kas1e, дык в том же и суть этой идеи, чтобы отказаться от слип и цикла, о чем я и указал в начале этой темы.
Не, транзакции тут совсем не к тому месту, это именно локи. Можно ставить флаг у каждой задачи - "взята на исполнение" и дата... а еще можно pid процесса, что бы тот, кто задачу взял по таймауту - послал kill этому задумчивому =) Остальные процессы читают задачи, и если там есть залоченные к выполнению - определяют через сколько можно задачу "перехватывать", добавляют сколько-то микросекунд рандомно против коллизий и засыпают. После просыпания есть 2 варианта - снова все проверить и попытаться перехватить задачу, но это не очень хорошо, ибо процесс и так уже ждал лока, а еще ему потенциально поломанную задачу на себя брать. В общем, черевато затыком системы. Так что лучше просто продолжать работу. Пользователь увидит старые данные, но зато хоть что-то увидит, а не нажмет стоп и уйдет. Перехват задачи можно сделать свежим процессом, который увидев, что залоченная задача повисла - перехватывает ее, киляет старого исполнителя и приступает к исполнению. Вообще, спорный момент, ибо такое вот "зависание" может быть как от падения исполнителя, так и от незапланированной тяжести задачи (мало ли что там захотели, мож кино скачать). От вечных килов можно защититься сделав лок - каунтером, и каждый перехват - увеличивая его. Тогда очередная задача, увидев что уже 3 другие пытались это сделать - не будет пытаться. Но все-равно, в случае фильма - убить 2 попытки и только на 3-ю отработать - не очень хорошо. Нужно думать... возможно, задача должна делать постоянный апдейт о том, жива ли она. В общем, написать свой крон ой как не просто, по-этому я за крон =)
MiksIr, ты уже опоздал. Я уже написал и написал без крона. И зачем может быть нужно скачать фильм с помощью этого - я не представляю.
фильм скачать.. Я так игры качал в свое время с Инфостора. У провайдера был UA-IX на хорошей скорости. А я админил у него же игровой архив. На сайт поставил скрипт и понеслась. Правда там до крона доступа у меня не было, был демон висящий
TheShock - ну написал, и что? Все в молодости ошибки делали. Фильм, не фильм - тебя как разработчика системы не должно волновать "зачем", а должно "а как это будет работать в той или иной ситуации".