UNPKG

core

Version:

Core Libs

218 lines (165 loc) 7.69 kB
var Request = require('../http/Request.js').Request; var Response = require('../http/Response.js').Response; var Loader = require('../http/Loader.js').Loader; var Memcached = require('../client/Memcached.js').Memcached; var MemcachedSocket = require('../client/MemcachedSocket.js').MemcachedSocket; var md5 = require('../crypto/Crypto.js').md5; var Event = require('../event/Event.js').Event; var ErrorEvent = require('../event/ErrorEvent.js').ErrorEvent; var EventDispatcher = require('../event/EventDispatcher.js').EventDispatcher; var memcachedPool = null; var storage = {}; var CacheLoader = function (request, options) { Loader.call(this, request); if (!memcachedPool) { memcachedPool = new Memcached(options); } this._prefix = { meta: "latest!headers!", body: "latest!body!" }; }; CacheLoader.prototype = Object.create(Loader.prototype); CacheLoader.prototype.load = function (request, force) { var that = this, response = new Response(), cacheKey = this._getCacheKey(undefined, request); if (!force && storage[cacheKey] && storage[cacheKey][CacheLoader.Prefix.META] && storage[cacheKey][CacheLoader.Prefix.BODY]) { var headersData = storage[cacheKey][CacheLoader.Prefix.META]; response.setStatusCode(headersData.statusCode); response.setHeaders(headersData.headers); this.dispatchEvent(new Event(CacheLoader.Event.HEADERS, { "statusCode": headersData.statusCode, "headers": headersData.headers, "httpVersion": null, "body": null, "response": response, "expire": headersData.expire, "generating": headersData.generating, "generatingStarted": headersData.generatingStarted })); var bodyData = storage[cacheKey][CacheLoader.Prefix.BODY]; response.write(bodyData); this.dispatchEvent(new Event(CacheLoader.Event.PROGRESS, bodyData)); response.end(); this.dispatchEvent(new Event(CacheLoader.Event.LOADED, response)); } else { if (!storage.hasOwnProperty(cacheKey)) { storage[cacheKey] = {}; } var headersKey = this._getMemcacheKey(CacheLoader.Prefix.META, request); var mSocketHeaders = memcachedPool.get(headersKey); mSocketHeaders.addEventListener(MemcachedSocket.Event.END, function (e) { if (e.data) { var headersData = JSON.parse(e.data); storage[cacheKey][CacheLoader.Prefix.META] = JSON.parse(e.data); response.setStatusCode(headersData.statusCode); response.setHeaders(headersData.headers); that.dispatchEvent(new Event(CacheLoader.Event.HEADERS, { "statusCode": headersData.statusCode, "headers": headersData.headers, "httpVersion": null, "body": null, "response": response, "expire": headersData.expire })); var bodyKey = that._getMemcacheKey(CacheLoader.Prefix.BODY, request); var mSocketBody = memcachedPool.get(bodyKey); mSocketBody.addEventListener(MemcachedSocket.Event.PROGRESS, function (e) { response.write(e.data); that.dispatchEvent(new Event(CacheLoader.Event.PROGRESS, e.data)); }); mSocketBody.addEventListener(MemcachedSocket.Event.END, function (e) { response.end(); storage[cacheKey][CacheLoader.Prefix.BODY] = response.getBody().toBuffer(); that.dispatchEvent(new Event(CacheLoader.Event.LOADED, response)); }); } else { that.dispatchEvent(new Event(CacheLoader.Event.HEADERS, { "statusCode": null, "headers": null, "httpVersion": null, "body": null, "response": null, "expire": null })); } }); } }; CacheLoader.prototype.upload = function(request, response){ var cacheKey = this._getCacheKey(undefined, request); if (!storage.hasOwnProperty(cacheKey)) { storage[cacheKey] = {}; } var memcacheKeyHeaders = this._getMemcacheKey(CacheLoader.Prefix.META, request); var memcacheKeyBody = this._getMemcacheKey(CacheLoader.Prefix.BODY, request); //console.error('\nMEMCACHE KEYS: \n%s\n%s\n', memcacheKeyHeaders, memcacheKeyBody); var headersData = { url: request.getUrl(), headers: JSON.parse(JSON.stringify(response.getHeaders())), statusCode: response.getStatusCode(), expire: Date.now() + (response.getCacheTimeInSeconds() * 1000) }; storage[cacheKey][CacheLoader.Prefix.META] = JSON.parse(JSON.stringify(headersData)); var headersBuffer = new Buffer(JSON.stringify(headersData), 'utf8'); var mSocketHeaders = memcachedPool.set(memcacheKeyHeaders, { lifetime: 0, length: headersBuffer.length, waitForReply: false }); mSocketHeaders.write(headersBuffer); var mSocketBody = memcachedPool.set(memcacheKeyBody, { lifetime: 0, length: response.getHeader('content-length'), waitForReply: false }); mSocketBody.addEventListener(MemcachedSocket.Event.END, function () { }); response.addEventListener(Response.Event.WRITE, function (e) { mSocketBody.write(e.data); }); response.addEventListener(Response.Event.END, function (e) { storage[cacheKey][CacheLoader.Prefix.BODY] = response.getBody().toBuffer(); }); }; CacheLoader.prototype.generating = function(request){ var cacheKey = this._getCacheKey(undefined, request); var memcacheKeyHeaders = this._getMemcacheKey(CacheLoader.Prefix.META, request); storage[cacheKey][CacheLoader.Prefix.META].generating = true; storage[cacheKey][CacheLoader.Prefix.META].generatingStarted = Date.now(); var headersBuffer = new Buffer(JSON.stringify(storage[cacheKey][CacheLoader.Prefix.META]), 'utf8'); var mSocketHeaders = memcachedPool.set(memcacheKeyHeaders, { lifetime: 0, length: headersBuffer.length, waitForReply: false }); mSocketHeaders.write(headersBuffer); }; CacheLoader.prototype['delete'] = function (request) { var cacheKey = this._getCacheKey(undefined, request); storage[cacheKey] = null; delete storage[cacheKey]; var memcacheKeyHeaders = this._getMemcacheKey(CacheLoader.Prefix.META, request), memcacheKeyBody = this._getMemcacheKey(CacheLoader.Prefix.BODY, request); memcachedPool['delete'](memcacheKeyHeaders); memcachedPool['delete'](memcacheKeyBody); }; CacheLoader.prototype._getCacheKey = function (key, request) { return md5(request.getUrl()); }; CacheLoader.prototype._getMemcacheKey = function (key, request) { return this._prefix[key] + this._getCacheKey(key, request); }; CacheLoader.Event = {}; CacheLoader.Event.HEADERS = "Loader_HEADERS"; CacheLoader.Event.PROGRESS = "Loader_PROGRESS"; CacheLoader.Event.LOADED = "Loader_LOADED"; CacheLoader.Event.ERROR = "Loader_ERROR"; CacheLoader.Prefix = {}; CacheLoader.Prefix.META = "meta"; CacheLoader.Prefix.BODY = "body"; exports.CacheLoader = CacheLoader;