Слушатель CouchDB _changes обновляет документ, что вызывает другое изменение

Я хочу написать фоновую программу, которая будет отслеживать канал _changes CouchDB и, возможно, обновлять документ. Проблема в том, что обновление вызывает еще один _change, и я получаю бесконечный цикл! Как лучше этого избежать?

Например, вот конкретный сценарий: у меня есть CouchApp, в котором пользователи изменяют документы через свой браузер. У меня также есть программа на Python, которая создает версию документа в формате PDF, а затем прикрепляет ее в виде вложенного файла к самому документу. Моя проблема в том, что выполнение вложения PUT для загрузки PDF также вызывает изменение документа. Я должен быть в состоянии сказать, вызвано ли изменение загрузкой PDF или нет. Кажется, что это должно быть легко, но я не могу придумать простой способ сделать это. Я бы предпочел, чтобы программа генератора PDF была «без гражданства», сохраняя любое необходимое состояние в самой базе данных.

Теперь это можно легко сделать, если я требую, чтобы пользователи, которые изменяют документ, устанавливали какой-то флаг в документе, чтобы указать, что его необходимо обработать. Хитрость в том, как это сделать, не требуя этого.


Я пришел к выводу, что слушатель "_changes" никогда не должен изменять документ, который он слушает. В моем случае я решил прикрепить свой PDF-файл к отдельному документу в отдельной «базе данных» в CouchDB, но используя тот же «_id», чтобы упростить сопоставление. Таким образом, я не запускаю «_change» для тех же документов, которые я слушаю. Я не мог пройти мимо необходимости требовать, чтобы каждый клиент, который изменяет документ, каким-то образом «помечал» его как требующий обработки (путем удаления существующего вложения или иной установки какого-либо «грязного» флага). После долгих размышлений я думаю, что это будет для меня эмпирическим правилом: вы не должны изменять документ после получения уведомления «_change» для этого документа. Кто-нибудь еще пришел к такому же выводу?


person Nick Perkins    schedule 20.08.2011    source источник


Ответы (1)


Используйте функцию фильтра и отфильтруйте второе изменение — либо по структуре документа изменить или установив дополнительный флаг измененному документу:

function(doc, req)
{
  if(!doc.hasStructuralChange) { //fix this
    return true;
  }
  return false;
}

or

function(doc, req)
{
  if(!doc.changed) { //set doc.changed during first update
    return true;
  }
  return false;
}

Изменить: вы можете проверить наличие вложения через if (doc._attachments)

person b_erb    schedule 20.08.2011
comment
Спасибо, это было быстро (вы ответили до того, как я добавил конкретный абзац сценария). Как проверить, есть ли в документе структурные изменения? Можете ли вы сравнить его с предыдущей версией? - person Nick Perkins; 20.08.2011
comment
Нет гарантии, что предыдущая версия доступна, поэтому вы должны убедиться, что можете определить, нуждается ли документ в обработке, используя сам документ. В вашем случае вы можете проверить заглушку PDF внутри doc._attachments. Если присутствует, ничего не делать. Если отсутствует, добавьте его. - person Robert Newson; 20.08.2011
comment
В функции filter doc вы получаете только текущую версию (ревизию после изменения), но вы можете установить такой флаг либо на стороне клиента, либо использовать обработчик обновлений и установить его автоматически. - person b_erb; 20.08.2011
comment
+1 за фильтры. @ Ник Перкинс, вы также можете фильтровать на стороне клиента, это зависит от ваших потребностей. По мере роста вашего программного обеспечения централизованные фильтры приобретают все больший смысл. PartlyCloudy верен, но я отправлю еще один ответ с некоторыми незначительными соображениями по этой теме в целом. - person JasonSmith; 21.08.2011