commit-jabber


После прочтения статьи о том, как в last.fm используют irc для логирования всего и вся тоже захотелось как-нибудь “выпендриться”.
Мониторить сервера нам ни к чему, да и irc – поди объясни сейчас что это такое и чем оно лучше _______. Но недавно выдалась свободная минутка и я нашёл куда приложить усилия.
Решил сделать post-commit хук в svn-репозитарии, который будет высылать детали о коммите, но не на почту, как это делается в традиционных скриптах, а в jabber (cам jabber достался нам вместе с почтой от гугла) .
По-моему получилось очень удобно и за несколько дней превратилось из игрушки в удобный инструмент для своевременного обновления и обнаружения “ну и зачем ты это сделал” :)

Собственно все внутренности состоят из библиотеки XMPPHP и маленького скриптика, который вешается на post-commit.
Сам скриптик настолько маленький и бесхитростный, что комментировать его не вижу смысла – кладу как есть.
Для функционирования нужно иметь xmpphp в include_path, бинарник svn в PATH и добавить post-commit hook в ваш репозитарий.

В сложнейшем, виндовом случае это будет post-commit.cmd, который лежит в директории hooks репозитария и имеет следующее содержание:

/path/to/php.exe /path/to/svnjabber.php %1 %2

24.02.09  |  , ,  | стань первым

ты не один

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

В рамках работ по выводу одного “неповоротливого асфальтоукладчика” на земную орбиту были проведены ряд его модернизаций. Испытания на тестовом полигоне показали что машина стала ездить на порядок быстрее и было решено доработки включить в работающий прототип(вроде и не первая космическая, но уже есть чем гордиться!). Но на первом же серьёзном показе зверь-машина с чудо{вищным} грохотом рассыпалась у всех на глазах и я сел в лужу…

А теперь тоже самое, но по-русски, с выражением.
Имеются ряд весьма тяжёлых для веба запросов к БД, результат которых условно не меняется в течении небольшого промежутка времени. Кеширование промежуточных результатов в самой БД нагрузку сняло на СУБД, но скрипты продолжали исправно тягать данные и это порой занимало внушительное время. Было решено результаты эти кешировать на стороне веб-сервера. Как хранилище был использован apc.

Первоначальный вариант выглядел примерно так:

if (!$data = cache_get($key)) {
   $data = data_from_db();
   cache_set($key,$data,$expire_time)
}

Без излишеств, просто и со вкусом. Но позже выснилось что “всё не так просто” и в зависимости от некоторых космических характеристик и результатов выборки из базы будет меняется ещё одна переменная (меняется переменная… ого!).

if (!$data = cache_get($key)) {
   $data = data_from_db();
   cache_set($key,$data,$expire_time);
   $other_data = some_function($data,$env);
   cache_set($other_key,$other_data,$expire_time);
} else {
   $other_data = cache_get($other_key);
}

Аляповато, но, чёрт возьми, работает…
Работало…
Должно было по идее работать…
Но, почему-то оказавшись на боевом, изрядно нагруженном, сервере это не сработало. Вернее это работало…, но не всё время… По истечении $expire_time периодически пропадали данные для $other_key. При отключении и/или очистке кеша работоспособность восстанавливалась… Кто виноват? Что делать? Кто за всё это ответит?!? Пришлось срочно пошевелить опилками.

Как мы все наверное догадываемся – реальный сервер обслуживает нереально много клиентов, причём не по очереди. И нет совершенно никаких гарантий на то, что между записью $key и $other_key не встрянет какой-либо маленький, но шустрый процесс (хотя нам это и не особо страшно), так же нет никаких оснований полагать что между выборкой $key и $other_key кто-то умный и большой не очистит кеш (целиком, или только $other_key – в данном эпизоде это не имеет значения).
Оснований не было, но я был почему-то твёрдо уверен, что “это если и происходит, то с кем-то другим”. С пониманием проблемы конечно же пришло и простое решение, но ошибка, согласитесь, совсем не тривиальная.

Так что мораль сей басни: помни – ты не один!

23.09.08  |   | стань первым

firebug для отладки серверного кода


За последние пару лет firebug стал стандартным инструментом для отладки клиентской части веб-приложений у большинства разработчиков.
Тем, у кого это не так – от души сочувствую ;o)
Но многие не догадываются, что с помощью firebug можно отлаживать и серверный код. Не breakpoint-ами конечно. Но как замена унылым print-ам и var_dump-ам очень даже!

Собственно делается всё очень просто. Для того чтобы в консоли firebug-а появилось сообщение, необходимо написать js-код:

console.log('сообщение');
console.group('разные типы сообщений');
console.info('к вашему сведению, мы тут логи пишем...');
console.warn('предупреждаем о разном');
console.error('и информируем об ошибках!!!');
console.groupEnd();
console.dir({сложная: {структура: [1,2,3]}});

