mirror of
https://github.com/samsonjs/kwikemon.git
synced 2026-04-03 10:35:49 +00:00
Compare commits
No commits in common. "master" and "v0.0.2" have entirely different histories.
20 changed files with 241 additions and 746 deletions
74
Readme.md
74
Readme.md
|
|
@ -11,27 +11,28 @@ npm install -g kwikemon
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
$ kwikemond &
|
$ kwikemond &
|
||||||
$ curl -s localhost/nginx_status | grep Active | kwikemon write nginx-connections
|
$ curl -s localhost/nginx_status | grep Active | kwikemon nginx-connections
|
||||||
$ curl localhost:1111/nignx-connections
|
$ curl localhost:1111/nignx-connections
|
||||||
Active connections: 316
|
Active connections: 316
|
||||||
$ kwikemon set foo bar
|
$ kwikemon foo bar
|
||||||
$ curl localhost:1111/
|
$ curl localhost:1111/
|
||||||
foo: bar
|
foo: bar
|
||||||
nginx-connections: Active connections: 316
|
nginx-connections: Active connections: 316
|
||||||
|
|
||||||
Here's how it works:
|
Here's how it works:
|
||||||
|
|
||||||
- call `kwikemon set thing status` to set the text for the monitor named "thing"
|
- call `kwikemon thing status` to set the text for the monitor named "thing"
|
||||||
- fire up the server, `kwikemond`, that serves up these monitors in a big list or individually
|
- fire up the server, `kwikemond`, that serves up these monitors in a big list or individually
|
||||||
|
|
||||||
Alternatively:
|
Alternatively:
|
||||||
|
|
||||||
- continuously pipe data to `kwikemon write <name of thing you are watching>` on stdin
|
- continuously pipe data to `kwikemon <name of thing you are watching>` on stdin
|
||||||
- every time a full line of text is received on stdin it becomes the new status for <name of thing you are watching>
|
- every time a full line of text is received on stdin it becomes the new status for <name of thing you are watching>
|
||||||
|
|
||||||
To see everything `kwikemon` can do run `kwikemon help`.
|
To see everything `kwikemon` can do run it without arguments.
|
||||||
|
|
||||||
$ kwikemon help
|
# or with -h or --help
|
||||||
|
$ kwikemon
|
||||||
|
|
||||||
This is very much a work in progress.
|
This is very much a work in progress.
|
||||||
|
|
||||||
|
|
@ -43,12 +44,12 @@ You can use kwikemon as a library.
|
||||||
var kwikemon = require('kiwkemon');
|
var kwikemon = require('kiwkemon');
|
||||||
|
|
||||||
kwikemon.set('foo', 'bar', function(err) {
|
kwikemon.set('foo', 'bar', function(err) {
|
||||||
kwikemon.get('foo', function(err, text) {
|
kwikemon.fetch('foo', function(err, text) {
|
||||||
console.log('foo = ' + text);
|
console.log('foo = ' + text);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
kwikemon.getAll(function(err, monitors) {
|
kwikemon.fetchAll(function(err, monitors) {
|
||||||
Object.keys(monitors).forEach(function (name) {
|
Object.keys(monitors).forEach(function (name) {
|
||||||
console.log(name + ' = ' + monitors[name]);
|
console.log(name + ' = ' + monitors[name]);
|
||||||
});
|
});
|
||||||
|
|
@ -69,14 +70,28 @@ A monitor named `nginx` stores its data in the hash `kwikemon:monitor:nginx`. Ha
|
||||||
are:
|
are:
|
||||||
|
|
||||||
- text
|
- text
|
||||||
- expire
|
|
||||||
- created
|
- created
|
||||||
- modified
|
- modified
|
||||||
- updates
|
- updates
|
||||||
|
|
||||||
The list of all monitors is a set stored at `kwikemon:monitors`.
|
The list of all monitors is a set stored at `kwikemon:monitors`.
|
||||||
|
|
||||||
#### Set
|
#### List
|
||||||
|
|
||||||
|
This is when you should clean out expired entries.
|
||||||
|
|
||||||
|
names = redis.smembers("kwikemon:monitors")
|
||||||
|
monitors = {}
|
||||||
|
for name in names:
|
||||||
|
if redis.exists("kwikemon:monitor:$name"):
|
||||||
|
monitors[name] = redis.hget("kwikemon:monitor:$name", "text")
|
||||||
|
return monitors
|
||||||
|
|
||||||
|
#### Read
|
||||||
|
|
||||||
|
redis.hgetall("kwikemon:monitor:nginx")
|
||||||
|
|
||||||
|
#### Update
|
||||||
|
|
||||||
exists = redis.exists("kwikemon:monitor:nginx")
|
exists = redis.exists("kwikemon:monitor:nginx")
|
||||||
if exists:
|
if exists:
|
||||||
|
|
@ -96,48 +111,11 @@ The list of all monitors is a set stored at `kwikemon:monitors`.
|
||||||
# optional
|
# optional
|
||||||
redis.expire("kwikemon:monitor:nginx", <ttl>)
|
redis.expire("kwikemon:monitor:nginx", <ttl>)
|
||||||
|
|
||||||
#### Get
|
#### Delete
|
||||||
|
|
||||||
redis.hgetall("kwikemon:monitor:nginx")
|
|
||||||
|
|
||||||
#### Remove
|
|
||||||
|
|
||||||
redis.del("kwikemon:monitor:nginx")
|
redis.del("kwikemon:monitor:nginx")
|
||||||
redis.srem("kwikemon:monitors", "nginx")
|
redis.srem("kwikemon:monitors", "nginx")
|
||||||
|
|
||||||
#### Sweep
|
|
||||||
|
|
||||||
Clean out expired monitors. Call this before anything that relies on counting or iterating through all monitors.
|
|
||||||
|
|
||||||
for name in redis.smembers("kwikemon:monitors"):
|
|
||||||
if not redis.exists("kwikemon:monitor:$name"):
|
|
||||||
remove(name)
|
|
||||||
|
|
||||||
#### Count
|
|
||||||
|
|
||||||
Sweep before running a count.
|
|
||||||
|
|
||||||
sweep()
|
|
||||||
redis.scard("kwikemon:monitors")
|
|
||||||
|
|
||||||
#### List names
|
|
||||||
|
|
||||||
Sweep before listing.
|
|
||||||
|
|
||||||
sweep()
|
|
||||||
redis.smembers("kwikemon:monitors")
|
|
||||||
|
|
||||||
#### Get all
|
|
||||||
|
|
||||||
Sweep before geting all.
|
|
||||||
|
|
||||||
sweep()
|
|
||||||
monitors = {}
|
|
||||||
for name in list():
|
|
||||||
if redis.exists("kwikemon:monitor:$name"):
|
|
||||||
monitors[name] = get(name)
|
|
||||||
return monitors
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
116
app.js
116
app.js
|
|
@ -1,116 +0,0 @@
|
||||||
// Copyright 2013 Sami Samhuri
|
|
||||||
|
|
||||||
var express = require('express')
|
|
||||||
, Negotiator = require('negotiator')
|
|
||||||
, kwikemon = require('./kwikemon.js')
|
|
||||||
, app = module.exports = express()
|
|
||||||
, version = require('./version.js')
|
|
||||||
;
|
|
||||||
|
|
||||||
// Middleware
|
|
||||||
app.use(express.favicon('/dev/null'));
|
|
||||||
app.use(express.logger());
|
|
||||||
app.use(express.static(__dirname + '/public'));
|
|
||||||
|
|
||||||
// Views
|
|
||||||
app.set('view engine', 'jade');
|
|
||||||
app.set('views', __dirname + '/views');
|
|
||||||
|
|
||||||
// Routes
|
|
||||||
app.get('/', route('monitors', getMonitors));
|
|
||||||
app.get('/:name', route('monitor', getMonitor));
|
|
||||||
|
|
||||||
function route(template, buildContext) {
|
|
||||||
return function(req, res) {
|
|
||||||
buildContext(req, res, function(err, ctx) {
|
|
||||||
if (err) {
|
|
||||||
var message = err.message || String(err)
|
|
||||||
, status = message == 'not found' ? 404 : 500
|
|
||||||
;
|
|
||||||
res.format({
|
|
||||||
html: function() {
|
|
||||||
res.render('error', {
|
|
||||||
version: version,
|
|
||||||
pageTitle: 'Error',
|
|
||||||
err: err
|
|
||||||
});
|
|
||||||
},
|
|
||||||
text: function() {
|
|
||||||
res.send(renderText('error', { err: err }));
|
|
||||||
},
|
|
||||||
json: function() {
|
|
||||||
res.json({ message: message });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ctx = ctx || {};
|
|
||||||
res.format({
|
|
||||||
html: function() {
|
|
||||||
ctx.version = version;
|
|
||||||
res.render(template, ctx);
|
|
||||||
},
|
|
||||||
text: function() {
|
|
||||||
res.send(renderText(template, ctx));
|
|
||||||
},
|
|
||||||
json: function() {
|
|
||||||
res.json(ctx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rendering
|
|
||||||
|
|
||||||
function renderText(template, ctx) {
|
|
||||||
var text;
|
|
||||||
switch (template) {
|
|
||||||
case 'monitor':
|
|
||||||
text = String(ctx.monitor.text);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'monitors':
|
|
||||||
text = Object.keys(ctx.monitors).sort().map(function(name) {
|
|
||||||
return name + ': ' + ctx.monitors[name].text;
|
|
||||||
}).join('\n');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'error':
|
|
||||||
text = ctx.err.message || String(ctx.err);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error('unknown text template: ' + template);
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// Request handlers //
|
|
||||||
//////////////////////
|
|
||||||
|
|
||||||
function getMonitors(req, res, cb) {
|
|
||||||
kwikemon.getAll(function(err, monitors) {
|
|
||||||
cb(err, err ? null : {
|
|
||||||
pageTitle: 'Monitors',
|
|
||||||
monitors: monitors
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMonitor(req, res, cb) {
|
|
||||||
var name = req.params.name;
|
|
||||||
kwikemon.get(name, function(err, mon) {
|
|
||||||
if (!mon) {
|
|
||||||
err = new Error('not found');
|
|
||||||
}
|
|
||||||
cb(err, err ? null : {
|
|
||||||
pageTitle: mon.name,
|
|
||||||
monitor: mon
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
220
bin/kwikemon
220
bin/kwikemon
|
|
@ -2,166 +2,120 @@
|
||||||
|
|
||||||
var kwikemon = require('../kwikemon.js');
|
var kwikemon = require('../kwikemon.js');
|
||||||
|
|
||||||
var commands = {};
|
function usage() {
|
||||||
function defineCommand(name, handler, args) {
|
console.log("usage: kwikemon [options]");
|
||||||
commands[name] = { handler: handler, args: args };
|
console.log(" kwikemon <name> [text]");
|
||||||
}
|
console.log();
|
||||||
defineCommand('clear', clear);
|
console.log("options:");
|
||||||
defineCommand('count', count);
|
console.log(" -c, --clear remove all monitors");
|
||||||
defineCommand('get', get, 'name');
|
console.log(" -f, --fetch <name> show the text of the named monitor");
|
||||||
defineCommand('help', usage);
|
console.log(" -n, --count count monitors");
|
||||||
defineCommand('list', list);
|
console.log(" -h, --help show what you're reading now");
|
||||||
defineCommand('remove', remove, 'name');
|
console.log(" -l, --list show all monitors");
|
||||||
defineCommand('set', set, 'name text');
|
console.log(" -r, --remove <name> remove the named monitor");
|
||||||
defineCommand('sweep', sweep);
|
console.log(" -s, --sweep clean up expired & deleted monitors");
|
||||||
defineCommand('ttl', ttl, 'name [ttl]');
|
console.log(" -t, --ttl <name> show the TTL of the named monitor");
|
||||||
defineCommand('write', write, 'name');
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
var cmd = process.argv[2]
|
|
||||||
, handler = commands[cmd] && commands[cmd].handler
|
|
||||||
;
|
|
||||||
if (handler) {
|
|
||||||
handler.apply(null, process.argv.slice(3));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (cmd) {
|
|
||||||
console.log('error: unknown command ' + cmd);
|
|
||||||
}
|
|
||||||
usage();
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear() {
|
var opt = process.argv[2]
|
||||||
kwikemon.clear(function(err) {
|
, name = process.argv[2]
|
||||||
process.exit(0);
|
, text = process.argv[3]
|
||||||
});
|
;
|
||||||
}
|
if (opt && opt[0] == '-') {
|
||||||
|
switch (opt) {
|
||||||
function count() {
|
case '-c':
|
||||||
kwikemon.count(function(err, n) {
|
case '--clear':
|
||||||
console.log(n);
|
kwikemon.removeAll(function(err) {
|
||||||
process.exit(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function expire(name, ttl) {
|
|
||||||
kwikemon.ttl(name, ttl, function(err) {
|
|
||||||
if (err && err.message == 'not found') {
|
|
||||||
console.log('no monitor named', name);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
else if (err) {
|
|
||||||
console.log('error: ' + (err.message || err));
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
});
|
||||||
});
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
function get(name) {
|
case '-f':
|
||||||
if (name) {
|
case '--fetch':
|
||||||
kwikemon.get(name, function(err, mon) {
|
var name = process.argv[3];
|
||||||
|
kwikemon.fetch(name, function(err, mon) {
|
||||||
if (mon) {
|
if (mon) {
|
||||||
console.log(mon.text);
|
console.log(mon.text);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('no monitor named', name);
|
console.log('error: no monitor named', name);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
break;
|
||||||
else {
|
|
||||||
console.log('get requires a name');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function list() {
|
case '-l':
|
||||||
kwikemon.getAll(function(err, monitors) {
|
case '--list':
|
||||||
Object.keys(monitors).forEach(function(name) {
|
kwikemon.fetchAll(function(err, monitors) {
|
||||||
console.log(name + ':', monitors[name].text);
|
Object.keys(monitors).forEach(function(name) {
|
||||||
});
|
console.log(name + ':', monitors[name].text);
|
||||||
process.exit(0);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove(name) {
|
|
||||||
if (name) {
|
|
||||||
kwikemon.remove(name, function(err) {
|
|
||||||
process.exit(0);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('remove requires a name');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function set(name, text) {
|
|
||||||
if (name && text) {
|
|
||||||
kwikemon.set(name, text, function() {
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
}
|
break;
|
||||||
else {
|
|
||||||
console.log('set requires a name and some text')
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sweep() {
|
case '-n':
|
||||||
kwikemon.sweep(function(err) {
|
case '--count':
|
||||||
process.exit(0);
|
kwikemon.count(function(err, n) {
|
||||||
});
|
console.log(n);
|
||||||
}
|
process.exit(0);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
function ttl(name, ttl) {
|
case '-r':
|
||||||
if (ttl) return expire(name, Number(ttl));
|
case '--remove':
|
||||||
if (name) {
|
name = process.argv[3];
|
||||||
kwikemon.ttl(name, function(err, ttl) {
|
if (name) {
|
||||||
|
kwikemon.remove(name, function(err) {
|
||||||
|
process.exit(0);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("error: --remove requires a name");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-s':
|
||||||
|
case '--sweep':
|
||||||
|
kwikemon.sweep(function(err) {
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-t':
|
||||||
|
case '--ttl':
|
||||||
|
var name = process.argv[3];
|
||||||
|
kwikemon.fetchTTL(name, function(err, ttl) {
|
||||||
if (typeof ttl == 'number') {
|
if (typeof ttl == 'number') {
|
||||||
console.log(ttl);
|
console.log(ttl);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('no monitor named', name);
|
console.log('error: no monitor named', name);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
break;
|
||||||
else {
|
|
||||||
console.log('ttl requires a name');
|
default:
|
||||||
process.exit(1);
|
usage();
|
||||||
|
process.exit(name == '-h' || name == '--help' ? 0 : 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (name && text) {
|
||||||
function write(name) {
|
kwikemon.set(name, text, function() {
|
||||||
if (name) {
|
process.exit(0);
|
||||||
process.stdin.pipe(kwikemon.writer(name));
|
|
||||||
process.stdin.on('end', function() {
|
|
||||||
process.exit(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('write requires a name');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function usage() {
|
|
||||||
console.log('usage: kwikemon <command> [args...]');
|
|
||||||
console.log('commands:');
|
|
||||||
Object.keys(commands).sort().forEach(function(name) {
|
|
||||||
var args = commands[name].args || '';
|
|
||||||
console.log(' ' + name + ' ' + args);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (name) {
|
||||||
if (require.main == module) {
|
process.stdin.pipe(kwikemon.createWriter(name));
|
||||||
main();
|
process.stdin.on('end', function() {
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
usage();
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
var port = process.argv[2] || 1111
|
var server = require('../server.js')
|
||||||
, host = process.argv[3] || '127.0.0.1'
|
, port = process.argv[2]
|
||||||
, app = require('../app.js')
|
, host = process.argv[3]
|
||||||
;
|
;
|
||||||
|
|
||||||
app.listen(port, host);
|
server.start(port, host);
|
||||||
console.log('kwikemond listening on ' + host + ':' + port);
|
|
||||||
|
|
|
||||||
106
kwikemon.js
106
kwikemon.js
|
|
@ -8,47 +8,29 @@ module.exports = {
|
||||||
|
|
||||||
// read
|
// read
|
||||||
, exists: callbackOptional(exists)
|
, exists: callbackOptional(exists)
|
||||||
, get: callbackOptional(get)
|
, fetch: callbackOptional(fetch)
|
||||||
, ttl: callbackOptional(ttl)
|
, fetchTTL: callbackOptional(fetchTTL)
|
||||||
, count: count
|
|
||||||
, list: list
|
, list: list
|
||||||
, getAll: getAll
|
, fetchAll: fetchAll
|
||||||
|
, count: count
|
||||||
|
|
||||||
// remove
|
// remove
|
||||||
, remove: callbackOptional(remove)
|
, remove: callbackOptional(remove)
|
||||||
, clear: clear
|
, removeAll: removeAll
|
||||||
, sweep: sweep
|
, sweep: sweep
|
||||||
|
|
||||||
// change redis client
|
// change redis client
|
||||||
, redis: redis
|
, redis: setRedis
|
||||||
};
|
};
|
||||||
|
|
||||||
var async = require('async')
|
var async = require('async')
|
||||||
, fs = require('fs')
|
, redis = require('redis').createClient()
|
||||||
, Redis = require('redis')
|
|
||||||
, redisClient
|
|
||||||
, toml = require('toml')
|
|
||||||
, LineEmitter = require('./line_emitter.js')
|
, LineEmitter = require('./line_emitter.js')
|
||||||
;
|
;
|
||||||
|
|
||||||
function redis(newRedis) {
|
function setRedis(newRedis) {
|
||||||
if (newRedis){
|
if (redis) redis.end();
|
||||||
if (redisClient) redisClient.end();
|
redis = newRedis;
|
||||||
redisClient = newRedis;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!redisClient) {
|
|
||||||
var configFile = process.env.HOME + '/.kwikemon.toml'
|
|
||||||
, config = {}
|
|
||||||
;
|
|
||||||
if (fs.existsSync(configFile)) {
|
|
||||||
config = toml.parse(fs.readFileSync(configFile));
|
|
||||||
}
|
|
||||||
config.redis = config.redis || {};
|
|
||||||
redisClient = Redis.createClient(config.redis.port, config.redis.host, config.redis.options);
|
|
||||||
}
|
|
||||||
return redisClient;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the callback argument of a function optional.
|
// Make the callback argument of a function optional.
|
||||||
|
|
@ -57,15 +39,15 @@ function redis(newRedis) {
|
||||||
// that accepts the callback is returned, with the
|
// that accepts the callback is returned, with the
|
||||||
// rest of the arguments fixed (like bind).
|
// rest of the arguments fixed (like bind).
|
||||||
//
|
//
|
||||||
// function get(id, cb) { db.get(id, cb); }
|
// function fetch(id, cb) { db.fetch(id, cb); }
|
||||||
// get = callbackOptional(get);
|
// fetch = callbackOptional(fetch);
|
||||||
//
|
//
|
||||||
// function print(err, x) { if (err) throw err; console.log(x); }
|
// function print(err, x) { if (err) throw err; console.log(x); }
|
||||||
//
|
//
|
||||||
// get(1, print);
|
// fetch(1, print);
|
||||||
//
|
//
|
||||||
// var get1 = get(1);
|
// var fetch1 = fetch(1);
|
||||||
// get1(print);
|
// fetch1(print);
|
||||||
function callbackOptional(fn, ctx) {
|
function callbackOptional(fn, ctx) {
|
||||||
return function() {
|
return function() {
|
||||||
var args = Array.prototype.slice.call(arguments);
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
|
@ -87,7 +69,7 @@ function k(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function exists(name, cb) {
|
function exists(name, cb) {
|
||||||
redis().exists(k(name), function(err, exists) {
|
redis.exists(k(name), function(err, exists) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
cb(null, exists == 1);
|
cb(null, exists == 1);
|
||||||
});
|
});
|
||||||
|
|
@ -106,11 +88,10 @@ function set(name, text, options, cb) {
|
||||||
;
|
;
|
||||||
exists(name, function(err, exists) {
|
exists(name, function(err, exists) {
|
||||||
var fields = {
|
var fields = {
|
||||||
name: name
|
text: text
|
||||||
, text: text
|
|
||||||
, modified: Date.now()
|
, modified: Date.now()
|
||||||
}
|
}
|
||||||
, multi = redis().multi()
|
, multi = redis.multi()
|
||||||
;
|
;
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
fields.created = Date.now();
|
fields.created = Date.now();
|
||||||
|
|
@ -137,37 +118,16 @@ function writer(name) {
|
||||||
return le;
|
return le;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get(name, cb) {
|
function fetch(name, cb) {
|
||||||
redis().hgetall(k(name), cb);
|
redis.hgetall(k(name), cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
function expire(name, ttl, cb) {
|
function fetchTTL(name, cb) {
|
||||||
exists(name, function(err, exists) {
|
redis.ttl(k(name), cb);
|
||||||
if (err || !exists) {
|
|
||||||
return cb(err || new Error('not found'));
|
|
||||||
}
|
|
||||||
redis().multi()
|
|
||||||
.hset(k(name), 'expire', ttl)
|
|
||||||
.expire(k(name), ttl)
|
|
||||||
.exec(cb);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function ttl(name, ttl, cb) {
|
|
||||||
if (typeof ttl == 'number') {
|
|
||||||
expire(name, ttl, cb);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cb = ttl;
|
|
||||||
redis().ttl(k(name), cb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function count(cb) {
|
function count(cb) {
|
||||||
sweep(function(err) {
|
redis.scard('kwikemon:monitors', cb);
|
||||||
if (err) return cb(err);
|
|
||||||
redis().scard('kwikemon:monitors', cb);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sweep(cb) {
|
function sweep(cb) {
|
||||||
|
|
@ -178,7 +138,7 @@ function sweep(cb) {
|
||||||
if (i == n) cb();
|
if (i == n) cb();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
redis().smembers('kwikemon:monitors', function(err, names) {
|
redis.smembers('kwikemon:monitors', function(err, names) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
n = names.length;
|
n = names.length;
|
||||||
if (n == 0) return cb();
|
if (n == 0) return cb();
|
||||||
|
|
@ -200,24 +160,24 @@ function sweep(cb) {
|
||||||
function list(cb) {
|
function list(cb) {
|
||||||
sweep(function(err) {
|
sweep(function(err) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
redis().smembers('kwikemon:monitors', cb);
|
redis.smembers('kwikemon:monitors', cb);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAll(cb) {
|
function fetchAll(cb) {
|
||||||
var monitors = {};
|
var monitors = {};
|
||||||
list(function(err, names) {
|
list(function(err, names) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
var geters = names.sort().map(function(name) {
|
var fetchers = names.sort().map(function(name) {
|
||||||
return function(done) {
|
return function(done) {
|
||||||
get(name, function(err, text) {
|
fetch(name, function(err, text) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
monitors[name] = text;
|
monitors[name] = text;
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
async.parallel(geters, function(err, _) {
|
async.parallel(fetchers, function(err, _) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
cb(null, monitors)
|
cb(null, monitors)
|
||||||
});
|
});
|
||||||
|
|
@ -225,16 +185,16 @@ function getAll(cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove(name, cb) {
|
function remove(name, cb) {
|
||||||
redis().multi()
|
redis.multi()
|
||||||
.del(k(name))
|
.del(k(name))
|
||||||
.srem('kwikemon:monitors', name)
|
.srem('kwikemon:monitors', name)
|
||||||
.exec(cb);
|
.exec(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear(cb) {
|
function removeAll(cb) {
|
||||||
redis().smembers('kwikemon:monitors', function(err, names) {
|
redis.smembers('kwikemon:monitors', function(err, names) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
var multi = redis().multi();
|
var multi = redis.multi();
|
||||||
names.forEach(function(name) {
|
names.forEach(function(name) {
|
||||||
multi.del(k(name));
|
multi.del(k(name));
|
||||||
multi.srem('kwikemon:monitors', name);
|
multi.srem('kwikemon:monitors', name);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{ "name": "kwikemon"
|
{ "name": "kwikemon"
|
||||||
, "version": "0.0.6"
|
, "version": "0.0.2"
|
||||||
, "description": "monitor one-off things on your servers"
|
, "description": "monitor one-off things on your servers"
|
||||||
, "author": "Sami Samhuri <sami@samhuri.net>"
|
, "author": "Sami Samhuri <sami@samhuri.net>"
|
||||||
, "license": "MIT"
|
, "license": "MIT"
|
||||||
|
|
@ -11,12 +11,9 @@
|
||||||
, "kwikemond": "./bin/kwikemond"
|
, "kwikemond": "./bin/kwikemond"
|
||||||
}
|
}
|
||||||
, "dependencies": {
|
, "dependencies": {
|
||||||
"async": "0.2.x"
|
"paramify": "0.0.x"
|
||||||
, "express": "3.0.x"
|
|
||||||
, "jade": "0.31.x"
|
|
||||||
, "negotiator": "0.2.x"
|
|
||||||
, "redis": "0.8.x"
|
, "redis": "0.8.x"
|
||||||
, "toml": "0.4.x"
|
, "async": "0.2.x"
|
||||||
}
|
}
|
||||||
, "devDependencies": {
|
, "devDependencies": {
|
||||||
"mocha": "1.10.x"
|
"mocha": "1.10.x"
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
ul#monitors {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
li.monitor {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer {
|
|
||||||
width: 80%;
|
|
||||||
margin: 0.5em auto;
|
|
||||||
padding: 0.3em 1em;
|
|
||||||
text-align: center;
|
|
||||||
border-top: solid 1px #aaa;
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
source 'https://rubygems.org'
|
|
||||||
|
|
||||||
gem 'hashie', '~> 2.0.5'
|
|
||||||
gem 'redis', '~> 3.0.4'
|
|
||||||
gem 'toml', '~> 0.0.4'
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
GEM
|
|
||||||
remote: https://rubygems.org/
|
|
||||||
specs:
|
|
||||||
blankslate (2.1.2.4)
|
|
||||||
hashie (2.0.5)
|
|
||||||
parslet (1.5.0)
|
|
||||||
blankslate (~> 2.0)
|
|
||||||
redis (3.0.4)
|
|
||||||
toml (0.0.4)
|
|
||||||
parslet
|
|
||||||
|
|
||||||
PLATFORMS
|
|
||||||
ruby
|
|
||||||
|
|
||||||
DEPENDENCIES
|
|
||||||
hashie (~> 2.0.5)
|
|
||||||
redis (~> 3.0.4)
|
|
||||||
toml (~> 0.0.4)
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
$LOAD_PATH << File.expand_path('../lib', __FILE__)
|
|
||||||
require 'kwikemon/version'
|
|
||||||
|
|
||||||
Gem::Specification.new do |s|
|
|
||||||
s.name = 'kwikemon'
|
|
||||||
s.version = Kwikemon::VERSION
|
|
||||||
s.license = 'MIT'
|
|
||||||
s.summary = 'Ruby client for kwikemon.'
|
|
||||||
s.description = 'Read & write simple monitors using Redis.'
|
|
||||||
s.author = 'Sami Samhuri'
|
|
||||||
s.email = 'sami@samhuri.net'
|
|
||||||
s.homepage = 'https://github.com/samsonjs/kwikemon'
|
|
||||||
s.require_path = './lib'
|
|
||||||
s.files = ['lib/kwikemon.rb', 'lib/kwikemon/monitor.rb', 'lib/kwikemon/version.rb']
|
|
||||||
s.add_dependency 'redis', '~> 3.0.4'
|
|
||||||
s.required_ruby_version = '>= 1.9.1'
|
|
||||||
end
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
# Copyright 2013 Sami Samhuri <sami@samhuri.net>
|
|
||||||
#
|
|
||||||
# MIT License
|
|
||||||
# http://sjs.mit-license.org
|
|
||||||
|
|
||||||
lib_dir = File.expand_path('../', __FILE__)
|
|
||||||
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
|
||||||
|
|
||||||
require 'hashie'
|
|
||||||
require 'redis'
|
|
||||||
require 'toml'
|
|
||||||
require 'kwikemon/monitor'
|
|
||||||
require 'kwikemon/version'
|
|
||||||
|
|
||||||
module Kwikemon
|
|
||||||
|
|
||||||
extend self
|
|
||||||
|
|
||||||
include Enumerable
|
|
||||||
|
|
||||||
def redis
|
|
||||||
@redis ||= Redis.new(config.redis || {})
|
|
||||||
end
|
|
||||||
|
|
||||||
def redis=(redis)
|
|
||||||
@redis = redis
|
|
||||||
end
|
|
||||||
|
|
||||||
def key_prefix
|
|
||||||
@key_prefix ||= "kwikemon"
|
|
||||||
end
|
|
||||||
|
|
||||||
def key_prefix=(key_prefix)
|
|
||||||
@key_prefix = key_prefix
|
|
||||||
end
|
|
||||||
|
|
||||||
def key(x)
|
|
||||||
"#{key_prefix}:#{x}"
|
|
||||||
end
|
|
||||||
|
|
||||||
Monitor.on(:create) do |name|
|
|
||||||
redis.sadd(key('monitors'), name)
|
|
||||||
end
|
|
||||||
|
|
||||||
Monitor.on(:remove) do |name|
|
|
||||||
redis.srem(key('monitors'), name)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# Set `name` to `value`.
|
|
||||||
#
|
|
||||||
# @param name [#to_s] name of the monitor
|
|
||||||
# @param text [#to_s] status text
|
|
||||||
def set(name, text)
|
|
||||||
Monitor.new(name, text).save
|
|
||||||
end
|
|
||||||
|
|
||||||
# Check if `name` exists3
|
|
||||||
#
|
|
||||||
# @param name [#to_s] name of the monitor
|
|
||||||
# @return [true, false] true if monitor exists, otherwise false
|
|
||||||
def exists?(name)
|
|
||||||
Monitor.new(name).exists?
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the value of `name`. Returns `nil` if it doesn't exist.
|
|
||||||
#
|
|
||||||
# @param name [#_tos] name of the monitor
|
|
||||||
# @return [String, nil] status text, or `nil` if it doesn't exist
|
|
||||||
def get(name)
|
|
||||||
Monitor.new(name).text
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the TTL in seconds of `name`. Returns `nil` if it doesn't exit.
|
|
||||||
#
|
|
||||||
# @param name [#_tos] name of the monitor
|
|
||||||
# @return [String, nil] TTL, or `nil` if it doesn't exist
|
|
||||||
def ttl(name)
|
|
||||||
Monitor.new(name).ttl
|
|
||||||
end
|
|
||||||
|
|
||||||
# Count all monitors.
|
|
||||||
def count
|
|
||||||
redis.scard(key('monitors'))
|
|
||||||
end
|
|
||||||
|
|
||||||
# List all monitor names.
|
|
||||||
def list
|
|
||||||
redis.smembers(key('monitors'))
|
|
||||||
end
|
|
||||||
|
|
||||||
def each
|
|
||||||
list.each { |m| yield(m) }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get a `Hash` of all monitors.
|
|
||||||
def get_all
|
|
||||||
list.inject({}) do |ms, name|
|
|
||||||
ms[name] = Monitor.new(name).text
|
|
||||||
ms
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Remove the monitor named `name`.
|
|
||||||
def remove(name)
|
|
||||||
Monitor.new(name).remove
|
|
||||||
end
|
|
||||||
|
|
||||||
# Clear all monitors.
|
|
||||||
def clear
|
|
||||||
list.each do |name|
|
|
||||||
remove(name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Clean up expired monitors.
|
|
||||||
def sweep
|
|
||||||
list.each do |name|
|
|
||||||
remove(name) unless exists?(name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def config
|
|
||||||
@config ||= Hashie::Mash.new(load_config)
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_config
|
|
||||||
path = File.join(ENV['HOME'], '.kwikemon.toml')
|
|
||||||
if File.exists?(path)
|
|
||||||
TOML.load_file(path)
|
|
||||||
else
|
|
||||||
{}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
# Copyright 2013 Sami Samhuri <sami@samhuri.net>
|
|
||||||
#
|
|
||||||
# MIT License
|
|
||||||
# http://sjs.mit-license.org
|
|
||||||
|
|
||||||
module Kwikemon
|
|
||||||
|
|
||||||
class Monitor
|
|
||||||
|
|
||||||
DefaultTTL = 86400 # 1 day
|
|
||||||
|
|
||||||
attr_accessor :redis
|
|
||||||
attr_reader :name, :text, :ttl, :created, :modified
|
|
||||||
|
|
||||||
@listeners = Hash.new { |h, k| h[k] = [] }
|
|
||||||
|
|
||||||
def Monitor.on(event, &block)
|
|
||||||
@listeners[event] << block
|
|
||||||
end
|
|
||||||
|
|
||||||
def Monitor.emit(event, *args)
|
|
||||||
@listeners[event].each { |handler| handler.call(*args) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(name, text = nil)
|
|
||||||
@name = name
|
|
||||||
@text = text
|
|
||||||
end
|
|
||||||
|
|
||||||
def save
|
|
||||||
if exists?
|
|
||||||
update(text)
|
|
||||||
else
|
|
||||||
create
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def exists?
|
|
||||||
redis.exists(key)
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
raise MonitorError.new('name cannot be blank') if name.to_s.strip.length == 0
|
|
||||||
redis.hmset(key, *to_a)
|
|
||||||
self.class.emit(:create, name)
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def update(text, ttl = nil)
|
|
||||||
raise MonitorError.new('name cannot be blank') if name.to_s.strip.length == 0
|
|
||||||
redis.hmset(key, 'text', text, 'modified', Time.now.to_i)
|
|
||||||
redis.ttl(key, ttl) if ttl
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove
|
|
||||||
redis.del(key)
|
|
||||||
self.class.emit(:remove, name)
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def key
|
|
||||||
Kwikemon.key("monitor:#{name}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def ttl
|
|
||||||
@ttl ||= exists? ? redis.ttl(key) : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def created
|
|
||||||
@created ||= exists? ? redis.hget(key, 'created').to_i : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def modified
|
|
||||||
@modified ||= exists? ? redis.hget(key, 'modified').to_i : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def text
|
|
||||||
@text ||= exists? ? redis.hget(key, 'text') : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def redis
|
|
||||||
Kwikemon.redis
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_hash
|
|
||||||
{ name: name,
|
|
||||||
text: text,
|
|
||||||
ttl: ttl || DefaultTTL,
|
|
||||||
created: created || Time.now.to_i,
|
|
||||||
modified: modified || Time.now.to_i
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_a
|
|
||||||
to_hash.to_a
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
module Kwikemon
|
|
||||||
VERSION = '0.0.9'
|
|
||||||
end
|
|
||||||
65
server.js
Normal file
65
server.js
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
// Copyright 2013 Sami Samhuri
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
create: create
|
||||||
|
, start: start
|
||||||
|
, stop: stop
|
||||||
|
};
|
||||||
|
|
||||||
|
var http = require('http')
|
||||||
|
, paramify = require('paramify')
|
||||||
|
, kwikemon = require('./kwikemon.js')
|
||||||
|
, _server
|
||||||
|
;
|
||||||
|
|
||||||
|
function create() {
|
||||||
|
return http.createServer(handleRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
function start(port, host) {
|
||||||
|
port = port || 1111;
|
||||||
|
host = host || '127.0.0.1';
|
||||||
|
_server = create();
|
||||||
|
_server.listen(port, host);
|
||||||
|
console.log('kwikemond listening on ' + host + ':' + port);
|
||||||
|
return _server;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
_server.close();
|
||||||
|
_server = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRequest(req, res) {
|
||||||
|
var name = req.url.replace(/^\//, '')
|
||||||
|
, type = 'html'
|
||||||
|
, m
|
||||||
|
;
|
||||||
|
if (name == 'favicon.ico') return res.end();
|
||||||
|
if (m = name.match(/\.(json|txt)$/)) {
|
||||||
|
type = m[1];
|
||||||
|
name = name.replace(RegExp('\.' + type + '$'), '');
|
||||||
|
}
|
||||||
|
if (name) {
|
||||||
|
kwikemon.fetch(name, function(err, text) {
|
||||||
|
if (err) {
|
||||||
|
res.end('error: ' + (err.message || 'unknown'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.end(text);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// all
|
||||||
|
else {
|
||||||
|
kwikemon.fetchAll(function(err, monitors) {
|
||||||
|
if (err) {
|
||||||
|
res.end('error: ' + (err.message || 'unknown'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.keys(monitors).sort().forEach(function(name) {
|
||||||
|
res.write(name + ': ' + monitors[name] + '\n');
|
||||||
|
});
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
53
test.js
53
test.js
|
|
@ -12,14 +12,14 @@ before(function(done) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
beforeEach(kwikemon.clear);
|
beforeEach(kwikemon.removeAll);
|
||||||
after(kwikemon.clear);
|
after(kwikemon.removeAll);
|
||||||
|
|
||||||
describe("kwikemon", function() {
|
describe("kwikemon", function() {
|
||||||
describe("#set", function() {
|
describe("#set", function() {
|
||||||
it("should set text", function(done) {
|
it("should set text", function(done) {
|
||||||
kwikemon.set('foo', 'bar', function(err) {
|
kwikemon.set('foo', 'bar', function(err) {
|
||||||
kwikemon.get('foo', function(err, mon) {
|
kwikemon.fetch('foo', function(err, mon) {
|
||||||
assert(mon.text == 'bar');
|
assert(mon.text == 'bar');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
@ -28,7 +28,7 @@ describe("kwikemon", function() {
|
||||||
|
|
||||||
it("should overwrite text", function(done) {
|
it("should overwrite text", function(done) {
|
||||||
kwikemon.set('foo', 'baz', function(err) {
|
kwikemon.set('foo', 'baz', function(err) {
|
||||||
kwikemon.get('foo', function(err, mon) {
|
kwikemon.fetch('foo', function(err, mon) {
|
||||||
assert(mon.text == 'baz');
|
assert(mon.text == 'baz');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
@ -37,7 +37,7 @@ describe("kwikemon", function() {
|
||||||
|
|
||||||
it("should set custom ttls", function(done) {
|
it("should set custom ttls", function(done) {
|
||||||
kwikemon.set('foo', 'bar', { ttl: 1 }, function(err) {
|
kwikemon.set('foo', 'bar', { ttl: 1 }, function(err) {
|
||||||
kwikemon.ttl('foo', function(err, ttl) {
|
kwikemon.fetchTTL('foo', function(err, ttl) {
|
||||||
assert(ttl <= 1);
|
assert(ttl <= 1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
@ -46,7 +46,7 @@ describe("kwikemon", function() {
|
||||||
|
|
||||||
it("should not expire with a ttl of zero", function(done) {
|
it("should not expire with a ttl of zero", function(done) {
|
||||||
kwikemon.set('foo', 'bar', { ttl: 0 }, function(err) {
|
kwikemon.set('foo', 'bar', { ttl: 0 }, function(err) {
|
||||||
kwikemon.ttl('foo', function(err, ttl) {
|
kwikemon.fetchTTL('foo', function(err, ttl) {
|
||||||
assert(ttl == -1);
|
assert(ttl == -1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
@ -55,7 +55,7 @@ describe("kwikemon", function() {
|
||||||
|
|
||||||
it("should not expire when ttl is < 0", function(done) {
|
it("should not expire when ttl is < 0", function(done) {
|
||||||
kwikemon.set('foo', 'bar', { ttl: -1 }, function(err) {
|
kwikemon.set('foo', 'bar', { ttl: -1 }, function(err) {
|
||||||
kwikemon.ttl('foo', function(err, ttl) {
|
kwikemon.fetchTTL('foo', function(err, ttl) {
|
||||||
assert(ttl == -1);
|
assert(ttl == -1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
@ -92,12 +92,12 @@ describe("kwikemon", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#get", function() {
|
describe("#fetch", function() {
|
||||||
it("should get the last text monitored", function(done) {
|
it("should fetch the last text monitored", function(done) {
|
||||||
async.series([
|
async.series([
|
||||||
kwikemon.set('foo', 'bar')
|
kwikemon.set('foo', 'bar')
|
||||||
, kwikemon.set('foo', 'marcellus')
|
, kwikemon.set('foo', 'marcellus')
|
||||||
, kwikemon.get('foo')
|
, kwikemon.fetch('foo')
|
||||||
],
|
],
|
||||||
function(err, results) {
|
function(err, results) {
|
||||||
var mon = results[2];
|
var mon = results[2];
|
||||||
|
|
@ -107,18 +107,18 @@ describe("kwikemon", function() {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should get null for non-existent monitors", function(done) {
|
it("should fetch null for non-existent monitors", function(done) {
|
||||||
kwikemon.get('non-existent', function(err, mon) {
|
kwikemon.fetch('non-existent', function(err, mon) {
|
||||||
assert(mon == null);
|
assert(mon == null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#ttl", function() {
|
describe("#fetchTTL", function() {
|
||||||
it("should get the last TTL set", function(done) {
|
it("should fetch the last TTL set", function(done) {
|
||||||
kwikemon.set('foo', 'bar', { ttl: 300 }, function(err) {
|
kwikemon.set('foo', 'bar', { ttl: 300 }, function(err) {
|
||||||
kwikemon.ttl('foo', function(err, ttl) {
|
kwikemon.fetchTTL('foo', function(err, ttl) {
|
||||||
assert(ttl <= 300);
|
assert(ttl <= 300);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
@ -126,31 +126,20 @@ describe("kwikemon", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return -1 for non-existent monitors", function(done) {
|
it("should return -1 for non-existent monitors", function(done) {
|
||||||
kwikemon.ttl('non-existent', function(err, ttl) {
|
kwikemon.fetchTTL('non-existent', function(err, ttl) {
|
||||||
assert(ttl == -1);
|
assert(ttl == -1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set a ttl if given one", function(done) {
|
|
||||||
kwikemon.set('foo', 'bar', function(err) {
|
|
||||||
kwikemon.ttl('foo', 100, function(err) {
|
|
||||||
kwikemon.ttl('foo', function(err, ttl) {
|
|
||||||
assert(ttl <= 100);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#getAll", function() {
|
describe("#fetchAll", function() {
|
||||||
it("should get all monitors", function(done) {
|
it("should fetch all monitors", function(done) {
|
||||||
async.series([
|
async.series([
|
||||||
kwikemon.set('a', '1')
|
kwikemon.set('a', '1')
|
||||||
, kwikemon.set('b', '2')
|
, kwikemon.set('b', '2')
|
||||||
, kwikemon.set('c', '3')
|
, kwikemon.set('c', '3')
|
||||||
, kwikemon.getAll
|
, kwikemon.fetchAll
|
||||||
],
|
],
|
||||||
function(err, results) {
|
function(err, results) {
|
||||||
var monitors = results.pop()
|
var monitors = results.pop()
|
||||||
|
|
@ -198,12 +187,12 @@ describe("kwikemon", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#clear", function() {
|
describe("#removeAll", function() {
|
||||||
it("should remove the named monitor", function(done) {
|
it("should remove the named monitor", function(done) {
|
||||||
async.series([
|
async.series([
|
||||||
kwikemon.set('foo', 'bar')
|
kwikemon.set('foo', 'bar')
|
||||||
, kwikemon.set('baz', 'quux')
|
, kwikemon.set('baz', 'quux')
|
||||||
, kwikemon.clear
|
, kwikemon.removeAll
|
||||||
, kwikemon.exists('foo')
|
, kwikemon.exists('foo')
|
||||||
, kwikemon.exists('baz')
|
, kwikemon.exists('baz')
|
||||||
, kwikemon.count
|
, kwikemon.count
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
// Copyright 2013 Sami Samhuri
|
|
||||||
|
|
||||||
module.exports = JSON.parse(require('fs').readFileSync(__dirname + '/package.json')).version;
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
extends layout
|
|
||||||
block content
|
|
||||||
p.
|
|
||||||
error: #{err.message || err}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
doctype 5
|
|
||||||
html(lang="en")
|
|
||||||
head
|
|
||||||
title kwikemon
|
|
||||||
link(rel="stylesheet", href="/css/style.css")
|
|
||||||
body
|
|
||||||
block nav
|
|
||||||
block title
|
|
||||||
h1= pageTitle || 'kwikemon'
|
|
||||||
#content
|
|
||||||
block content
|
|
||||||
#footer
|
|
||||||
a(href="https://github.com/samsonjs/kwikemon") kwikemon #{version}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
extends layout
|
|
||||||
block nav
|
|
||||||
p: a(href="/") ← monitors
|
|
||||||
block content
|
|
||||||
p= monitor.text
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
extends layout
|
|
||||||
block content
|
|
||||||
ul#monitors
|
|
||||||
- each monitor in monitors
|
|
||||||
li.monitor: a(href="/#{monitor.name}") #{monitor.name}: #{monitor.text}
|
|
||||||
Loading…
Reference in a new issue