让我们假设两个用户在离线时对同一文档进行更改,但是在文档的不同部分。如果用户2在用户1之后重新上线,用户1所做的更改是否会丢失?
在我的数据库中,每行包含一个JS对象,该对象的一个属性是一个数组。此数组绑定到接口上的一系列复选框。我想要的是,如果两个用户对这些复选框进行了更改,则根据更改的时间而不是同步发生的时间,为每个复选框单独保留最新的更改。 GroundDB是实现这一目标的合适工具吗?是否有任何意义来添加一个事件处理程序,我可以在其中添加一些逻辑,这些逻辑将在同步发生时触发,并且会处理合并?
答案 0 :(得分:1)
简短的回答是“是”没有任何基础数据库版本具有冲突解决方案,因为逻辑是自定义的,具体取决于冲突解决的行为,例如。如果你想自动化或让用户参与。
旧的Ground DB只依赖于Meteor的冲突解决方案(服务器的最新数据获胜)我猜你可以看到一些问题,具体取决于哪个客户端上线的顺序。
Ground db II没有方法恢复它或多或少只是一种离线缓存数据的方法。它正在观察一个可观察的来源。
我猜你可以为GDB II创建一个中间件观察者 - 在更新之前检查本地数据并更新客户端或/并调用服务器来更新服务器数据。这样你就有办法处理冲突。
我想要记住为某些类型的冲突处理编写一些支持“deletedAt”/“updatedAt”的代码,但是冲突处理程序在大多数情况下也应该是自定义的。 (为可重用的冲突处理程序打开大门可能很有用)
如果您不通过使用“deletedAt”实体进行“软”删除,尤其了解何时删除数据可能会非常棘手。
答案 1 :(得分:0)
" rc" branch目前是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()
返回一个带有函数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);
}
}));