Почему заметки в РСС Эгеи могут повторяться

Потому что у вашего блога несколько адресов-синонимов и не настроен редирект на канонический адрес. Сейчас объясню.

Об определении новых заметок

Иногда люди жалуются, что от некоторых блогов на Эгее заметки «приходят по два раза» (или даже больше). Такое, например, было у Максима Ильяхова.

Чтобы разобраться, в чём дело, важно сначала понять, что заметки по РСС никуда не «приходят». РСС — это просто формат, в котором отдаётся лента. Читалка смотрит, не появилось ли в ленте новое, и, если появилось, показывает вам это как непрочитанное. Разумеется, каждая заметка в ленте встречается один раз — можете сами в этом убедиться на любом проблемном блоге. Но что-то заставляет читалку при очередном взгляде на ленту считать, что заметки из неё она ещё не видела, и нужно показать вам их как новые.

Чтобы понять, видела читалка заметку или нет, она смотрит не в текст заметки, а в РСС-тег <guid>. Этот тег должен содержать некий глобально уникальный идентификатор заметки. Традиционно для этого используют просто адрес заметки, и в этом случае ещё ставится атрибут isPermaLink.

Например, у этой заметки в ленте написано так:

<guid isPermaLink="true">
  http://ilyabirman.ru/meanwhile/all/aegea-rss-duplication/
</guid>

Об адресах-синонимах

Мой блог доступен по нескольким другим адресам, например:

И по всем возможным сочетаниям этих доменов и путей, с www и без. Однако у меня настроены редиректы. Если вы зайдёте не по каноническому адресу, вы автоматически перейдёте на канонический — попробуйте сами.

Когда редиректы не настроены, по нескольким адресам открывается одно и то же, при этом браузер остаётся по тому адресу, по которому вы зашли и никуда не переходит.

Это ошибка в настройке сервера: кроме владельца сайта никто не знает, что эти адреса — синонимы, и для внешнего мира всё выглядит так, будто есть несколько сайтов с одинаковым содержимым. Наверное, поисковики умеют такое отслеживать и понимать, но РСС-читалке неоткуда знать, что ilyabirman.ru и ilbi.ru — это один сайт (не пойдёт же она их постранично сравнивать).

Так почему возникают дубликаты-то?

Предположим, у меня бы не было редиректов, и кто-то бы подписался на РСС с сайта ilbi.ru/blog. Тогда в его РСС-ленте «уникальный» идентификатор этой заметки выглядел бы уже вот так:

<guid isPermaLink="true">
  http://ilbi.ru/blog/all/aegea-rss-duplication/
</guid>

Само по себе это не было бы проблемой, ведь для каждого конкретного подписчика эти адреса действительно уникальны. Если кто-то подписался на ilbi.ru/blog, то в его РСС-потоке неоткуда же взяться заметке с адресом ilyabirman.ru? Есть: из кеша!

Когда читалка первый раз просит у Эгеи РСС конкретного блога, Эгея генерирует его, отдаёт читалке и сохраняет себе локально, в кеш. Поэтому когда читалка (эта же или другая) спрашивает ещё раз, Эгея просто отдаёт готовый файл, ничего не генерируя. Когда автор добавляет или редактирует заметку, Эгея удаляет устаревший кеш, и следующий соберёт только тогда, когда какая-то читалка её попросит.

Получается, что когда читалка обращается за РССом, Эгея отдаёт его из кеша, где все идентификаторы зависят от того, по какому адресу у неё спрашивали РСС первый раз после последнего изменения. Когда читалка, которая в прошлый раз видела десять заметок с идентификатором ilyabirman.ru/что-то, видит десять новых заметок с идентификаторами ilbi.ru/что-то, она думает, что перед ней новьё — вот и показывает всё это как непрочитанное.

Так падажжи

Тут у вас могут возникнуть вопросы.

— Что мешает Эгее во избежание этой проблемы писать идентификаторы всегда с одним адресом, даже если она доступна по нескольким?

Не только внешний мир без редиректа не знает, что ilyabirman.ru и ilbi.ru — это одно и тоже. Эгея, чтобы узнать, на каком сервере она работает, смотрит, по какому адресу её открыли — больше ей это узнать неоткуда. Если её открыли по адресу ilbi.ru, то в её вселенной просто не существует набора символов «ilyabirman.ru», чтобы засунуть его в РСС. То, что он оказывается в кеше — чистая случайность.

Конечно, можно вести отдельный список всех адресов, по которым данная копия движка когда-либо открывалась, и всегда ставить в РСС первый из них. Но это ужасный костыль, и если автор от одного из синонимов откажется в будущем, а он как раз окажется первым в этом списке, у него просто сломается РСС, и он никогда не поймёт, почему.

— Что мешает в качестве уникальных идентификаторов отдавать какую-то случайную (но постоянную для заметки) шестнадцатиричную фигню, чтобы вообще не завязываться на адреса?

Помимо того, что это тоже костыль и усложнение движка, проблема ещё вот в чём. Отдавать именно адрес заметки в качестве идентификатора принято в мире РСС — я за всю жизнь не видел ленты с другими идентификаторами. Я боюсь, что какие-то читалки могут на это полагаться, и что-нибудь в них сломается, если сделать иначе.

Помимо этих я могу придумать ещё много вариантов того, как обойти эту проблему, но все они имеют серьёзные недостатки. Ну, например: можно хранить раздельные кеши для всех адресов, по которым заходят в блог — и занимать в несколько раз больше места на диске, чем нужно. Или: не кешировать РСС вообще — и увеличивать нагрузку на сервер не по делу. Но главное, мне не нравится сама идея пытаться из последних сил работать в шизофреническом окружении.

Вывод

РСС ломается, потому что вы делаете странное: у вас сайт одновременно и один, и несколько. Настройте редиректы, сбросьте кеш и всё будет хорошо.

Дальше
Мои книги