24 февр. 2015 г.

Lock в файл или в redis?

Иногда нужно гарантировать эксклюзивное исполнение функции для определенного набора данных. Например, только одно одновременное изъятие данных из какого-либо источника. На помощь в таких ситуациях приходят локи.

Проще всего создать какой-нибудь lock-файл и проверять его существование. Если есть файл - lock включен.
import os
from contextlib import contextmanager


class LockedException(Exception):
    pass


@contextmanager
def file_lock(lock_file):
    """
    with file_lock('/tmp/file.lock'):
        some code here
    """
    if os.path.exists(lock_file):
        raise LockedException('LockedException')
    else:
        open(lock_file, 'w').write("1")
        try:
            yield
        finally:
            os.remove(lock_file)

Жалко напрягать HDD такими мелкими операциями. Попробуем делать lock в redis:
import redis
from contextlib import contextmanager


r = r = redis.StrictRedis(host='localhost', port=6379, db=0)


class LockedException(Exception):
    pass

@contextmanager
def redis_lock(lock_id):
    """
    with redis_lock('unique_redis_key'):
        some code here
    """
    if r.get(lock_id):
        raise LockedException('LockedException')
    else:
        r.set(lock_id, 1)
        try:
            yield
        finally:
            r.delete(lock_id)

Теперь проверим какой вариант быстрей:
if __name__ == '__main__':
    import time
    from numpy import mean


    count = 10000

    times1 = []
    for i in xrange(0, count):
        start = time.time()
        with file_lock('/tmp/file.lock'):
            pass

        times1.append(float(time.time() - start))

    times2 = []
    for i in xrange(0, count):
        start = time.time()
        with redis_lock('redis_lock'):
            pass

        times2.append(float(time.time() - start))

    print 'file lock:', max(times1), min(times1), mean(times1)
    print 'redis lock:', max(times2), min(times2), mean(times2)

Результаты:

maxminavg
file_lock0.08177495002750.000284910202026 0.000996773791313
redis_lock0.00140619277954 0.000319957733154 0.000346991157532

Lock в redis в 3 раза быстрей.

12 янв. 2015 г.

Shiningpanda и jenkins

Надкусил собаку, при настройке CI на базе jenkins. Проглотить мешают постоянные всякие мелочи. Например из последнего: плагин Virtualenv Builder [Shiningpanda], с помощью которого можно более лучше развертывать виртуальные окружения python, принимает настройку "name". По документации, настройка соответствует названию virtualenv окружения. Изменение этой опции не влияет на фактическое название окружения (по факту получается что-то вроде c934fdf).
При всем этом, Shiningpanda реально экономит время при создании CI для python проекта.

Сборка:
[Virtualenv Builder]
pip install pytest pytest-cov
$PYTHON_EXE setup.py install
py.test --junitxml junit.xml --cov-report xml --cov src tests.py

Постсборка:
[Cobertura coverage]
coverage.xml

[juint]
result.xml

И далее в постсборке запускает выкатка библиотеки и/или обновление девелоперского-стейджа.

А как в ваших компаниях реализован CI?

11 янв. 2015 г.

Отправка push-сообщений на мобильные устройства

Вчера меня в очередной раз спросили "как и чем лучше отправлять пуши?" Отвечаю: если у вас не очень много сообщений в месяц - идеально использовать http://urbanairship.com/. В нем есть много "богатой" аналитики прямо из коробки и он поможет вам акцентировать внимание на том, что действительно важно в этом вопрос: длинна сообщения, формат, скорость и гарантии доставки, отслеживания и аналитика. Есть бесплатный ознакомительный период, дающий максимум возможностей, но и бесплатной версии хватит, чтобы отправлять пуши на android, ios, win phone.
Если же количество отправляемых ежемесячно сообщений большое, а квартиру Москве продавать жалко - пишите свое решение, как поступили мы в Anews. В основе нашего решения django-push-notifications, который, в свою очередь, использовал код двух более низкоуровневых библиотек, которые постепенно были улучшены (без возврата кода в оные). Мы для себя улучшили поддержку юникода при отправке сообщений на iOS и добавили ttl в андройде (последние версии библиотеки ttl уже есть), обработку ответов о GCM сервера.
На данный момент на Anews мы почти ежедневно отправляем 500 тысяч сообщений, которые улетают к пользователям в среднем менее чем за 12 минут.

Блогинг на самописном джвике

В общем, эксперимент с блогом на самописном джвике можно считать завершенным. Больше всего этот опыт похож на попытку создать свою собственную почту вместо использования gmail - есть ощущение защищенности от Большого Брата, но нет тех печенек, которыми он заманивает на темную сторону.
Самая главная печенька, которой мне не хватало - отсев спам комментариев. Я натурально ловил себя на мысли, что не хочу заходить в админку блога, потому что там снова тонны скриптованных комментов с предложением сыграть в онлайн казино и сразу после этого медикаментозно увеличить себе пенис. Буэ.
После переноса постов из старого блога в новые прилетело сразу несколько комментов, которые я не получал к постам более года, потому как на том движке у меня не было старых подписчиков. Приятно получил комментарии к посту, но радость омрачает осознание того, что подписчики получили сразу пачку старых постов в RSS-ленте. Не удивительно, что общий тон комментариев раздраженно-осуждающий.

10 янв. 2015 г.

Интервью на openmonte.com

Очень интересный для меня опыт - интервью для сайта openmonte.com. Опубликовано почти месяц назад, но до этого было как-то не до блога. Паааадписывайтесь, ставьте лайк и др. и пр.! Что там еще нужно писать в таких случая? )

Идея!

Знающие люди утверждают, что сделать технологический бизнес сейчас не сложно. Куда сложней сделать масштабируемый бизнес. Скажем, сделать проект решающий проблему кросс-постинга в различные социальные сети и группы рекламного объявления не сложно. Как на этом заработать? Модель подписок можно считать масштабируемой?
Есть например http://post-it-quickly.com/ с именно такой моделью монетизации. Их посадочная страница уверяет, что дела идут не плохо. Какой потенциал может быть у подобной технологически короткой идеи?

Видео для "подумать":

Руслан - умница. Больше всего меня поразила его способность удерживать в голове прочитанные истории (ну и 70+ сотрудников, конечно). Для меня они (истории из книг) - подобие белого шума, руководствоваться ими мне тяжело. Ему - нет.

29 сент. 2014 г.

Проверка бранча перед пушем Mercurial hook



В очередной раз запушив в production ветку вместо devel задумался о хуке, который бы делал проверку за меня. Хук выглядит примерно так:
preoutgoing.confirm = if [ "$(hg branch)" = "production" ]; then read -p 'Are you sure you want to push to branch "production"? (y/n): '; echo $REPLY | grep -q 'y'; fi