autostart server, return wrapped

This commit is contained in:
AJ ONeal 2015-07-22 20:58:18 -06:00
parent 4e3b9b88f7
commit 696ac1ed1c
5 changed files with 209 additions and 40 deletions

View File

@ -23,7 +23,7 @@ var sqlite = require('sqlite3-server');
var opts = {
key: '1892d335081d8d346e556c9c3c8ff2c3'
, bits: 128
, storage: path.join('/tmp/authn.sqlcipher')
, filename: path.join('/tmp/authn.sqlcipher')
, verbose: false
, port: 3232 // default random
, forceServer: true // default false

138
client.js
View File

@ -1,3 +1,141 @@
'use strict';
/*global Promise*/
// TODO iterate over the prototype
// translate request / response
var sqlite3real = require('sqlite3');
/*
function createConnection(opts) {
var server = ;
return server.create(opts).then(function () {
// created and listening
});
}
*/
function startServer(opts) {
return require('./server').create(opts).then(function (server) {
// this process doesn't need to connect to itself
// through a socket
return server.masterClient;
});
}
function getConnection(opts) {
if (!opts.sock) {
opts.sock = opts.filename + '.sock';
}
return new Promise(function (resolve) {
setTimeout(function () {
var WebSocket = require('ws');
var ws = new WebSocket('ws+unix:' + opts.sock);
if (opts.server) {
return startServer(opts);
}
ws.on('error', function (err) {
console.error('[ERROR] ws connection failed, retrying');
console.error(err);
function retry() {
setTimeout(function () {
getConnection(opts).then(resolve);
}, 100 + (Math.random() * 250));
}
if ('ENOENT' === err.code || 'ECONNREFUSED' === err.code) {
return startServer(opts).then(function (client) {
// ws.masterClient = client;
resolve({ masterClient: client });
}, function () {
retry();
});
}
retry();
});
ws.on('open', function () {
resolve(ws);
});
});
}, 100 + (Math.random() * 250));
}
function create(opts) {
// TODO maybe use HTTP POST instead?
return getConnection(opts).then(function (ws) {
if (ws.masterClient) {
return ws.masterClient;
}
var db = {};
var proto = sqlite3real.Database.prototype;
function rpc(fname, args) {
var id;
var cb;
if ('function' === typeof args[args.length - 1]) {
id = Math.random();
cb = args.pop();
}
ws.send({
type: 'rpc'
, func: fname
, args: args
, filename: opts.filename
, id: id
});
if (!cb) {
return;
}
function onMessage(data) {
if (!data || 'object' !== typeof data) {
return;
}
if (data.id !== id) {
return;
}
cb.apply(data.this, data.args);
}
ws.on('message', onMessage);
}
db.sanitize = require('./wrapper').sanitize;
Object.keys(sqlite3real.Database.prototype).forEach(function (key) {
if ('function' === typeof proto[key]) {
db[key] = function () {
rpc(key, Array.prototype.slice.call(arguments));
};
}
});
// serialize
// parallel
db.serialize = db.parallel = function () {
throw new Error('NOT IMPLEMENTED in SQLITE3-remote');
};
return db;
});
}
module.exports.sanitize = require('./wrapper').sanitize;
module.exports.create = create;

View File

@ -3,7 +3,7 @@
var numcpus = require('os').cpus().length;
var sqlite3;
if (false && numcpus >= 2) {
if (numcpus >= 2) {
sqlite3 = require('./client');
} else {
sqlite3 = require('./wrapper');

100
server.js
View File

@ -1,54 +1,84 @@
'use strict';
/*global Promise*/
function create(options) {
var url = require('url');
var express = require('express');
var app = express();
var wss = options.wss;
var wsses = {};
wss.on('connection', function (ws) {
var location = url.parse(ws.upgradeReq.url, true);
// you might use location.query.access_token to authenticate or share sessions
// or ws.upgradeReq.headers.cookie (see http://stackoverflow.com/a/16395220/151312
function createApp(server, options) {
console.log('Create App');
ws.__session_id = location.query.session_id || Math.random();
if (wsses[options.filename]) {
return Promise.resolve(wsses[options.filename]);
}
ws.on('message', function (buffer) {
var cmd;
return require('./wrapper').create(options).then(function (db) {
var url = require('url');
var express = require('express');
var app = express();
var wss = server.wss;
try {
cmd = JSON.parse(buffer.toString('utf8'));
} catch(e) {
ws.send(JSON.stringify({ type: 'error', value: { message: e.message, code: "E_PARSE_JSON" } }));
}
wss.on('connection', function (ws) {
var location = url.parse(ws.upgradeReq.url, true);
// you might use location.query.access_token to authenticate or share sessions
// or ws.upgradeReq.headers.cookie (see http://stackoverflow.com/a/16395220/151312
switch(cmd.type) {
case 'init':
break;
ws.__session_id = location.query.session_id || Math.random();
case 'rpc':
break;
ws.on('message', function (buffer) {
var cmd;
default:
break;
}
try {
cmd = JSON.parse(buffer.toString('utf8'));
} catch(e) {
ws.send(JSON.stringify({ type: 'error', value: { message: e.message, code: "E_PARSE_JSON" } }));
}
switch(cmd.type) {
case 'init':
break;
case 'rpc':
break;
default:
break;
}
});
ws.send(JSON.stringify({ type: 'session', value: ws.__session_id }));
});
ws.send(JSON.stringify({ type: 'session', value: ws.__session_id }));
app.masterClient = db;
wsses[options.filename] = app;
return app;
});
}
/*
var tablename = 'authn';
if (tablename) {
setup.push(db.runAsync("CREATE TABLE IF NOT EXISTS '" + sanitize(tablename)
+ "' (id TEXT, secret TEXT, json TEXT, PRIMARY KEY(id))"));
}
*/
function create(options) {
console.log('Create Server');
/*global Promise*/
return new Promise(function (resolve) {
resolve(app);
var server = require('http').createServer();
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server: server });
//var port = process.env.PORT || process.argv[0] || 4080;
console.log('options.sock');
console.log(options.sock);
var fs = require('fs');
fs.unlink(options.sock, function () {
// ignore error when socket doesn't exist
server.listen(options.sock, function () {
console.log('Listening');
});
});
createApp({ server: server, wss: wss }, options).then(function (app) {
server.on('request', app);
resolve({ masterClient: app.masterClient });
});
});
}

View File

@ -19,11 +19,12 @@ function create(opts) {
sqlite3.verbose();
}
if (!dbs[opts.storage] || dbs[opts.storage].__key !== opts.key) {
dbs[opts.storage] = new sqlite3.Database(opts.storage);
if (!dbs[opts.filename] || dbs[opts.filename].__key !== opts.key) {
dbs[opts.filename] = new sqlite3.Database(opts.filename);
}
db = dbs[opts.storage];
db = dbs[opts.filename];
db.sanitize = sanitize;
db.__key = opts.key;
return new Promise(function (resolve, reject) {