Fix session memory leak

This commit is contained in:
Jonathan Cremin 2015-08-22 18:24:39 +01:00
parent 0289bddde8
commit 046d8475cb
6 changed files with 62 additions and 32 deletions

View file

@ -11,12 +11,12 @@ const debug = debugname('hostr-api');
const router = new Router(); const router = new Router();
let statsdOpts = {prefix: 'hostr-api', host: process.env.STATSD_HOST || 'localhost'}; let statsdOpts = {prefix: 'hostr-api', host: process.env.STATSD_HOST || 'localhost'};
router.use(stats(statsdOpts));
let statsd = new StatsD(statsdOpts); let statsd = new StatsD(statsdOpts);
router.use(function*(next) { router.use(function*(next) {
this.statsd = statsd; this.statsd = statsd;
yield next; yield next;
}); });
router.use(stats(statsdOpts));
router.use(cors({ router.use(cors({
origin: '*', origin: '*',

7
app.js
View file

@ -9,9 +9,10 @@ import favicon from 'koa-favicon';
import compress from 'koa-compress'; import compress from 'koa-compress';
import bodyparser from 'koa-bodyparser'; import bodyparser from 'koa-bodyparser';
import websockify from 'koa-websocket'; import websockify from 'koa-websocket';
import helmet from 'koa-helmet';
import raven from 'raven'; import raven from 'raven';
import mongo from './lib/mongo'; import mongo from './lib/mongo';
import redis from './lib/redis'; import * as redis from './lib/redis';
import co from 'co'; import co from 'co';
import api from './api/app'; import api from './api/app';
import web from './web/app'; import web from './web/app';
@ -29,6 +30,8 @@ if (process.env.SENTRY_DSN) {
const app = websockify(koa()); const app = websockify(koa());
app.keys = [process.env.KEYS || 'INSECURE']; app.keys = [process.env.KEYS || 'INSECURE'];
app.use(helmet());
app.use(function* (next){ app.use(function* (next){
this.set('Server', 'Nintendo 64'); this.set('Server', 'Nintendo 64');
if(this.req.headers['x-forwarded-proto'] === 'http'){ if(this.req.headers['x-forwarded-proto'] === 'http'){
@ -38,7 +41,7 @@ app.use(function* (next){
}); });
app.use(mongo()); app.use(mongo());
app.use(redis()); app.use(redis.middleware());
app.use(logger()); app.use(logger());
app.use(compress()); app.use(compress());
app.use(bodyparser()); app.use(bodyparser());

View file

@ -1,29 +1,59 @@
import redis from 'redis-url'; import redis from 'redis-url';
import coRedis from 'co-redis'; import coRedis from 'co-redis';
import koaRedis from 'koa-redis';
import session from 'koa-generic-session';
import debugname from 'debug'; import debugname from 'debug';
const debug = debugname('hostr:redis'); const debug = debugname('hostr:redis');
const redisUrl = process.env.REDIS_URL || process.env.REDISTOGO_URL || 'redis://localhost:6379'; const redisUrl = process.env.REDIS_URL || process.env.REDISTOGO_URL || 'redis://localhost:6379';
let connection = new Promise((resolve, reject) => { const connection = new Promise((resolve, reject) => {
debug('Connecting to Redis'); debug('Connecting to Redis');
const client = redis.connect(redisUrl); resolve(redis.connect(redisUrl));
const wrapped = coRedis(client);
wrapped.client = client;
wrapped.on('error', (err) => {
debug('Client error: ' + err);
});
wrapped.on('ready', () => {
debug('Successfully connected to Redis');
resolve(wrapped);
});
}).catch((err) => { }).catch((err) => {
debug('Promise error: ' + err); debug('Connection error: ' + err);
}); });
export default function () { const redisSession = new Promise((resolve, reject) => {
return function* redisMiddleware(next) { return connection.then((client) => {
this.redis = yield connection; client = koaRedis({client: client});
resolve(session({
key: 'hid',
store: client
}));
}).catch((err) => {
debug('koa-redis error: ' + err);
reject(err);
});
});
const wrapped = new Promise((resolve, reject) => {
return connection.then((client) => {
client = coRedis(client);
client.on('error', (err) => {
debug('Client error: ' + err);
reject(err);
});
client.on('ready', () => {
debug('Successfully connected to Redis');
resolve(client);
});
}).catch((err) => {
debug('co-redis error: ' + err);
reject(err);
});
});
export function sessionStore() {
return function* (next) {
const sess = yield redisSession;
yield sess.bind(this)(next);
}
}
export function middleware() {
return function* (next) {
this.redis = yield wrapped;
yield next; yield next;
} }
} }

View file

@ -23,7 +23,7 @@
"watch-sass": "node-sass -w -r -o web/public/styles/ web/public/styles/" "watch-sass": "node-sass -w -r -o web/public/styles/ web/public/styles/"
}, },
"dependencies": { "dependencies": {
"aws-sdk": "~2.1.45", "aws-sdk": "~2.1.46",
"babel": "~5.8.21", "babel": "~5.8.21",
"basic-auth": "~1.0.3", "basic-auth": "~1.0.3",
"co": "~4.6.0", "co": "~4.6.0",
@ -43,9 +43,10 @@
"koa-favicon": "~1.2.0", "koa-favicon": "~1.2.0",
"koa-file-server": "~2.3.1", "koa-file-server": "~2.3.1",
"koa-generic-session": "~1.9.0", "koa-generic-session": "~1.9.0",
"koa-helmet": "^0.2.0",
"koa-logger": "~1.3.0", "koa-logger": "~1.3.0",
"koa-mount": "~1.3.0", "koa-mount": "~1.3.0",
"koa-redis": "~1.0.0", "koa-redis": "~1.0.1",
"koa-route": "~2.4.2", "koa-route": "~2.4.2",
"koa-router": "^5.1.2", "koa-router": "^5.1.2",
"koa-static": "^1.4.9", "koa-static": "^1.4.9",
@ -53,7 +54,7 @@
"koa-views": "~3.1.0", "koa-views": "~3.1.0",
"koa-websocket": "~1.0.0", "koa-websocket": "~1.0.0",
"mandrill-api": "~1.0.45", "mandrill-api": "~1.0.45",
"mime-types": "~2.1.4", "mime-types": "~2.1.5",
"mkdirp": "~0.5.1", "mkdirp": "~0.5.1",
"moment": "~2.10.6", "moment": "~2.10.6",
"mongodb-promisified": "~1.0.3", "mongodb-promisified": "~1.0.3",
@ -71,7 +72,7 @@
"virustotal.js": "~0.3.1" "virustotal.js": "~0.3.1"
}, },
"devDependencies": { "devDependencies": {
"eslint": "~1.2.0", "eslint": "~1.2.1",
"istanbul": "~0.3.18", "istanbul": "~0.3.18",
"mocha": "~2.2.5", "mocha": "~2.2.5",
"nodemon": "~1.4.1", "nodemon": "~1.4.1",

View file

@ -3,9 +3,7 @@ import Router from 'koa-router';
import csrf from 'koa-csrf'; import csrf from 'koa-csrf';
import views from 'koa-views'; import views from 'koa-views';
import stats from 'koa-statsd'; import stats from 'koa-statsd';
import redis from '../lib/redis'; import * as redis from '../lib/redis';
import koaRedis from 'koa-redis'
import session from 'koa-generic-session';
import co from 'co'; import co from 'co';
import StatsD from 'statsy'; import StatsD from 'statsy';
// waiting for PR to be merged, can remove swig dependency when done // waiting for PR to be merged, can remove swig dependency when done
@ -22,18 +20,16 @@ const router = new Router();
router.use(errors({template: path.join(__dirname, 'public', '404.html')})); router.use(errors({template: path.join(__dirname, 'public', '404.html')}));
let statsdOpts = {prefix: 'hostr-web', host: process.env.STATSD_HOST || 'localhost'}; let statsdOpts = {prefix: 'hostr-web', host: process.env.STATSD_HOST || 'localhost'};
router.use(stats(statsdOpts));
let statsd = new StatsD(statsdOpts); let statsd = new StatsD(statsdOpts);
router.use(function* (next) { router.use(function* (next) {
this.statsd = statsd; this.statsd = statsd;
yield next; yield next;
}); });
router.use(stats(statsdOpts));
router.use(session({ router.use(redis.sessionStore());
store: koaRedis({client: redis().client})
}));
router.use(function* (next){ router.use(function* (next) {
this.state = { this.state = {
session: this.session, session: this.session,
apiURL: process.env.API_URL, apiURL: process.env.API_URL,

View file

@ -45,7 +45,7 @@ export function* get() {
localPath = path.join(storePath, file._id[0], this.params.size, file._id + '_' + file.file_name); localPath = path.join(storePath, file._id[0], this.params.size, file._id + '_' + file.file_name);
remotePath = path.join(this.params.size, file._id + '_' + file.file_name); remotePath = path.join(this.params.size, file._id + '_' + file.file_name);
} }
console.log(localPath);
if (file.malware) { if (file.malware) {
this.statsd.incr('file.malware.download', 1); this.statsd.incr('file.malware.download', 1);
} }
@ -82,7 +82,7 @@ export function* landing() {
this.params.name = file.file_name; this.params.name = file.file_name;
return yield get.call(this); return yield get.call(this);
} }
console.log('incr')
this.statsd.incr('file.landing', 1); this.statsd.incr('file.landing', 1);
const formattedFile = formatFile(file); const formattedFile = formatFile(file);
yield this.render('file', {file: formattedFile}); yield this.render('file', {file: formattedFile});