Skip to content

Commit

Permalink
Initial readme
Browse files Browse the repository at this point in the history
Also added /example and made _load private.
  • Loading branch information
felixge committed Sep 24, 2010
1 parent cde9bad commit 95b72b1
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 48 deletions.
111 changes: 102 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,105 @@
# v0.2 branch
# node-dirty

This is me hacking away at a new version of dirty. The main concept stays, but things will be simpler, faster, compatible with node 0.1.30+ and less buggy : ).
## Purpose

# Todo
A tiny & fast key value store with append-only disk log. Ideal for apps with < 1 million records.

* flush(cb) does not really behave properly
* dirty.close()
* dirty.forEach() or dirty.filter()
* More testing / tinkering
* Final Benchmarks
* Update docs
## Installation

npm install dirty

## Why dirty?

This module is called dirty because:

* The file format is newline seperated JSON
* Your database lives in the same process as your application, they share memory
* There is no query language, you just `forEach` through all records

So dirty means that you will hit a very hard wall with this database after ~1 million records,
but it is a wonderful solution for anything smaller than that.

## Tutorial

require('../test/common');
var db = require('dirty')('user.db');

db.on('load', function() {
db.set('john', {eyes: 'blue'});
console.log('Added john, he has %s eyes.', db.get('john').eyes);

db.set('bob', {eyes: 'brown'}, function() {
console.log('User bob is now saved on disk.')
});

db.forEach(function(key, val) {
console.log('Found key: %s, val: %j', key, val);
});
});

db.on('drain', function() {
console.log('All records are saved on disk now.');
});

Output:

Added john, he has blue eyes.
Found key: john, val: {"eyes":"blue"}
Found key: bob, val: {"eyes":"brown"}
User bob is now saved on disk.
All records are saved on disk now.

## API

### new Dirty([path])

Creates a new dirty database. If `path` does not exist yet, it is created. You
can also omit the `path` if you don't want disk persistence (useful for testing).

The constructor can be invoked in multiple ways:

require('dirty')('my.db');
require('dirty').Dirty('my.db');
new (require('dirty'))('my.db');
new (require('dirty').Dirty)('my.db');

### dirty.path

The path of the dirty database.

### dirty.set(key, value, [cb])

Set's the given `key` / `val` pair. The state of the database is affected instantly,
the optional `cb` callback is fired when the record was written to disk.

`val` can be any JSON-serializable type, it does not have to be an object.

### dirty.get(key)

Retrieves the value for the given `key`.

### dirty.rm(key, cb)

Removes the record with the given `key`. This is identical to setting the `key`'s value
to `undefined`.

### dirty.forEach(fn)

Calls the given `fn` function for every document in the database. The passed
arguments are `key` and `val`. You can return `false` to abort a query (useful
if you are only interested in a limited number of records).

This function is blocking and runs at ~4 Mhz.

### dirty event: 'load' ()

Emitted once the database file has finished loading. It is not safe to access
records before this event fires. Writing records however should be fine.

### dirty event: 'drain' ()

Emitted whenever all records have been written to disk.

## License

node-dirty is licensed under the MIT license.
19 changes: 19 additions & 0 deletions example/bob.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require('../test/common');
var db = require('dirty')(TEST_TMP+'/bob.dirty');

db.on('load', function() {
db.set('john', {eyes: 'blue'});
console.log('Added john, he has %s eyes.', db.get('john').eyes);

db.set('bob', {eyes: 'brown'}, function() {
console.log('User bob is now saved on disk.')
});

db.forEach(function(key, val) {
console.log('Found key: %s, val: %j', key, val);
});
});

db.on('drain', function() {
console.log('All records are saved on disk now.');
});
68 changes: 34 additions & 34 deletions lib/dirty/dirty.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,46 @@ var Dirty = exports.Dirty = function(path) {
this._readStream = null;
this._writeStream = null;

this.load();
this._load();
};

sys.inherits(Dirty, EventEmitter);
Dirty.Dirty = Dirty;
module.exports = Dirty;

Dirty.prototype.load = function() {
Dirty.prototype.set = function(key, val, cb) {
if (val === undefined) {
delete this._docs[key];
} else {
this._docs[key] = val;
}

if (!cb) {
this._queue.push(key);
} else {
this._queue.push([key, cb]);
}

this._maybeFlush();
};

Dirty.prototype.get = function(key) {
return this._docs[key];
};

Dirty.prototype.rm = function(key, cb) {
this.set(key, undefined, cb);
};

Dirty.prototype.forEach = function(fn) {
for (var key in this._docs) {
if (fn(key, this._docs[key]) === false) {
break;
}
}
};

Dirty.prototype._load = function() {
if (!this.path) {
return;
}
Expand Down Expand Up @@ -89,30 +121,6 @@ Dirty.prototype.load = function() {
});
};

Dirty.prototype.get = function(key) {
return this._docs[key];
};

Dirty.prototype.set = function(key, val, cb) {
if (val === undefined) {
delete this._docs[key];
} else {
this._docs[key] = val;
}

if (!cb) {
this._queue.push(key);
} else {
this._queue.push([key, cb]);
}

this._maybeFlush();
};

Dirty.prototype.rm = function(key, cb) {
this.set(key, undefined, cb);
};

Dirty.prototype._maybeFlush = function() {
if (this.flushing || !this.path || !this._queue.length) {
return;
Expand Down Expand Up @@ -165,11 +173,3 @@ Dirty.prototype._flush = function() {

this._queue = [];
};

Dirty.prototype.forEach = function(fn) {
for (var key in this._docs) {
if (fn(key, this._docs[key]) === false) {
break;
}
}
};
10 changes: 5 additions & 5 deletions test/simple/test-dirty.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require('../common');
var Dirty = require('dirty'),
EventEmitter = require('events').EventEmitter,
dirtyLoad = Dirty.prototype.load,
dirtyLoad = Dirty.prototype._load,
constants = require('constants'),
gently,
dirty;
Expand All @@ -11,7 +11,7 @@ var Dirty = require('dirty'),

(function testBasic() {
var PATH = '/foo/bar';
Dirty.prototype.load = gently.expect(function() {
Dirty.prototype._load = gently.expect(function() {
assert.equal(this.path, PATH);
});
var dirty = new Dirty(PATH);
Expand All @@ -25,15 +25,15 @@ var Dirty = require('dirty'),
})();

(function testWithoutNew() {
Dirty.prototype.load = gently.expect(function() {});
Dirty.prototype._load = gently.expect(function() {});
var dirty = Dirty();
})();

(function testOldSchoolClassName() {
assert.strictEqual(Dirty, Dirty.Dirty);
})();

Dirty.prototype.load = function(){};
Dirty.prototype._load = function(){};
gently.verify();
})();

Expand All @@ -44,7 +44,7 @@ function test(fn) {
gently.verify();
}

test(function load() {
test(function _load() {
(function testNoPath() {
gently.expect(HIJACKED.fs, 'createWriteStream', 0);
dirtyLoad.call(dirty);
Expand Down

0 comments on commit 95b72b1

Please sign in to comment.