offline/online 同步的 Meteor GroundDB 粒度

Meteor GroundDB granularity for offline/online syncing

假设两个用户在离线时对同一文档进行了更改,但更改的是文档的不同部分。如果用户2在用户1之后重新上线,用户1所做的更改是否会丢失?

在我的数据库中,每一行包含一个JS对象,其中一个属性是一个数组。该数组绑定到界面上的一系列复选框。我想要的是,如果两个用户对这些复选框进行了更改,则根据进行更改的时间而不是同步发生的时间,为每个复选框单独保留最新更改。 GroundDB 是实现这一目标的合适工具吗?有什么方法可以添加一个事件处理程序,我可以在其中添加一些在同步发生时触发的逻辑,并负责合并?

简短的回答是 "yes" none 地面数据库版本具有冲突解决方案,因为逻辑是自定义的,具体取决于冲突解决的行为,例如。如果您想自动化或让用户参与。

旧的 Ground DB 仅仅依赖于 Meteor 的冲突解决(服务器的最新数据获胜)我猜你会看到一些问题,这取决于客户端何时上线的顺序。

Ground db II 没有恢复方法,它或多或少只是一种离线缓存数据的方法。它正在观察可观察的来源。

我想您可以为 GDB II 创建一个中间件观察器 - 一个在执行更新和更新客户端之前检查本地数据的观察器 or/and 调用服务器来更新服务器数据。这样你就有办法处理冲突了。

我想记得写一些支持 "deletedAt"/"updatedAt" 的代码来处理某些类型的冲突,但是冲突处理程序在大多数情况下应该是自定义的。 (为可重用的冲突处理程序打开大门可能会有用)

如果您不"soft"通过诸如使用"deletedAt"实体之类的方式进行删除,那么知道何时删除数据可能会很棘手。

"rc"分支当前为grounddb-caching-2016版本"2.0.0-rc.4",

我在想类似的事情: (注意没测试过,直接用SO写的)

// Create the grounded collection
foo = new Ground.Collection('test');

// Make it observe a source (it's aware of createdAt/updatedAt and
// removedAt entities)
foo.observeSource(bar.find());

bar.find() returns 带有函数的游标 observe 我们的中间件应该做同样的事情。让我们为它创建一个 createMiddleWare 助手:

function createMiddleWare(source, middleware) {
  const cursor = (typeof (source||{}).observe === 'function') ? source : source.find();
  return {
    observe: function(observerHandle) {
      const sourceObserverHandle = cursor.observe({
        added: doc => {
          middleware.added.call(observerHandle, doc);
        },
        updated: (doc, oldDoc) => {
          middleware.updated.call(observerHandle, doc, oldDoc);
        },
        removed: doc => {
          middleware.removed.call(observerHandle, doc);
        },
      });
      // Return stop handle
      return sourceObserverHandle;
    }
  };
}

用法:

foo = new Ground.Collection('test');

foo.observeSource(createMiddleware(bar.find(), {
  added: function(doc) {
    // just pass it through
    this.added(doc);
  },
  updated: function(doc, oldDoc) {
    const fooDoc = foo.findOne(doc._id);

    // Example of a simple conflict handler:
    if (fooDoc && doc.updatedAt < fooDoc.updatedAt) {
      // Seems like the foo doc is newer? lets update the server...
      // (we'll just use the regular bar, since thats the meteor
      // collection and foo is the grounded data
      bar.update(doc._id, fooDoc);
    } else {
      // pass through
      this.updated(doc, oldDoc);
    }
  },
  removed: function(doc) {
    // again just pass through for now
    this.removed(doc);
  }
}));