Permalink
Browse files

Initial readme

Also added /example and made _load private.
  • Loading branch information...
1 parent cde9bad commit 95b72b13c0892e73e369d66cde5ce376bfea9ef4 @felixge felixge committed Sep 24, 2010
Showing with 160 additions and 48 deletions.
  1. +102 −9 README.md
  2. +19 −0 example/bob.js
  3. +34 −34 lib/dirty/dirty.js
  4. +5 −5 test/simple/test-dirty.js
View
@@ -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.
View
@@ -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.');
+});
View
@@ -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;
}
@@ -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;
@@ -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;
- }
- }
-};
@@ -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;
@@ -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);
@@ -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();
})();
@@ -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);

0 comments on commit 95b72b1

Please sign in to comment.