Как разрешать конфликты с непрерывной репликацией

Я новичок как в CouchDB, так и в PouchDB, и использую его для создания системы управления контактами, которая синхронизируется между мобильными и настольными устройствами и может использоваться в автономном режиме. Я вижу, что использовать PouchDB бесконечно проще, чем писать бэкэнд PHP/MySQL.

Я успешно использую его, и когда я вношу противоречивые изменения на автономных устройствах, CouchDB использует алгоритм для произвольного выбора победителя, а затем правильно отправляет его на все устройства.

Я хотел бы реализовать собственный алгоритм для объединения конфликтующих записей. Вот алгоритм, который я хотел бы использовать:

  1. Если запись удаляется на одном клиенте и просто обновляется на другом, обновленная версия выигрывает, если только оба клиента не согласятся на удаление.
  2. Запись с самой последней «измененной» отметкой времени становится главной, а более старая запись становится вторичной.
  3. Любые поля, которые существуют только во вторичном (или пустые в главном), перемещаются в главный.
  4. Основная ревизия сохраняется, а вторичная удаляется.

В руководстве CouchDB есть хорошее объяснение, но я понятия не имею, как реализовать это с помощью PouchDB API во время непрерывной репликации. Согласно PouchDB API, в параметрах репликации есть прослушиватель onChange, но я не понимаю, как использовать его для перехвата конфликтов.

Если бы кто-то мог написать краткое руководство, включающее пример кода, я и, уверен, многие другие пользователи PouchDB были бы признательны за это!


person Colin Skow    schedule 25.08.2013    source источник


Ответы (1)


Написать статью с примерами того, как именно управлять разрешением конфликтов, это действительно хорошая идея, это может сбивать с толку, но с отсутствием одного

Идея та же, что и в CouchDB: для разрешения конфликтов вы удаляете ревизии, которые не выиграли (и при необходимости пишете нового победителя).

# 1 — это то, как в любом случае работает разрешение конфликтов CouchDB, поэтому вам не нужно об этом беспокоиться, удаленные листья не конфликтуют.

function onChange(doc) { 
  if (!doc._conflicts) return;
    collectConflicts(doc._conflicts, function(docs) {
      var master = docs.sort(byTime).unshift();
      for (var doc in docs) {
        for (var prop in doc) {
          if (!(prop in master)) { 
            master[prop] = doc[prop];
          } 
        }
      }
      db.put(master, function(err) {
        if (!err) { 
          for (var doc in docs) {
            db.remove(doc);
          }
        }
      });     
    });
  }
}

db.changes({conflicts: true, onChange: onChange});

Это потребует обработки ошибок и т. д., и его можно было бы написать намного лучше, это был просто быстрый рисунок на салфетке того, как может выглядеть код.

person Dale    schedule 18.09.2013
comment
Большое спасибо Дале! Это очень помогает. - person Colin Skow; 08.11.2013