spincycle
Version:
A reactive message router and object manager that lets clients subscribe to object property changes on the server
514 lines (473 loc) • 15.2 kB
JavaScript
// Generated by CoffeeScript 1.12.6
(function() {
var Couch, DB, LRU, OStore, ResolveModule, Rethink, all, debug, defer, resolver, uuid,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
defer = require('node-promise').defer;
all = require('node-promise').all;
uuid = require('node-uuid');
LRU = require('lru-cache');
OStore = require('./OStore');
Couch = require('./CouchPersistence');
Rethink = require('./RethinkPersistence');
ResolveModule = require('./ResolveModule');
resolver = new ResolveModule();
debug = process.env["DEBUG"];
DB = (function() {
function DB() {}
DB.dburl = 'localhost';
DB.lru = LRU();
DB.lrudiff = LRU();
DB.dbname = '';
DB.onUpdated = function(record) {
if (record && record.type && record.id) {
return resolver.createObjectFrom(record).then(function(ooo) {
return OStore.updateObj(ooo);
});
}
};
DB.getDataStore = function(_name) {
var name, q;
name = _name || DB.dbname;
DB.dbname = name;
q = defer();
if (!DB.DataStore) {
if (!name) {
DB.DataStore = new Rethink(DB.dburl, DB);
} else if (name === 'couchdb') {
DB.DataStore = new Couch(DB.dburl);
} else if (name === 'rethinkdb') {
DB.DataStore = new Rethink(DB.dburl, DB);
}
DB.DataStore.connect().then(function(ds) {
return DB.getOrCreateObjectByRecord({
id: 11122333444,
type: 'SpinMeta'
}).then(function(meta) {
DB.meta = meta;
meta.serialize();
DB.DataStore = ds;
return q.resolve(ds);
});
});
} else {
q.resolve(DB.DataStore);
}
return q;
};
DB.createDatabases = function(dblist) {
var q;
q = defer();
console.log('*** createDatabases called for list of dbs...');
console.dir(dblist);
DB.getDataStore().then(function(store) {
var promises;
console.log('DB.createDatabases got back store');
promises = [];
dblist.forEach(function(dbname) {
var db;
console.log('attempting to get table for ' + dbname);
if (!(indexOf.call(DB.meta.knownModels, dbname) >= 0)) {
DB.meta.knownModels.push(dbname);
DB.meta.serialize();
}
db = store.getDbFor(dbname);
return promises.push(db);
});
return all(promises).then(function(results) {
console.log('*DB.createDatabases all good');
dblist.forEach(function(dbname2) {
return DB.extendSchemaIfNeeded(DB.DataStore, dbname2);
});
return q.resolve(results);
});
});
return q;
};
DB.extendSchemaIfNeeded = function(db, _dbname) {
var dbname, proto, q;
dbname = _dbname;
q = defer();
proto = ResolveModule.modulecache[dbname];
if (!(proto && proto.model)) {
console.log('found undefined prototype for ' + dbname);
q.resolve();
} else {
db.all(dbname, {
skip: 0,
limit: 10
}, function(res) {
var k, lookup, missing, o, v;
if (res.length > 0) {
o = res[res.length - 1];
missing = [];
lookup = {
createdAt: true,
modifiedAt: true,
createdBy: true
};
for (k in o) {
v = o[k];
lookup[k] = k;
}
proto.model.forEach(function(property) {
if (!lookup[property.name]) {
return missing.push(property);
}
});
if (missing.length > 0) {
return DB.count(dbname).then(function(modelcount) {
var count, cursor, getThese, loopThrough;
count = modelcount;
cursor = 0;
console.log('adding ' + missing.length + ' missing properties to ' + modelcount + ' existing objects');
getThese = function(where) {
var r, start;
console.log('getThese called with skip ' + where);
r = defer();
start = Date.now();
db.all(dbname, {
skip: where,
limit: 1000
}, function(objs) {
var cnt;
console.log('getThese got ' + objs.length + ' objs');
cnt = objs.length * missing.length;
return objs.forEach(function(ro) {
return missing.forEach(function(mprop) {
if (!mprop["default"]) {
if (mprop.array) {
mprop["default"] = [];
} else if (mprop.hashtable) {
mprop["default"] = {};
} else if (mprop.type) {
mprop["default"] = '';
}
}
if (ro) {
return DB.extend(ro.type, ro.id, mprop.name, mprop["default"]).then(function(o) {
var diff, end;
DB.lru.set(ro.id, ro);
if (--cnt === 0) {
end = Date.now();
diff = parseInt((end - start) / 1000);
console.log('extendSchemaIfNeeded done for ' + res.length + ' objects. runtime = ' + diff + ' seconds');
return r.resolve();
}
});
}
});
});
});
return r;
};
loopThrough = function() {
return getThese(cursor).then(function() {
return setTimeout(function() {
if (cursor < count) {
cursor += 1000;
return loopThrough();
}
}, 100);
});
};
return loopThrough();
});
} else {
return q.resolve();
}
}
});
}
return q;
};
DB.extend = function(type, id, field, def) {
return DB.getDataStore().then(function(store) {
return store.extend(type, id, field, def);
});
};
DB.getFromStoreOrDB = function(type, id) {
var q;
q = defer();
OStore.getObject(id, type).then(function(oo) {
if (oo) {
return q.resolve(oo);
} else {
return DB.get(type, [id]).then(function(records) {
var record;
if (records && records[0]) {
record = records[0];
return resolver.createObjectFrom(record).then(function(ooo) {
return q.resolve(ooo);
});
} else {
return q.resolve(void 0);
}
});
}
});
return q;
};
DB.getOrCreateObjectByRecord = function(record) {
var q;
q = defer();
if (debug) {
console.log('getOrCreateObjectByRecord called for type ' + record.type + ' and id ' + record.id);
}
OStore.getObject(record.id, record.type).then(function(oo) {
if (debug) {
console.log('DB.getOrCreateObjectByRecord OStore returns ' + oo);
}
if (oo) {
return q.resolve(oo);
} else {
return DB.get(record.type, [record.id]).then(function(res) {
if (debug) {
console.log('DB.getOrCreateObjectByRecord DB load returns ' + res);
}
if (res && res[0]) {
if (debug) {
console.log('DB.getOrCreateObjectByRecord found existing record in DB *');
}
record = res[0];
}
return resolver.createObjectFrom(record).then(function(ooo) {
if (debug) {
console.log('DB.getOrCreateObjectByRecord createFromRecord returns ' + ooo);
}
return q.resolve(ooo);
});
});
}
});
return q;
};
DB.byProviderId = function(type, pid) {
var q;
q = defer();
if (pid) {
DB.getDataStore().then(function(store) {
return store.byProviderId(type, pid).then(function(res) {
return q.resolve(res);
});
});
} else {
q.resolve(void 0);
}
return q;
};
DB.all = function(type, query, cb) {
return DB.getDataStore().then(function(store) {
if (store.all) {
return store.all(type, query, cb);
} else {
console.log('DB.all: All not implemented in underlying persistence logic');
return cb([]);
}
});
};
DB.count = function(type) {
var q;
q = defer();
DB.getDataStore().then(function(store) {
return store.count(type).then(function(value) {
return q.resolve(value);
});
});
return q;
};
DB.find = function(type, property, value) {
var q;
q = defer();
DB.getDataStore().then(function(store) {
return store.find(type, property, value).then(function(result) {
if (!result) {
} else {
if (!typeof result.id === 'string') {
console.log('----------***************** DB.find error: trying to cache found result but id is not a string!!!');
console.dir(result);
} else {
if (result.length) {
result.forEach(function(re) {
return DB.lru.set(re.id, re);
});
} else {
DB.lru.set(result.id, result);
}
}
}
return q.resolve(result);
});
});
return q;
};
DB.findMany = function(type, property, value) {
var q;
q = defer();
DB.getDataStore().then(function(store) {
return store.findMany(type, property, value).then(function(results) {
if (debug) {
console.log('DB.findMany results are..');
}
if (debug) {
console.dir(results);
}
if (!results || !results.length || results.length === 0) {
return q.resolve([]);
} else {
results.forEach(function(result) {
return DB.lru.set(result.id, result);
});
return q.resolve(results);
}
});
});
return q;
};
DB.findQuery = function(type, query) {
var q;
q = defer();
DB.getDataStore().then(function(store) {
return store.findQuery(type, query).then(function(results) {
if (results && results.length && results.length > 0) {
if (debug) {
console.log(' DB.findQuery got back ');
}
if (debug) {
console.dir(results);
}
results.forEach(function(result) {
if (result) {
return DB.lru.set(result.id, result);
}
});
}
return q.resolve(results);
});
});
return q;
};
DB.filter = function(type, query) {
var q;
q = defer();
DB.getDataStore().then(function(store) {
return store.filter(type, query).then(function(results) {
if (results && results.length && results.length > 0) {
if (debug) {
console.log(' DB.filter got back ');
}
if (debug) {
console.dir(results);
}
results.forEach(function(result) {
if (result) {
return DB.lru.set(result.id, result);
}
});
}
return q.resolve(results);
});
});
return q;
};
DB.search = function(type, property, value) {
var q;
q = defer();
DB.getDataStore().then(function(store) {
return store.search(type, property, value).then(function(results) {
if (!results) {
if (debug) {
console.log('DB.search type ' + type + ', property ' + property + ', value ' + value + ' got back ' + results);
}
} else {
results.forEach(function(result) {
return DB.lru.set(result.id, result);
});
}
return q.resolve(results);
});
});
return q;
};
DB.get = function(type, ids) {
var id, q, rv, toarr;
if (!type || !ids) {
console.log('********************************* DB.get called with null type or id ***********************');
console.dir(arguments);
xyzzy;
}
toarr = function(x) {
if (!Array.isArray(x)) {
x = [x];
}
return x;
};
if (!ids.length) {
ids = [ids];
}
q = defer();
id = ids[0];
if (!id) {
console.log('DB.get for type ' + type + ' was served an empty id!');
q.resolve();
} else if (typeof id === 'object') {
console.log('DB.get was served an object instead of an id!!!');
console.dir(id);
xyzzy;
} else {
rv = DB.lru.get(id);
if (rv) {
if (debug) {
console.log('DB found ' + id + ' in lru: ' + rv);
}
if (debug) {
console.dir(rv);
}
q.resolve(toarr(rv));
} else {
DB.getDataStore().then(function(store) {
return store.get(type, id, function(result) {
if (!result) {
} else {
result = toarr(result);
DB.lru.set(id, result);
if (debug) {
console.log('DB.get resolving ' + result);
}
if (debug) {
console.dir(result);
}
}
return q.resolve(result);
});
});
}
}
return q;
};
DB.set = function(type, obj, cb) {
if (obj) {
DB.lru.set(obj.id, obj);
return DB.getDataStore().then(function(store) {
return store.set(type, obj, function(res) {
return cb(res);
});
});
} else {
return cb();
}
};
DB.remove = function(obj, cb) {
DB.lru.del(obj.id);
return DB.getDataStore().then(function(store) {
return store.remove(obj.type, obj, function(res) {
if (cb) {
return cb(res);
}
});
});
};
return DB;
})();
module.exports = DB;
}).call(this);
//# sourceMappingURL=DB.js.map