Skip to content

Commit

Permalink
BF: Handle redis errors
Browse files Browse the repository at this point in the history
Fix #9

This commit offers a cleanup to unify the redis client usage
and add an error handler to handle redis connection errors. The option
for offline queue has been removed (for now) as it may grow the callback
queue to infinity and eventually result in a RangeError.
  • Loading branch information
rahulreddy committed Aug 17, 2016
1 parent b2760ba commit da09106
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 32 deletions.
34 changes: 16 additions & 18 deletions lib/UtapiClient.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Redis from 'ioredis';
import { Logger } from 'werelogs';
import Datastore from './Datastore';
import { createBucket, deleteBucket, listBucket, getBucketAcl, putBucketAcl,
Expand All @@ -9,27 +8,26 @@ import { createBucket, deleteBucket, listBucket, getBucketAcl, putBucketAcl,
deleteObject, bucketOutgoingBytes, getObject, getObjectAcl, putObjectAcl,
putObject, uploadPart,
} from './schema';
import redisClient from '../utils/redisClient';

export default class UtapiClient {
constructor(config) {
this.disableClient = true;
if (config) {
const { redis } = config;
if (redis) {
// when redis server is unavailable, commands are added to an
// offline queue and processed when redis is back again
// TODO: need to revisit this. It needs to be verified if this
// option is hogging memory under heavy load when redis is
// unavailable
redis.enableOfflineQueue = true;
// keep alive 3 seconds
redis.keepAlive = 3000;
const redisClient = new Redis(redis);
this.ds = new Datastore().setClient(redisClient);
this.disableClient = false;
this.log = new Logger('UtapiClient',
config.log || { level: 'info', dump: 'error' });
}
this.log = null;
this.ds = null;
// setup logger
if (config && config.log) {
this.log = new Logger('UtapiClient', { level: config.log.level,
dump: config.log.dumpLevel });
} else {
this.log = new Logger('UtapiClient', { level: 'info',
dump: 'error' });
}
// setup datastore
if (config && config.redis) {
this.ds = new Datastore()
.setClient(redisClient(config.redis, this.log));
this.disableClient = false;
}
}

Expand Down
16 changes: 2 additions & 14 deletions lib/server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import http from 'http';
import https from 'https';
import Redis from 'ioredis';

import { Clustering, https as arsenal } from 'arsenal';
import { Logger } from 'werelogs';
Expand All @@ -11,6 +10,7 @@ import Route from '../router/Route';
import Router from '../router/Router';
import UtapiRequest from '../lib/UtapiRequest';
import Datastore from './Datastore';
import redisClient from '../utils/redisClient';

class UtapiServer {
/**
Expand Down Expand Up @@ -178,23 +178,11 @@ export default function spawn(params) {
} else {
port = Config.port;
}
// when redis server is unavailable, commands are added to an offline queue
// and processed when redis is back again
// TODO: need to revisit this. It needs to be verified if this option
// is hogging memory under heavy load when redis is unavailable
redis.enableOfflineQueue = true;
// keep alive 3 seconds
redis.keepAlive = 3000;
const logger = new Logger('Utapi', { level: log.logLevel,
dump: log.dumpLevel });
const cluster = new Clustering(workers, logger);
cluster.start(worker => {
const redisClient = new Redis(redis);
const datastore = new Datastore().setClient(redisClient);

redisClient.on('error', err => logger.trace('error with redis client', {
error: err,
}));
const datastore = new Datastore().setClient(redisClient(redis, logger));
const server = new UtapiServer(worker, port, datastore, logger);
server.startup();
});
Expand Down
20 changes: 20 additions & 0 deletions utils/redisClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Redis from 'ioredis';

/**
* Creates a new Redis client instance
* @param {object} config - redis configuration
* @param {Werelogs} log - Werelogs logger
* @return {Redis} - Redis client instance
*/
export default function redisClient(config, log) {
const redisClient = new Redis(Object.assign({
// disable offline queue
enableOfflineQueue: false,
// keep alive 3 seconds
keepAlive: 3000,
}, config));
redisClient.on('error', err => log.trace('error with redis client', {
error: err,
}));
return redisClient;
}

0 comments on commit da09106

Please sign in to comment.