Архив

Node Saver

Примерно в марте месяце, пока мне было скучно и хотелось поиграться с MongoDB, я решил сделать свой аналог замечательного сайта peeep.us. Дело в том, что peeep.us хоть и жутко удобный, но не совсем безопастный, добавленные туда страницы потом хрен удалишь и самое ужасное, он открыт к индексации. Кстати все кто хочет почитать лепру но не имеют туда доступа могут ..., ну короче намек поняли, все как с мегафоном.

save.rpsl.info

Первую версию, которая на момент публикации поста, живет на save.rpsl.info я написал часа за четыре, из них примерно два часа я искал у кого своровать дизайн :D

После этого, я решил что связка php и mongodb для такой микрозадачи не нужна и решил переписать ее на node.js. За несколько вечеров я разобрался и сделал и то, что хотел. В конечном варианте полностью отказалася от MongoDB и заменил его на Memcached. Зачем мне тут монго? Данные я кладу на несколько дней, данных мало, заодно и решится вопрос с их очисткой, а то, что не надежно, ну и фиг с ним. Ничего ценного там хранить смысла нету, а статистика ребута memcached'a на серваке говорит о том, что если раз в полгода я и потеряю данные, то ничего страшного не произойдет.

И все бы было хорошо, но я не решил главную проблему - сохранение работает только для открытых источников, как передавать страницу с сайта, которая закрыта basic auth я не придумал. У меня есть конечнонесколько идей, но проверять их мне слишком лениво. Вторая проблема в том, что мне не хочется из-за этой мелочи поднимать на боевом серваке Node.JS, в какой-то момент пробовал взять виртуалку у clodo.ru, заодно потестировать его, но тесты оказались плачевными, потом хотел у alice2k стрельнуть кусочек vds, но уехал в Испанию и снова забил на это.

В итоге с марта месяца, у меня на рабочем столе лежит папка node, которую я все время хочу удалить и в последний момент вспоминаю, что этого делать не стоит. Несколько раз приходилось доставать из бэкапа.

Сегодня мне захотелось ее удалить, поэтому я решил выложить сорцы на github

В общем форкайте меня, все дела. https://github.com/Rpsl/node-saver


Проверка multi_query в mysqli

Увидел сегодня красивое решение проверки выполнения мультизапроса в mysqli.

Если кто не в курсе, то можно сформировать в одну строку кучу запросов, разделяемых точкой с запятой, а потом отдать это на выполнение. Так вот проверять ошибки можно разными способами, а можно просто в конец добавить некий абстрактный SELECT 'complete'. Это подходит для запросов типа INSERT, DELETE, UPDATE.

Eще, у меня в примере указан не прямой вызов multi_query, а обертка для запросов, думаю что это и зачем вам объяснять не нужно.

if ( $DB()->multi("
    UPDATE someshit SET bla=bla-1 WHERE id='%d';
    DELETE FROM someshit WHERE category='%d';
    DELETE FROM someshit WHERE id='%d';
    SELECT 'complete';",
    $id, $category, $id) != "complete" )
{
    self::$resultCode = self::DB_ERROR;
    return false;
}
self::$resultCode = self::SUCCESS;

Обновил NAS

nas

У меня дома, уже почти год живет ReadyNAS Duo, вчера мне было скучно и я подумал, что будет неплохо обновить его.

Изначально планировал купить в него второй жесткий диск, т.к. с момента покупки, в нем живет только один seagate на полтора террабайта и бэкапам time machine, в последнее время, там очень тесно. Хотел купить второй такой-же, но почитав документацию, обнаружил, что покупка второго hdd не позволит увелить общий объем устройства, а позволит сделать только raid. Так как raid на 1.5 террабайта мне совсем не нужен, я решил отказаться от этой идеи и потом, когда будут ресурсы, купить жесткий диск от 3 террабайт.

Таким образом, из возможного обновления, мне оставалась только оперативка. По спецификации, в него можно засунуть до 1гб оперативной памяти, SODIMM на 200pin. В целом, мне вполне хорошо жилось и на 256. Nas тихо стоит в шкафу, качает торренты, принимает бэкапы и ничего больше не делает, но когда кол-во активных торрентов переваливает 10-15, то веб-интерфейс начинает жутко тупить.

