- Ключевые факты
- Как появляется «фантомная статья»
- Порядок, который я использую сейчас
- 1. Сначала готовлю статью и обложку локально
- 2. Загружаю обложку и сохраняю media ID
- 3. Создаю запись только со статусом draft
- 4. Проверяю ответ WordPress
- 5. И только потом дописываю covered-topics.log
- Что сработало, а что всё ещё не идеально
- Частые вопросы (FAQ)
- Почему не записывать тему в журнал в самом начале?
- Достаточно ли проверить HTTP-код 201?
- Почему нельзя просто повторить POST после таймаута?
- Что делать, если обложка загрузилась, а пост не создался?
- Почему не хранить всё состояние в WordPress?
- Итог
TL;DR: Я дописываю тему в covered-topics.log только после того, как WordPress вернул ID нового черновика. Если сделать наоборот, краткий сетевой сбой оставит в журнале «готовую» статью, которой на сайте нет, а следующий запуск решит, что тему уже использовали.
Ключевые факты
| Факт | Что это значит в моём процессе | Источник |
|---|---|---|
Новый материал создаётся запросом POST /wp/v2/posts, а в ответе есть его уникальный id | ID — мой основной признак того, что черновик действительно появился в WordPress | WordPress REST API: Posts |
Обложка загружается отдельно через POST /wp/v2/media | Успешная загрузка картинки ещё не означает, что сама статья создана | WordPress REST API: Media |
WordPress поддерживает явный статус draft, поле featured_media и массив categories | Я проверяю не только ID, но и статус, обложку и рубрику 73 | Схема записи WordPress |
| POST не относится к методам, которые стандарт HTTP объявляет идемпотентными | После неясного сетевого сбоя нельзя бездумно повторять создание: можно получить дубль | RFC 9110, раздел 9.2.2 |
Как появляется «фантомная статья»
У моего ежедневного агента есть очень простой файл памяти — covered-topics.log. В каждой строке записаны дата, буква рубрики и короткое название темы. Перед новой статьёй агент читает последнюю строку, выбирает следующую рубрику по цепочке A → B → C → D → E и проверяет, не писал ли я уже на похожую тему.
Этот файл удобен именно своей простотой: его можно открыть глазами, найти тему обычным поиском и быстро понять, почему агент выбрал сегодняшнюю рубрику. Но журнал не является WordPress. Строка в файле не доказывает, что на сайте существует соответствующий черновик.
Представим неправильный порядок. Сначала агент добавил в журнал строку о новой статье. Затем загрузил обложку, отправил материал в WordPress — и соединение оборвалось. На следующем запуске агент увидит тему в журнале и не станет повторять её. Получится запись о якобы выполненной работе без статьи. Это и есть фантом: память говорит «готово», а WordPress говорит «такого черновика нет».
Есть и обратная проблема. Сервер мог создать запись, но ответ не дошёл до агента. Если автоматически повторить тот же POST, в WordPress могут появиться два черновика. Поэтому мне недостаточно знать, что скрипт дошёл до строки отправки запроса. Мне нужен проверяемый результат.
Порядок, который я использую сейчас
1. Сначала готовлю статью и обложку локально
На этом этапе ещё ничего не меняется в журнале тем. Если генератор картинки не ответил, сработал резервный источник или водяной знак не наложился, я могу остановиться, не оставив ложный след о готовой публикации.
2. Загружаю обложку и сохраняю media ID
WordPress хранит медиа и записи как отдельные сущности. Поэтому удачный ответ от /media подтверждает только появление файла в медиатеке. Он не подтверждает статью. Полученный media ID я передаю дальше как featured_media.
3. Создаю запись только со статусом draft
В одном запросе явно передаю заголовок, HTML, ID обложки, категорию 73 и status: draft. Я не полагаюсь на значения по умолчанию: у автоматизации безопаснее назвать критичные поля прямо. Особенно статус и рубрику — это две вещи, которые потом легко не заметить при беглом просмотре.
4. Проверяю ответ WordPress
Минимальный положительный результат для меня — числовой post ID и статус draft. Дополнительно я сверяю категорию и featured media. Код ответа 2xx важен, но сам по себе это ещё не вся бизнес-проверка: сервер мог принять запрос, а нужное поле — например, SEO-мета — не сохраниться из-за конфигурации плагина.
5. И только потом дописываю covered-topics.log
Строка в журнале означает не «я придумал тему» и не «я отправил запрос», а «WordPress вернул подтверждение созданного черновика». Такая семантика делает файл полезным. Если строка есть, у меня должен быть post ID и прямая ссылка на редактор в финальном логе запуска.
Что сработало, а что всё ещё не идеально
Сработала сама идея короткого линейного журнала. Для ежедневного блога мне пока не нужна отдельная база данных только ради ротации тем. Обычный текстовый файл хорошо решает задачу памяти, остаётся читаемым и не зависит от внешнего сервиса.
Но я перестал воспринимать его как источник истины о WordPress. Источник истины для существования статьи — ответ API и сама запись на сайте. Журнал отвечает на другой вопрос: какие темы агент уже использовал и какую рубрику выбирать следующей.
Неидеальная часть — сбой после создания черновика, но до записи в файл. В этом узком окне статья уже есть, а журнал ещё не обновлён. Полностью закрыть его можно поиском по уникальному заголовку или служебному ключу перед повторным POST. Пока мой практический барьер проще: я вывожу post ID и админскую ссылку в лог и не делаю слепой автоматический повтор POST при неоднозначном ответе.
Частые вопросы (FAQ)
Почему не записывать тему в журнал в самом начале?
Потому что тогда журнал фиксирует намерение, а не результат. Любая ошибка генерации, загрузки медиа или создания поста оставит ложную отметку о выполненной статье.
Достаточно ли проверить HTTP-код 201?
Это хороший первый фильтр, но я также читаю JSON-ответ: мне нужны post ID, статус draft, правильная категория и ID обложки. Для автоматизации важен не просто успешный транспорт, а корректное состояние созданного объекта.
Почему нельзя просто повторить POST после таймаута?
Потому что POST в общем случае не идемпотентен. Первый запрос мог успеть создать запись, хотя ответ потерялся по дороге. Повтор создаст второй черновик, если заранее не проверить результат первого запроса.
Что делать, если обложка загрузилась, а пост не создался?
Не отмечать тему как завершённую. Медиафайл можно использовать при следующей попытке, если сохранён его ID, либо позже убрать вручную после проверки. Сам факт наличия картинки не должен переключать ротацию рубрик.
Почему не хранить всё состояние в WordPress?
Можно, но для моего текущего масштаба это усложняет прозрачную проверку тем. Текстовый журнал остаётся удобной памятью контент-агента, пока я чётко отделяю его от подтверждения факта создания записи.
Итог
Главное изменение — не новый инструмент, а точное значение слова «готово». Тема считается использованной только после того, как WordPress подтвердил новый черновик и вернул его ID. Сначала внешний результат, потом локальная отметка: этот порядок не устраняет все возможные сбои, но не даёт журналу уверенно рассказывать о статье, которой нет.
Автор: Denis | Дата: 15 октября 2026 | Обновлено: 15 октября 2026
Denis — трейдер с 10+ летним опытом на форексе и крипторынках











