четверг, 18 февраля 2010 г.

CouchDB | Тонкости map-функции

Никогда не пишите в map-функции
emit(doc._id, doc);

т.к. при вызове view на жестком диске создается индекс-файл, который будет содержать значения doc._id и doc!

UPDADE: doc - т.е. будут все поля документа.

Возвращайте только новые, просчитанные данные. Ибо есть ключик include_docs=true, при наличии которого БД отдаст кроме того, что в emit ещё и сами документы!

среда, 3 февраля 2010 г.

CouchDB | Простенький скрипт для keep-alive

CouchDB запускается как фоновый процесс. Но он не умеет подниматься в случае ошибки.
Вот пример простого скрипта, который через curl проверяет - активен ли процесс и если нет - перезапускает его:

#!/bin/bash

echo "Checking, is CouchDB is alive..."
#замените адрес на свой!
ANSWER=$(curl http://192.168.0.5:5984 -s)

if test $ANSWER
then
    echo "CouchDB is alive!"
else
    echo "Trying to restart..."

    /etc/init.d/couchdb restart
fi

Скрипт можно усложнить - например, после рестарта проверить - запустился ли. Если нет - отсылать письмо админу :-)

вторник, 26 января 2010 г.

Python + Psycopg2 + Win32 | Ошибка при большом кол-ве подключений к БД

Написав простецкий скрипт на питоне для копирования данных таблицы с MSSQL в PostgreSQL (+ конвертация некоторых полей) напоролся на ошибку - "psycopg.OperationalError, could not connect to server: Address already in use". Запускал скрипт я на Win32, Python2.6, Psycopg2 2.0.13. Долго ковырял гугль. Нашлась тема. И хотя она оказалась решенной ещё в 2006 году - я эту ошибку всё равно получал. Да, библиотека у меня судя по её номеру - намного "новее"...

Помучав мозг и посмотрев на код работы с psql, я увидел, что для вставки каждой строки данных я каждый раз открываю и закрываю соединение... Вот оно! А что, если открыть соединение 1 раз и кидать инсерты? Да, так и быстрее и не получаю ошибку! (вот в фоне уже 80К строк обработано, только нужно учесть, что я соединился с pgBouncer).

Ну или можно вставить time.sleep(3*60) после каждых 2К строк...

четверг, 21 января 2010 г.

Genius NetScroll 220 Laser | Мышь. Понижение чувствительности.

OMG! Все мучался - мышь ЛЕТАЕТ! Оказалось есть переключение dpi (влияет на чувствительность). Знаете как? ХАХА! Нажатием лк+пк+колеса!

УРА!

MSSQL | Подлость. Никогда не доверяйте!

Был обычный день. Настал момент в базе данных у одной таблицы сменить тип с text на ntext. А таблица на 500к строк. И важная - жуть! Ок, Sql managment studio создала скрипт. Интересно, но скрипт создавал временную таблицу, копировал в неё оригинальную, потом дропал оригинальную и переименовывал временную в название оригинала. Вроде - все нормально, все обернуто транзакциями.

Да вот только обернуто то не все вместе, а каждая команда по отдельности! Ну в результате - сначала мешали внешние ключи. А потом просто - оригинальная таблица дропнулась и временной не видно!? ВСЁ!

Прощайте данные!

Да, есть бекап. Ночной. Общий на 50Гиг. Шутки в сторону. Микрософт не научил студию восстанавливать таблицы по одной. Финиш. А точнее - пипец!

Но я умный. У меня есть машина-дублер. Правда она - на постгресе!

В общем поимел я секса с sqlcmd и конвертированием ~300Мегового бекапа в стиле INSERT INTO TABLE. Хорошо что была линукс-машина и хвала vim! Особенно его комманде глобальной замены %s/что_искать/на_что_менять/gn.

Для интереса - sqlcmd работает по стандарту. Т.е. каждая команда должна завершаться пинком командой GO. Но кроме того из-за огромного размера - каждый инсерт пришлось обернуть в транзакцию.

Типа:
begin tran;
insert into ...;
commit tran;
go

Ну и конечно же вызов sqlcmd с флагом кодировки -f 65001 (это utf-8).

Всё. Живем.

пятница, 4 декабря 2009 г.

Werkzeug + SQLAlchemy + Jinja2 + Memcached = Маст трай

Да, да, да! Дошли таки руки! Django отложен в темный ящик, так как мне нужна бОльшая гибкость. Да и админка не нужна совсем в том проекте, который делаю (секрет :-).

Хорошо, что перед встречей с werkzeug я поковырялся с GAE Python (сделал нечто вроде блога). Это помогло мне сделать этакий фреймворк для обработки запросов.
К примеру сделал свой базовый класс Controller. Это объект с response и request классами внутри.

Куски класса:
class Controller():
    def __init__(self, request):
    def get(self): #вызывается при get-запросе
    def post(self): #вызывается при post-запросе
    def render_template(self, template, **context): #так вызывается шаблонизатор
    def preprocess(self): # дергается в конце инициализации. сюда можно навесить декоратор для проверки прав доступа
Кроме того, Controller при каждой инициализации создает в себе объект self.current_user - думаю понятно что это :-)

Еще очень обрадовал шаблонизатор:
- он кэширует шаблоны! (т.е. хранит их в своем пре-компилед виде).
- макросы (можно загружать из файла)

Отдельно помучался с апачем + wsgi. Но как обычно - документация спасает.

П.С.: просто надоел зависающий IIS6