Почитав несколько заметок и упоминаний на сайте производителя, что этому величеству не всякая память подходит, остановил свой выбор на "Crucial CT12864X40B". Заказал, проехался до магазина, привез, запустил.

Вообще я не ожидал сильных изменений, да и на глаз ничего нового не увидел. Работать, вроде, стал шустрее, торренты качаются, time machine стала работать быстрее, но т.к. никаких тестот я не проводил, мне кажется все эти улучшения эффект плацебо.


Scrollbar и центрирование

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

#content {
   margin: 0 auto;
}

Так вот, при загрузке страницы, до момента пока основной контент еще не подгрузился, а шапка уже появилась, то scroll'a справа нету, как только контент подгружается, то сбоку появляется scrollbar и весь контент из-за этого прыгает на несколько пикселей влево. В целом этот баг можно решить, если задать основному блоку min-height, но это не универсальное решение. Тем более это может вызывать косяки, если вдруг окажется, что контента у нас на странице нету, будет большой вентум.

Думали-думали, не знали что делать, в итоге решили сделать как у fb, что бы скроллбар был всегда на странице, не важно активный или нет.

body {
   overflow-y: scroll;
}

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

Может расскажите другие способы решения?


PHP - Переворот числа

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

Задача простая. Перевернуть любое целое число используя только математические операторы. Было 5432, должно стать 2345.

function reverseInt( $a )
{
    $tmp = $a;
    $return = 0;

    while( $tmp > 0 )
    {
        /*

        Играть с числами очень весело, можно находить и открывать для себя
        их волшебные свойства. Так, например, если 432 разделить на 10,
        то мы получим 43.2

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

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

        */

        $return = ( $return * 10 ) + ( $tmp % 10 );

        /*
        Каждый раз делим исходное число на 10, что-бы обойти каждый его разряд.
        */

        $tmp = intval( $tmp / 10 );
    }

    return $return ;
}

$foo = 123456789;

echo 'Start: ' . $foo . "\n";

$bar = reverseInt( $foo );

echo 'End: ' . $bar . "\n";

Как видно, все достаточно просто, нужно просто понять как это работает. Теперь хочу найти все варианты с решением этой задачи, думаю что если сделать это с помощью битовых операций получится еще быстрее и красивее.


Request uri в nginx

Второй раз натыкаюсь.

В первый раз я не мог понять почему на php скрипт приходил GET запрос, хотя я отправлял POST и при этом массив был пустой, но при просмотре php://input нужные мне переменные были видны.

Тут ситуация была простой, но не очевидной, при запросе, я не попадал в нужный location и nginx успешно отправлял меня на @404, в следствие чего, php получал уже GET запрос.

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

Из доков nginx:

$request_uri - эта переменная равна полному первоначальному URI вместе с аргументами;

Пример, вывод $_SERVER из подключенного ssi блока:

  • [QUERY_STRING] => do=search&action=search
  • [REQUEST_URI] => /?q=творог&lr=213

Что бы получить нужный нам фэйковый $_GET, можно сделать что-нибудь типо этого:

parse_str( str_replace('/?', '', getenv('REQUEST_URI') ), $original_get );

Хитрожопые инкорпорейтед

Наткнулся сегодня на еще одно решение задачи, про переворот строки. Вспомнил этот комикс.

$a = 'abcdefgh';
// Напишите здесь недостающий код,
// чтобы результатом работы скрипта
// была строка $a, повернутая наоборот
echo $a;
$a = 'abcdefgh';
$a='hgfedcba';
echo $a;

welcome aboard


Про блоги

Давно уже в голове крутится мысль, что современные блог движки, они такие сухие, безидейные, не вдохновляющие. Вот тот-же самый wordpress, есть он, у меня на нем блог работает, при этом я 100500 раз переезжал на другие движки и пробовал вести блог на них, но все равно возвращался обратно. Они не вдохновляют на то, что-бы в них писать. Тем на которые можно и хочется написать много, а желания нету. Это не потому что я такой ленивый, а потому что написать новый пост превращается в тягомотину.

