Skip to content

Instantly share code, notes, and snippets.

@rla
Created January 27, 2012 19:06
Show Gist options
  • Save rla/1690375 to your computer and use it in GitHub Desktop.
Save rla/1690375 to your computer and use it in GitHub Desktop.
Syncing with conflict resolution
Client.prototype.sync = function(server) {
var scs = server.changesAfter(this.rev);
var ccs = this.currentChanges();
var conflicting = {}; // id -> true
var client = this;
// Find and resolve conflicting changes.
scs.forEach(function(sc) {
ccs.forEach(function(cc) {
if (sc.id === cc.id) {
console.log('Conflicting for id ' + sc.id);
conflicting[sc.id] = true;
// Current resolution: prefer master
// Which changes to send to master (below) also depend on it.
if (sc.op === 'U') {
client.data[sc.id] = server.data[sc.id];
} else if (sc.op === 'D') {
delete client.data[sc.id];
}
}
});
});
// Find and apply non-conflicting server changes.
scs.forEach(function(sc) {
if (conflicting[sc.id] === undefined) {
if (sc.op === 'U') {
client.data[sc.id] = server.data[sc.id];
} else if (sc.op === 'D') {
delete client.data[sc.id];
}
}
});
// Find and apply non-conflicting client changes.
ccs.forEach(function(cc) {
if (conflicting[cc.id] === undefined) {
if (cc.op === 'U') {
server.data[cc.id] = client.data[cc.id];
} else if (cc.op === 'D') {
delete server.data[cc.id];
}
}
});
// Push rev.
server.rev += 1;
this.rev = server.rev;
// Transfer client changes with increased revision number.
// Conflicting changes are not sent since we chose to prefer master.
ccs.forEach(function(cc) {
if (conflicting[cc.id] === undefined) {
server.changes.push({ id: cc.id, rev: client.rev });
}
});
// Cleanup.
this.changes = [];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment