UNPKG

nodebjectify

Version:

Abstraction layer for using Google Appengine datastore & memcache on NodeJs

205 lines (168 loc) 4.65 kB
'use strict'; const Datastore = require('./index')().Datastore; const Cache = require('./cache')(); const Q = require('q'); function generateCacheName(kind, id) { return kind+'_'+id; } class Model { constructor(data) { data = data || {}; let _this = this; Object.keys(data).forEach(function(key){ _this[key] = data[key]; }); if(!this.createdAt) { this.createdAt = new Date(); } } // INTROSPECTION static getKind() { return this.prototype.constructor.name; } // NODEBJECTIFY static runQuery(query) { let _this = this; let deferred = Q.defer(); Datastore.runQuery(query).then(function(resp){ if(!resp.entities || resp.entities.length === 0) { return deferred.resolve({models:[], nextQuery: null}); } let models = []; resp.entities.forEach(function(entity){ models.push(new _this.prototype.constructor(entity)); }); return deferred.resolve({models:models, nextQuery: resp.nextQuery}); }).catch(function(err){ deferred.reject(new Error(err)); }); return deferred.promise; } static query() { return Datastore.createQuery(this.getKind()); } static get(id) { //console.log('get', id); let _this = this; let deferred = Q.defer(); Q.spawn(function* () { try { //console.log('get model from cache'); let model = yield _this.getFromCache(id); //console.log('model from cache', model); if(model) { //console.log('cache version available'); return deferred.resolve(model); } //console.log('cache version NOT available'); model = yield _this.getFromDatastore(id); if(model) { yield model.setToCache(); } deferred.resolve(model); } catch(err) { console.log('error in get !!!', err); deferred.reject(new Error(err)); } }); return deferred.promise; } static del(id) { let _this = this; let deferred = Q.defer(); //console.log('del', id); Q.spawn(function* () { try { yield _this.delFromCache(id); //console.log('deleted from cache'); let resp = yield _this.delFromDatastore(id); //console.log('deleted from ds'); deferred.resolve(resp); } catch(err) { deferred.reject(new Error(err)); } }); return deferred.promise; } save() { let _this = this; let deferred = Q.defer(); Q.spawn(function* () { try { _this.updatedAt = new Date(); let model = null; let isNew = (typeof _this.id !== 'number') && (typeof _this.id !== 'string'); //console.log('is new',isNew, _this); if(!isNew) { yield _this.setToCache(); } model = yield _this.setToDatastore(); if(isNew) { yield _this.setToCache(); } deferred.resolve(model); } catch(err) { deferred.reject(new Error(err)); } }); return deferred.promise; } del() { //console.log('this.del', this); return this.constructor.del(this.id); } // DATASTORE static getFromDatastore(id) { let _this = this; let deferred = Q.defer(); Datastore.get(this.getKind(), id).then(function(model){ if(!model) { return deferred.resolve(); } deferred.resolve( new _this.prototype.constructor(model) ); }); return deferred.promise; } static delFromDatastore(id) { //console.log('del from DS', this.getKind(), id); return Datastore.del(this.getKind(), id); } setToDatastore() { return Datastore.save(this.constructor.getKind(), this); } delFromDatastore() { //console.log('del instance', this); return this.constructor.delFromDatastore(this.id); } // CACHE static getCacheName(id) { return generateCacheName(this.getKind(),id); } static getFromCache(id) { let _this = this; let deferred = Q.defer(); Cache.get(this.getCacheName(id)).then(function(model){ //console.log('cache.get', model); if(!model) { return deferred.resolve(); } deferred.resolve( new _this.prototype.constructor(model) ); }); return deferred.promise; } static delFromCache(id) { return Cache.del(this.getCacheName(id)); } setToCache(lifetime) { //console.log('set to cache', this); //console.log(this); return Cache.set(this.constructor.getCacheName(this.id), this, lifetime); } delFromCache() { return this.constructor.delFromCache(this.id); } } module.exports = Model;