Created
April 7, 2010 20:49
-
-
Save willconant/359435 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// saves local changes to articles. mergeParentGuid should be null unless we are resolving a merge conflict | |
function editArticle(articleName, content, mergeParentGuid, callback) { | |
flow.exec( | |
function() { | |
// find my current head for this article | |
db.sync.findLastLocal("articleHeads", {name: articleName}, this) | |
},function(err, articleHead) { | |
if (err) throw err | |
var article = { | |
name: articleName, | |
parent1Guid: articleHead ? articleHead.currentGuid : null, | |
parent2Guid: mergeParentGuid, | |
content: content | |
} | |
// save the article in a sync table getting a guid back | |
db.sync.save("articles", article, this) | |
},function(err, newGuid) { | |
if (err) throw err | |
// save an entry in the articleHeads table pointing at the latest | |
// version of this article | |
db.sync.save("articleHeads", {name: articleName, currentGuid: newGuid}, callback) | |
} | |
) | |
} | |
// this is a quick-and-dirty bit of code for pulling remote articles and marking conflicts | |
db.sync.pull(remoteNode, "articles", function(articlesSyncResponse) { | |
articlesSyncResponse.addListener("close", function(err) { | |
if (err) throw err | |
db.sync.pull(remoteNode, "articleHeads", function(headsSyncResponse) { | |
// I think this is most convenient if the response is an EventEmitter | |
// The "receive" event is emitted for each new row from the remote node. | |
// By the time "receive" is fired, the node is already saved in your | |
// local db. (The idea being that NoSQLite keeps track of which rows | |
// it has received from each node, so you don't have to. That's the | |
// automatic part of the synchronization layer.) | |
var latestRemoteHeadGuids = {} | |
headsSyncResponse.addListener("receive", function(remoteHead) { | |
latestRemoteHeadGuids[remoteHead.articleName] = remoteHead.currentGuid | |
}) | |
headsSyncResponse.addListener("close", function(err) { | |
if (err) throw err | |
// now I have all of the heads of remotely changed documents... | |
// we can actually look for conflicts now. | |
for (var articleName in latestRemoteHeadGuids) { | |
db.sync.findLastLocal("articleHeads", {name: articleName}, function(localHead) { | |
// sometimes I hate asynchronous programming | |
// saving keystrokes... | |
var remoteGuid = latestRemoteHeadGuids[articleName] | |
if (localHead === null) { | |
// simple case, we don't even have that article | |
db.sync.save("articleHeads", {name: articleName, currentGuid: remoteGuid}) | |
} | |
else { | |
articleIsDescendantOf(remoteGuid, localHead.currentGuid, function(isDescendant) { | |
if (isDescendant) { | |
// this is also a simple case akin to Git's "fast-forward" | |
db.sync.save("articleHeads", {name: articleName, currentGuid: remoteGuid}) | |
} | |
else { | |
// This means we have a conflict. | |
// keep remotes from pulling until conflict is resolved | |
db.sync.disableSync("articles") | |
db.sync.disableSync("articleHeads") | |
// save conflict state in local tables (i think you should support | |
// upserts in local non-sync tables). | |
db.upsert("articleConflicts", {articleName: articleName}, {articleName: articleName, conflict: true}) | |
} | |
}) | |
} | |
}) // end of findLastLocal("articleHeads"... | |
} // end for (var articleName... this is why I wrote flow-js | |
}) // end "close" handler on headsSyncResponse | |
}) // end db.sync.pull articleHeads | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment