2015-12-16 22:57:58 +08:00
|
|
|
'use strict';
|
|
|
|
|
2016-10-12 00:41:59 +08:00
|
|
|
var Channel = require('./channel');
|
2016-10-12 01:01:39 +08:00
|
|
|
var QueueSeeker = require('./queue-seeker');
|
2016-10-12 00:28:46 +08:00
|
|
|
var debug = require('./../util/debug')('pubsub:subscriber');
|
|
|
|
var error = require('./../util/debug')('pubsub:subscriber:error');
|
2016-07-07 16:44:17 +08:00
|
|
|
|
2016-10-12 18:29:18 +08:00
|
|
|
var MINUTE = 60 * 1000;
|
|
|
|
var SUBSCRIBE_INTERVAL = 5 * MINUTE;
|
2016-04-05 02:00:18 +08:00
|
|
|
|
2016-10-13 03:32:29 +08:00
|
|
|
function JobSubscriber(pool, userDatabaseMetadataService) {
|
2016-07-07 20:14:46 +08:00
|
|
|
this.pool = pool;
|
2016-10-13 03:32:29 +08:00
|
|
|
this.userDatabaseMetadataService = userDatabaseMetadataService;
|
2016-10-12 01:01:39 +08:00
|
|
|
this.queueSeeker = new QueueSeeker(pool);
|
2015-12-16 22:57:58 +08:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:00:18 +08:00
|
|
|
module.exports = JobSubscriber;
|
|
|
|
|
2016-10-12 01:59:11 +08:00
|
|
|
function seeker(queueSeeker, onJobHandler, callback) {
|
2016-10-13 03:32:29 +08:00
|
|
|
queueSeeker.seek(function (err, users) {
|
2016-10-12 01:45:26 +08:00
|
|
|
if (err) {
|
2016-10-12 01:59:11 +08:00
|
|
|
if (callback) {
|
|
|
|
callback(err);
|
|
|
|
}
|
2016-10-12 01:45:26 +08:00
|
|
|
return error(err);
|
|
|
|
}
|
|
|
|
debug('queues found successfully');
|
2016-10-13 03:32:29 +08:00
|
|
|
users.forEach(onJobHandler);
|
2016-10-12 01:59:11 +08:00
|
|
|
|
|
|
|
if (callback) {
|
|
|
|
return callback(null);
|
|
|
|
}
|
2016-10-12 01:45:26 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-10-12 01:59:11 +08:00
|
|
|
JobSubscriber.prototype.subscribe = function (onJobHandler, callback) {
|
2016-03-31 23:37:35 +08:00
|
|
|
var self = this;
|
|
|
|
|
2016-10-13 03:32:29 +08:00
|
|
|
function wrappedJobHandlerListener(user) {
|
|
|
|
self.userDatabaseMetadataService.getUserMetadata(user, function (err, userDatabaseMetadata) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
return onJobHandler(user, userDatabaseMetadata.host);
|
|
|
|
});
|
|
|
|
}
|
2016-10-12 01:45:26 +08:00
|
|
|
|
2016-10-13 03:32:29 +08:00
|
|
|
seeker(this.queueSeeker, wrappedJobHandlerListener, function(err) {
|
|
|
|
if (callback) {
|
|
|
|
callback(err);
|
2016-07-07 20:14:46 +08:00
|
|
|
}
|
|
|
|
|
2016-10-13 03:32:29 +08:00
|
|
|
// do not start any pooling until first seek has finished
|
|
|
|
self.seekerInterval = setInterval(seeker, SUBSCRIBE_INTERVAL, self.queueSeeker, wrappedJobHandlerListener);
|
2016-10-12 01:45:26 +08:00
|
|
|
|
2016-10-13 03:32:29 +08:00
|
|
|
self.pool.acquire(Channel.DB, function (err, client) {
|
|
|
|
if (err) {
|
|
|
|
return error('Error adquiring redis client: ' + err.message);
|
|
|
|
}
|
2016-10-12 01:45:43 +08:00
|
|
|
|
2016-10-13 03:32:29 +08:00
|
|
|
self.client = client;
|
|
|
|
client.removeAllListeners('message');
|
|
|
|
client.unsubscribe(Channel.NAME);
|
|
|
|
client.subscribe(Channel.NAME);
|
|
|
|
|
|
|
|
client.on('message', function (channel, user) {
|
|
|
|
debug('message received in channel=%s from user=%s', channel, user);
|
|
|
|
wrappedJobHandlerListener(user);
|
|
|
|
});
|
|
|
|
|
|
|
|
client.on('error', function () {
|
|
|
|
self.unsubscribe();
|
|
|
|
self.pool.release(Channel.DB, client);
|
|
|
|
self.subscribe(onJobHandler);
|
|
|
|
});
|
2016-10-12 01:45:43 +08:00
|
|
|
});
|
2016-07-07 20:14:46 +08:00
|
|
|
});
|
2015-12-16 22:57:58 +08:00
|
|
|
};
|
|
|
|
|
2016-10-12 18:29:54 +08:00
|
|
|
JobSubscriber.prototype.unsubscribe = function (callback) {
|
2016-04-05 02:00:18 +08:00
|
|
|
clearInterval(this.seekerInterval);
|
2016-07-07 20:14:46 +08:00
|
|
|
if (this.client && this.client.connected) {
|
2016-10-12 18:29:54 +08:00
|
|
|
this.client.unsubscribe(Channel.NAME, callback);
|
|
|
|
} else {
|
2016-10-13 03:32:29 +08:00
|
|
|
if (callback) {
|
|
|
|
return callback(null);
|
|
|
|
}
|
2016-07-07 20:14:46 +08:00
|
|
|
}
|
2015-12-23 03:12:10 +08:00
|
|
|
};
|