Когда-то давно, когда у меня не было стандалон блога, я тусил в жж. В 2004 году в жж было интересно, а сейчас он стал убогим, политизированным уг.

Идея написать свой блог движег не покидает меня уже миллион лет, но это такая морока, что мне не хочется этим заниматься. Читая интернеты, обнаружил что Бирман выложил очередной релиз своего блог движка. Снаружи очень красивая, внутри какой-то дикий пиздец творится. Я всегда был уверен, что дизайнеры не должны заниматься программированием, а программисты дизайном ( именно поэтому, в моем блоге, такой убогий диз ). Но учитывая, что Эгея носит еще статус беты, я не буду выражать свое "фи", ведь если не заглядывать под капот, то это действительно очень красивый и лаконичный продукт.

Вот честно, я заинсталил его себе и даже тешил себя мыслями, что смогу перенести свой блог туда, мол буду писать там, но две вещи меня держат:

​1) Все ссылки на страницы моего блога поломаются, но это не проблема, это решаемо.

2) Оформление постов в данном движке происходит с помощью wiki разметки и соответсвенно все посты едут, полез в гугл поискать механизм который умеет конвертировать html в wiki формат, но адекватных механизмов не нашел.

На этом и забил.

Но все же мысль избавить от Wordpress'a не дает мне покоя. Он меня жутко достал. Он медленный. Он уродует контент. #hate, #hate.

Мне тут подсказывали еще попробовать LiveStreet в качестве личного блога. Но спасибо, я на LiveStreet сейчас веду один проект, в основном клипы хип-хоп тематики и затрахался с ним до глубины души. Я не знаю что в головах у авторов, но внутреннее устройство движка это такой лютый бред. Навернуть такое кол-во ООП на единицу кода и при этом суметь использовать все анти-паттерны визуального оформления кода, это надо быть действительно смелым и уверенным в себе человеком.

Вот опять я всех обругал, а ведь не хотел. ((


Про отображение ошибок

Меня жутко, прямо до костей, бесят люди, которые делают логику сайта такой, что в случае возникновения ошибки на сайте, тебя перебрасывает на страницу вида

http://site.ru/wow/it/is/error/page/

Ну реально полный кретинизм.

Ок, допустим произошла ошибка, допустим база отвалилась и сайт не может нам ничего показать кроме ошибки. Ну так покажи ошибку, а не перебрасывай меня на другую страницу. Ведь у меня нет возможности обновить страницу с ошибкой через 5 минут и увидеть интересный мне контент.

Прям вот ваще. Если у вас так - то я вас ненавижу.


Самое простое ускорение сайта

В итернете есть куча более правильных статей на тему организации дружбы между nginx и memcache. Я же, покажу самый простой пример, который можно сделать за пять - десять минут и который поможет разгрузить основные страницы вашего сайта.

Что я предлагаю ?

Давайте засунем главную страницу сайта, в memcache, и настроим nginx что бы он отдавал ее прямо из memcache не обращаясь к интерпретаторам. Будем класть раз в минуту сроком жизни на 60 секунд. Стоит понимать, что данный способ нужно дорабатывать, если у вас на страницах используется динамичные данные, то есть данный способ актуален только для "гостей" сайта, благо nginx умеет работать и cookie.

Пример настройки nginx'a

location / {

    default_type    text/html;

    if ( $request_uri = '/')
    {
        set $memcached_key "index_page";
        memcached_pass 127.0.0.1:11211;

        error_page 404 503 = @fallback;
    }

    error_page 404 = @fallback;
}

Пример cron скрипта, который можно повесить на выполнение.

error_reporting(E_ALL);
ini_set('display_errors', 1);

if( class_exists('Memcache', FALSE))
{
    $mem = new Memcache;

    $mem->connect('localhost', 11211);

    $html = file_get_contents('http://blog.rpsl.info/?asd');

    if(!empty( $html ) )
    {
        //$mem->delete('index_page', 0);
        $mem->set('index_page', $html, 0, 60 );

        //echo $html;
    }
}
else
{
    echo 'no memcache';
}

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