Похоже, у меня нет метастаз в лёгкие, это просто пневмония </sarcasm>
Author Archives: himself
Отличные новости
День, когда WordPress подавился метадатой
Сегодняшняя история програмистская. Кому компьютеры скучны, можете смело пропускать.
Как все знают, у меня есть отдельный блог на boku.ru. Записи туда по большей части копируются отсюда – в виде исключения я пару раз выложил там скучные рассказы, чтобы включить их в архив, но не афишировать.
Блог сделан на WordPress. Копирование записей устроено так: специальный скрипт генерирует RSS из дневника на Diary, а плагин FeedWordPress забирает RSS и импортирует в WordPress.
Категории при этом сохраняются, внутренние ссылки мой собственный плагин заменяет на местные, а если пост на дайри изменился – изменяется и пост на boku.ru, так что всё устроено достаточно удобно.
Но есть проблема. (далее)
function WhatToDo(post) localPost = FindLocalCopy(post); if localPost==null then //New post! AddPostMeta(localPost, 'syndication_item_hash', post.Hash); return doCreateNewPost; else if not FindMeta(localPost, 'syndication_item_hash', post.Hash) then //Post changed! AddPostMeta(localPost, 'syndication_item_hash', post.Hash); return doUpdatePost; else //No changes. return doNothing;
Если пост на дайри не менялся, FeedWordPress не будет заново его импортировать и не создаст новой ревизии местного поста. Это хорошо. Но перед тем, как записать пост в базу, WordPress прогоняет его через ряд плагинов, которые меняют его содержание:
Пост на дайри (из RSS) –> (замена ссылок на местные) —-> (исправление форматирования) –> Пост на boku.ru
Бывает, что какой-то из плагинов сбоит, и преобразует пост неправильно. Тогда я начинаю искать, в чём дело. Чтобы разобраться, мне нужно импортировать пост снова и снова, пока я не найду ошибку.
Но как это сделать? Ведь пост уже импортирован, и с точки зрения FeedWordPress, его содержимое не менялось (на дайри он остался тем же).
Для этой цели я влез в файлы FeedWordPress, и временно покромсал описанную выше процедуру. Она стала выглядеть так:
function WhatToDo(post) localPost = FindLocalCopy(post); if localPost==null then //New post! AddPostMeta(localPost, 'syndication_item_hash', post.Hash); return doCreateNewPost; else if not FindMeta(localPost, 'syndication_item_hash', post.Hash) then //Hack: Post is always changed! AddPostMeta(localPost, 'syndication_item_hash', post.Hash); return doUpdatePost; //TODO: Restore normal version.
Менялся пост или нет, мы всегда импортируем его заново. Конечно, при этом создаётся новая ревизия и захламляется база, но подумаешь, мне же ненадолго… А старые ревизии поста легко удалить.
Поправив таким образом FeedWordPress, я залил новые файлы на сервер и стал искать баг в своих плагинах. И нашёл. Исправил. Убедился, что теперь посты преобразуются правильно. Всё сохранил, применил, закрыл… а отключить хак забыл.
И ушёл.
Вторая половина этой истории началась через месяц, когда я зашёл на блог на boku.ru. Все страницы с последними постами не работали.
Вместо них отображался белый экран. Не работала даже консоль админа, из которой посты можно удалить. В логах сервера появлялась ошибка:
php error: maximum memory allocation exceeded
Какой-то из скриптов жрёт память? Но почему? Что я менял?
И тут я вспомнил, что забыл отключить хак.
Но постойте, а что такого? Проверки раз в полчаса – это 48 проверок в день, жалкие полторы тысячи ревизий за месяц. WordPress может обслуживать десятки тысяч постов, для MySQL лишние несколько тысяч ревизий – пустяк.
Если я напишу ещё полторы тысячи постов – вордпресс даже не поперхнётся. А полторы тысячи ревизий вывели его из строя?
Да ну! Не так он написан.
Тогда почему любая страница, которая обращается к последним постам – вылетает с переполнением памяти? База данных находится на диске – что вообще вордпресс грузит в память?
Метадату.
Каждый раз, загружая очередной пост для печати, вордпресс делает примерно следующее:
rows = exec_sql('SELECT * FROM post_metadata WHERE post_id=id'); while rows.MoveNext() do metadata[rows['name']]=rows['value']
То есть, читает из базы все относящиеся к посту записи метадаты и загружает их для быстрого доступа в память.
Обычно таких записей 8-10, иногда до 15 – мелочи, в общем.
У последних записей в моём блоге их было по 60 000.
Ничего удивительного, что обращаясь к этим записям, вордпресс падал. Он не рассчитан на 60 000 записей метадаты у поста. Удивительно, откуда эти записи взялись.
Я открыл таблицу phpMyAdmin-ом, и увидел, что все они – это копии параметра syndication_permalink. Тогда всё стало ясно.
Описанная выше функция WhatToDo решает, что делать с постом из RSS – добавить новый, обновить существующий или пропустить. При этом она регистрирует syndication_permalink, чтобы второй раз не обновлять одно и то же.
Да, импорт RSS происходит лишь раз в полчаса, 48 раз в сутки, и каждый пост импортируется лишь однажды – но функция проверки WhatToDo вызывается десятки раз за процедуру одного импорта. Только однажды её результат имеет значение, поэтому ревизий в базе действительно создано лишь полторы тысячи – но при каждом вызове она добавляет syndication_permalink, и этих пермалинков, совершенно одинаковых, у одного поста набираются десятки тысяч.
Ирония: вордпресс мог бы вынести десятки тысяч постов – но не десятки тысяч свойств поста.
Как всё это чинить?
Итак, испорчена таблица post_metadata: в ней для некоторых постов некоторые записи продублированы десятки тысяч раз. Нужно удалить дубли, но оставить по одной копии каждой записи.
После некоторой возни и гуглинга сотворился следующий манёвр:
CREATE TABLE `keep_ids` AS ( SELECT MIN(`rowid`) AS `rowid` FROM `post_metadata` GROUP BY `postid`, `name`, `value` )
Этим запросом мы находим все цепочки дублей (записей с одинаковыми данными в полях postid, name и value), и в каждой выбираем наименьший номер записи. Таким образом, мы получаем по одной копии каждой уникальной записи. Эти копии надо сохранить, а всё остальное удалить.
ALTER TABLE `keep_ids` ADD UNIQUE INDEX `rowid` (`rowid`)
Это чтобы операции с новой таблицей были быстрыми – сейчас понадобится.
DELETE FROM `post_metadata` WHERE `rowid` NOT IN (SELECT `rowid` FROM `keep_ids`)
Удаляем все записи из исходной таблицы, которые не вошли в наш “список на сохранение”. Если б в `keep_ids` не было индексов, мы бы тут завязли на несколько минут, а так – только секунд.
Ну и, наконец, удаляем временную таблицу:
DROP TABLE `keep_ids`
Победа! Число записей в post_metadata резко падает с сотен тысяч до 13 000 и блог снова работает нормально.
Названия таблиц и полей в примерах условны, и не соответствуют настоящим названиям в базе вордпресс. Код написан на условном языке, а код SQL может быть не совсем правильным, но передаёт общую мысль.
Ну вот, похоже, девятого числа я еду в Японию. Хотя чувствую себя по-прежнему нехорошо (после последней химии). Надеюсь, всё в ближайшие дни как-нибудь разрешится: либо мне резко станет лучше или хуже, либо придут результаты каких-нибудь анализов, которые любые путешествия исключат, и т.д. и т.п.. А то непонятно как-то.
В Токио я буду неделю, при этом попадаю на летний комикет (10-12) и, возможно, Обон (15 августа, но в Канто 15 июля, короче, я ничего не понял, разберусь ближе к делу).
Надо вспомнить все места, которые я хотел посетить. Подскажите что-нибудь интересное. Пока помню:
– Комикет
– Акибу
– Синдзюку
– Токийскую башню
– Сибую
– Это место где продают отоме-игры (забыл место)
– Посмотреть на Токийский залив
– Обон
Принимаю запросы на сувениры, также на покупки с комикета (поскольку заранее неясно, что будет на комикете, и что я из этого увижу, можно просить и в общих чертах, например, “додзи по ореимо манами х папа кёске”, и тогда я, скрепя сердце, постараюсь найти хоть что-нибудь в таком духе).
Разумеется, нужно уметь как-то у меня это потом забрать. Обычно я в Москве.
Ещё аниме пачками
Kokoro connect – ещё пять школьников открыли кружок времяпровождения.
Binbougami ga! – ещё один сверхъестественный кто-то поселился в доме у кого-то.
Jinrui wa suitai shimashita – что-то из ноитамины, очередной непонятный мир будущего, мало сюжета, все такие необычные девочки, феечки, какая-то соц. сатира (но в сто раз менее едкая, чем в зецубо сенсее), в общем, кому-то может понравиться… скорее, девушкам.
Sword Art Online – чуваки зашли в виртуальную реальность и не могут выйти. Капля интереса в завязке есть, но похоже, впереди просто 13 серий приключенчества.
Получил свою японскую визу
Выглядит как радужная наклейка во всю страницу загранпаспорта.
Заодно сравнил последнее фото с тем, что на загранке (circa 2010). Два года назад я был вежливый молодой человек, а сейчас бандит какой-то лысый
Я не уверен!
Попробуйте быстро ответить на вопрос, в ответе на который не уверены до конца:
– Ты дома свет выключил?
– По-моему, да.
Не годится! “По-моему” – это сокращение от “по моему мнению” (“По-моему, Пупкин – плохой президент”), а какое уж тут мнение? Либо выключил, либо нет.
– Кажется, да.
Не годится! “Казаться” могут предметы вдалеке (“Кто это там на эшафоте?” – “Ба! Кажется, Пупкин”), ну в крайнем случае, будущее (“Кажется, Пупкину кранты”), но никак не прошлое! Где это оно “кажется” (показывается)?
– Вроде бы да.
Не годится! “Вроде” значит “похожего рода, сорта” (“Чья это дача?” – “Вроде бы депутата какого-то”). Вы же со светом поступили вполне определённо, либо выключили, либо нет.
– Полагаю, да.
Не годится! Полагают верным то, на чём строят дальнейшие рассуждения (“Полагаю, здесь теперь не искупаться, так что надо искать новый пляж”). А тут речь о ваших сомнениях, а не предположениях.
– Наверное.
Не годится! Какое же это “на верное”, когда вы не уверены? Правильное употребление: “Почему стоим?” – “Наверное, депутата везут.”
– Возможно.
Не годится! А то мы не знали, что это возможно! Правильное употребление: “Возможно, будет революция”.
– Видимо.
Что это вам “видимо”, когда дом далеко-далеко? Правильное употребление: “Что солдаты там делают?” – “Видимо, охраняют мир и порядок.”.
– Скорее всего.
А что, было соревнование в скорости выключения света? Правильно – указать на событие, которое случится прежде любых других: “Скорее всего, президент выступит с заявлением.”.
– Да выключил я, выключил, отвяжись от меня!
О договорах
Раньше я думал, что я один такой, но похоже, в головах очень многих людей сидит мысль, что договор на бумаге – это формальность, а главное договориться по-человечески. Заказываю у одной фирмы, скажем, покупку и посадку картошки. Посидели, поговорили, выдают мне договор на подписание. Читаю:
Исполнитель обязуется посадить картошку на поле заказчика.
И ни слова про то, откуда он её возьмёт.
Я спрашиваю:
– А почему не сказано про то, что картошку вы купите сами?
– Да-да, купим, мы же договорились.
– Но в договоре об этом не сказано…
– Купим, откуда ещё нам взять картошку?
Приставать к менеджеру стыдно – мы ведь договорились! Получается, я им не доверяю? Я крючкотвор, придираюсь к бумажке?
Но договор и существует на случай, если мы поссоримся. Никому не хочется ссориться, но если слепо верить в чужую порядочность, то договоры вообще не нужны, правильно? Не надо ничего писать – ни про покупку, ни про посадку. А раз уж начали, то дело следует довести до конца. Неправильный договор – хуже, чем вообще никакого.
– Давайте, всё-таки, укажем это в договоре. А то, если мы поссоримся, вы скажете – “кто говорил о покупке? Мы вашу картошку обещали посадить”.
– Хорошо, не проблема. Не будем ссориться. (сделал) Раньше просто никто не просил такого.
У этой достаточно крупной фермерской фирмы были десятки клиентов. Ни один не прочёл договора и не попросил указать в нём всё правильно? Либо менеджер говорит неправду, либо эти люди – растяпы, такие же, как я (если бы не обдумал это заранее).
Памятка исправляющимся растяпам:
Читайте от начала и до конца каждый договор, который подписываете. Не стесняйтесь потратить чужое время или задержать очередь – в крайнем случае, отойдите в уголок. Всегда просите разъяснения непонятным местам, и если формулировка договора вам не нравится, или вам кажется, что в нём сказано неясно, не то или не всё, о чём договорились, просите договор исправить.
Ни один договор не написан в камне, это всё вордовские документы, и пусть вас не пугает, что слова уже распечатаны: изменить текст и распечатать заново – дело минуты. Не сдавайтесь при словах, что “такой договор подписывают все”: платить за ЭТОТ договор придётся вам, а не “всем”, вы и решаете, что в нём написано.
Если вы и ваш партнёр действительно договорились, нет никаких причин не изменить договор, чтобы прояснить обязанности сторон или описать их полнее.
Отказать вам могут тогда – и только тогда! – когда вас хотят обмануть.
Игра по Back to the Future
Конечно, это фанфик, но очень хороший фанфик. Настолько кинематографичный и похожий на оригинал, что сцены из игры в голове путаются со сценами из фильма. Даже сюжет, который местами выбивается из стилистики, по большому счёту всё-таки “настоящий” – приключенческий и интересный. Не перечесть всех моментов, когда думаешь “чёрт, а ведь это правда могло быть и в фильмах”.
А знакомая музыка и знакомые голоса Марти и Дока (трудно поверить, что их играли другие люди) сшивают любые разрывы и заставляют поверить, что это действительно “Назад в будущее”. Авторы могли ошибиться во стольких местах, но в большинстве не ошиблись.
Кризис существования
Нашёл в черновиках – сейчас уже не совсем отвечаю за написанное
Интересно, многим ли смешно читать статью Existential crisis на Википедии?
An existential crisis is often provoked by a significant event in the person’s life — marriage, separation […], reaching a personally-significant age (turning 20, turning 30, turning 40, etc.), etc. Usually, it provokes the sufferer’s introspection about personal mortality, thus revealing the psychological repression of said awareness.
Там ведь написано, если убрать мишуру:
“Экзестенциальный кризис – это когда человек вдруг теряет способность к самообману и видит во всей полноте, насколько его жизнь бессмысленна и коротка.”
То, что способность видеть истину люди считают проблемой, что состояние пренебрежения к ней считается здоровым, разве это не смешно? Разве не в жалком свете выставляет нас, людей? Не как зверей, сознающих и не способных победить свою животную природу? Или дикарей, оказавшихся в рубке самолёта, и отмечающих мелом на стене:
“Руль – штуковина, которую нельзя долго тянуть вниз, иначе все умрут”