Подробнее о возможностях консоли firebug-а можно узнать в документации.

Дело за малым – сформировать эти строки на вашей серверной платформе.
Сложность представляет лишь последнее – json-упаковка сложных структур, но и она уже во многих платформах решена. Сам я пользуюсь функцией, описанной в коментариях к json_encode, т.к. родная слишком консервативна в вопросах кодировок(по стандарту в json можно упаковать только уникод, но браузеры более лояльны нежели писатели стандартов).

Собственно теперь чем это лучше всяких принтов и вар_дампов?
Тем, что не меняют визуально документ, что существенно в современных сложных веб-приложениях.
К тому же это в разы удобнее – все сообщения в одном месте, красиво представлены…

В заключение скажу о якобы готовых решениях для PHP:
Log::Firebug из PEAR – драйвер для довольно распространнённого pear::log
FirePHP – более комплексное решение, плагин к firebug-у и обёртка к серверному коду.

Я ни тем, ни другим не пользуюсь, т.к. первое сделано левой ногой, а второе заворачивает оригинальный документ в страшную multipart-кашу…

06.05.08  |  ,  | 2 comments

чуть ниже нуля

Вот так вот:

<?php
  var_dump(round(-0.1));
?>

29.02.08  |   | 7 comments

Y2K38

Ожидаемый коллапс электронного пространства в y2k так и не состоялся, а следующий намечен на далёкий 2038-ой год.
Но такой ли он далёкий? Буквально сегодня пришлось столкнуться лицом к лицу с нависшей над миром угрозой.
В разрабатываемой системе все манипуляции с датами проводились через преобразование в unix timestamp и последующим его форматированием штатными средствами php (strtotime, mktime, strftime, date) и вся эта хрупкая конструкция разлетелась, когда вдруг возникла дата 01.01.2059. Нет, это не сумашедшие бета-тестеры и не опечатка – это оказался срок годности пива действия паспорта. Казалось выхода нет и человеку надо будет менять паспорт, но решение всё же нашлось: ADOdb Date Time Library – старенькая библиотечка на чистом php, которая позволит вам жить счастливо даже после официального окончания unix-эпохи.
Какие ещё беды настрадал нам Предсказамус?

Update: во какую штуку нашёл, надо бы донести это знание до тех, кому не безразлично…

27.02.08  |   | 2 comments

phing.tasks.ext.SvnExportRevisionDiffTask

В последнее время в посещаемых мною форумах и конференциях часто всплывает тема деплоя php-приложений на production-сервер. Я решил поделиться собственным рецептом.

В распоряжении имеется:

  1. svn-репозитарий с проектом.
  2. ftp-доступ к рабочему серверу.
  3. установленный и готовый к тяжёлой рутине phing

Сценарий работ следующий:

  1. Сделать экспорт кода из svn
  2. Подготовить его к загрузке (например убрать комментарии, “склеить” мелкие в один большой, удалить лишнее и т.п.)
  3. Проверить на наличие ошибок (они могли попасть в репозитарий или образоваться на предыдущем шаге)
  4. Закачать полученное на рабочий сервер.

Всё вроде бы просто, но смущает один момент – экспорт всего и вся. Со времени последнего обновления на сервере в репозитарии обновились 3 файла, а экспортировать нужно всё? Никак нет! Экспортировать будем только то, что изменилось. То есть первый шаг сценария будет выглядеть так:

  1. Получить последнюю версию проекта на сервере – RevFrom
  2. Получить последнюю версию проекта в репозитарии – RevTo
  3. Экспортировать файлы, которые изменились или добавились c RevFrom до RevTo

Версию рабочего проекта, не мудрствуя лукаво, предлагаю хранить в текстовом файле. Например revision.txt. Версию проекта в репозитарии поможет узнать SvnLastRevisionTask. Неясным остался лишь момент – каким образом выяснить какие файлы изменились. Те, кто пользовались TortoiseSVN наверняка знают о чудесной его возможности – сравнить две ревизии и экспортировать “разницу”. Но svn в чистом виде такой возможности не предоставляет. Так что пришлось немного поработать.
(more…)

25.02.08  |  , ,  | 4 comments

Sendmail & shared hosting II

Когда-то давно я писал о том, как решил проблему обнаружения источников спама на виртуальном хостинге. По просьбе товарища Murz выкладываю описываемый в заметке скрипт – быть может пригодиться он не только ему.

Ну и краткое руководство:

  1. Поместите скрипт куда-нибудь (пусть это будет /usr/bin/sendmail например, а реальный бинарник переименуйте в /usr/bin/sendmail.real)
  2. Отредактируете пути в скрипте (если вы выбрали их другими)
  3. Укажите путь к скрипту в директиве sendmail_path вашего php.ini (если отличается от указанных мною)
  4. Ждите вестей…

P.S.
Вы без труда сможете добавить простейшие “фильтры” и не отправлять например письма содержащие некие сигнатуры…