histo-revisions
v0.0.2
Published
peer-to-peer synchronizable database written in javascript
Downloads
1
Readme
A database that tracks changing revisions of data.
Each revision is accessible through a unique ref which is based on a cryptographic hash of the data's content and history. A ref is similar to a git commit hash.
Each written data object is combined with a link to its ancestors - the combination is called a revision. A revision can be compared to a git commit object.
Revisions look like this:
{
ancestors: ['someref'],
data: 'some data'
}
The cryptographic hash of the revision is its ref.
##Documentation
revisions.createDB(opts) -> db
db.put(data, [ancestorRefs], cb)
db.get([ref], cb)
db.head(cb) -> ref
db.setHead(ref, [previousHead], cb)
db.remoteHead(remoteName, cb)
db.setRemoteHead(remoteName, ref, cb)
db.refDifference(fromRef, toRef, cb)
db.ancestors(ref, cb)
db.commonAncestor(ref1, ref2, cb)
db.createStream(refs) -> stream
db.writeStream(stream, cb)
revisions.createSynchronizer(sourceDB, targetDB) -> synchronizer
synchronizer.run(cb)
- Merging synchronized data
###require('histo-revisions') -> revisions
{
name: 'your-db-name', // will generate uuid if omitted
revisionStore: revStore,
branchStore: branchStore
}
With revStore
being an object with a content-addressable store interface:
put(data, cb)
: should write some data and responds with a unique identifier of the data in the callbackget(identifier, cb)
: should respond with the data in the callbackdel(identifier, cb)
: should delete the data for the specified identifier
branchStore
is expected to be a simple key-value store interface:
put(key, value, cb)
get(key, cb)
del(key, cb)
The difference is computed using the graph-difference module.
The common ancestor is computed using the ancestor module.
name
head(cb)
refDifference(fromRef, toRef, cb)
createStream(refs)
->stream
targetDB
requires the following set of functions:
head(cb)
remoteHead(remoteName, cb)
writeStream(stream, cb)
setRemoteHead(remoteName, ref, cb)
function readRemoteRev(db, remoteName, cb) {
db.remoteHead(remoteName, function(err, remoteHead) {
db.get(remoteHead, function(err, remoteData) {
cb(null, {head: remoteHead, data: remoteData});
});
});
}
function readLocalRev(db, cb) {
db.head(function(err, localHead) {
db.get(localHead, function(localData) {
cb(null, {head: localHead, data: remoteData});
});
});
}
readRemoteRev(targetDB, 'your-remote-name', function(err, remoteRev) {
readLocalRev(targetDB, function(err, localRev) {
var mergedData = yourMergeFunction(remoteRev.data, localRev.data);
var ancestors = [remoteRev.head, localRev.head];
targetDB.put(mergedData, ancestors, function(err, mergedRef) {
targetDB.setHead(mergedRef, localRev.head, function(err) {
// on err repeat merging with new local head
});
});
});
});
##Todo
- list of remotes
- garbage collect history
##Contributors This project was created by Mirko Kiefer (@mirkokiefer).