From ced0f36cbf7983853a9d7060694b9c58818e6d6b Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 25 Jul 2015 12:06:12 -0600 Subject: [PATCH] add README.md --- README.md | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..1bfeca7 --- /dev/null +++ b/README.md @@ -0,0 +1,115 @@ +memstore Cluster +================ + +A very simple in-memory object store for use with node cluster +(or even completely and unrelated node processes). + +Node.js runs on a single core, which isn't very effective. + +You can run multiple Node.js instances to take advantage of multiple cores, +but if you do that, you can't share memory between processes. + +This module will either run client-server style in environments that benefit from it +(such as the Raspberry Pi 2 with 4 cores), or in-process for environments that don't +(such as the Raspberry Pi B and B+). + +**Note**: Most people would probably prefer to just use Redis rather than +wrap a dumb memstore as a service... but I am not most people. + +Also works with **level-session-store** (leveldb), **connect-session-knex** (SQLite3), +**session-file-store** (fs), and any other embedded / in-process store. + +Usage +===== + +The default behavior is to try to connect to a master and, if that fails, to become the master. + +However, if you are in fact using the `cluster` rather than spinning up random instances, +you'll probably prefer to use this pattern: + +```js +var cluster = require('cluster'); +var store = require('memstore-cluster'); +var numCores = require('os').cpus().length; + +var opts = { + sock: '/tmp/mydb.memstore.sock' + + // If left 'null' or 'undefined' this defaults to a similar memstore + // with no special logic for 'cookie' or 'expires' +, store: cluster.isMaster && new require('express-session/session/memory')() + + // a good default to use for instances where you might want + // to cluster or to run standalone, but with the same API +, serve: cluster.isMaster +, connect: cluster.isWorker +, standalone: (1 === numCores) // overrides serve and connect +}; + +memstore.create(opts).then(function (store) { + // same api as new sqlite3.Database(options.filename) + + store.get(id, function (err, data) { + console.log(data); + }); + + // app.use(expressSession({ secret: 'keyboard cat', store: store })); +}); + +process.on('unhandledPromiseRejection', function (err) { + console.error('Unhandled Promise Rejection'); + console.error(err); + console.error(err.stack); + + throw err; +}); +``` + +If you wish to always use clustering, even on a single core system, see `test-cluster.js`. + +Likewise, if you wish to use standalone mode in a particular worker process see `test-standalone.js`. + +API +=== + +This is modeled after Express' +[Session Store Implementation](https://github.com/expressjs/session#session-store-implementation) + +**Note**: These are only exposed if the underlying store supports them. + +CRUD methods +------------ + +* `store.set(id, data, fn) => (error)` +* `store.get(id, fn) => (error, data)` +* `store.touch(id, data, fn) => (error)` +* `store.destroy(id, fn) => (error)` + +Helpers +------- + +* `store.all(fn) => (error, array)` +* `store.clear(fn) => (error)` +* `store.length(fn) => (error, length)` + +See @4.x for full details + +Standalone / Master Mode is in-process +======================== + +The `master` in the cluster (meaning `opts.serve = true`) will directly hold the `express-session/session/memory` +memory store. + +Likewise, when only one process is being used (`opts.standalone = true`) the listener is +not started and API is completely in-process. + +If you take a look at `wrapper.js` you'll see that it's a rather simple memory store instance. + +Security Warning +================ + +Note that any application on the system could connect to the socket. + +In the future I may add a `secret` field in the options object to be +used for authentication across processes. This would not be difficult, +it's just not necessary for my use case at the moment.