UNPKG

@tiledesk/tiledesk-server

Version:
360 lines (273 loc) 10.7 kB
var amqp = require('amqplib/callback_api'); var listeners = []; class QueueManager { constructor(url, options) { this.debug = false; if (options && options.debug!=undefined) { this.debug = options.debug; } this.pubChannel = null; this.offlinePubQueue = []; // if the connection is closed or fails to be established at all, we will reconnect this.amqpConn = null; this.url = url || "amqp://localhost"; // process.env.CLOUDAMQP_URL + "?heartbeat=60" // this.exchange = 'amq.topic'; this.exchange = 'tiledeskserver'; if (options && options.exchange!=undefined) { this.exchange = options.exchange; } this.defaultTopic = "subscription_run"; if (options && options.defaultTopic!=undefined) { this.defaultTopic = options.defaultTopic; } this.topic = "jobsmanager"; if (options && options.topic!=undefined) { this.topic = options.topic; } // this.listeners = []; } connect(callback) { var that = this; // console.log("[JobWorker] connect", this.url); // return new Promise(function (resolve, reject) { amqp.connect(this.url, function(err, conn) { if (err) { // if (this.debug) {console.log("[AMQP]", err.message); console.error("[JobWorker] AMQP error", err); return setTimeout(function () { if (that.debug) { console.log("[JobWorker] AMQP reconnecting"); } that.connect(callback) }, 1000); } conn.on("error", function(err) { if (err.message !== "Connection closing") { console.log("[JobWorker] AMQP conn error", err); } }); conn.on("close", function() { // if (that.debug) {console.log("[JobWorker] AMQP reconnecting");} console.log("[JobWorker] AMQP reconnecting") return setTimeout(() => { that.connect(callback); }, 1000); }); console.log("[JobWorker] AMQP connected") that.amqpConn = conn; // that.whenConnected(callback); if (callback) { callback('Connected', null); } // return resolve(); // }); }); } close(callback) { if (this.debug) { console.log("Closing connection.."); }; this.amqpConn.close((err) => { callback(err); }); } whenConnected(callback) { var that = this; // that.startPublisher(callback); that.startPublisher(); that.startWorker(callback); } startPublisher(callback) { var that = this; that.amqpConn.createConfirmChannel(function (err, ch) { if (that.closeOnErr(err)) return; ch.on("error", function (err) { if (that.debug) { console.log("[JobWorker] AMQP channel error", err); } }); ch.on("close", function () { if (that.debug) { console.log("[JobWorker] AMQP channel closed"); } }); // if (this.debug) {console.log("[AMQP] pubChannel"); that.pubChannel = ch; // console.log("[JobWorker] that.pubChannel",that.pubChannel); // while (true) { // var m = that.offlinePubQueue.shift(); // if (!m) break; // that.publish(m[0], m[1], m[2]); // } if (callback) { callback(err); } }); } // method to publish a message, will queue messages internally if the connection is down and resend later publish(exchange, routingKey, content, callback) { var that = this; if (that.debug) {console.log("[JobWorker] that", that);} if (that.debug) {console.log("[JobWorker] that.pubChannel", that.pubChannel);} that.pubChannel.publish(exchange, routingKey, content, { persistent: false }, function(err, ok) { callback(err, ok) } ); // try { // if (that.debug) {console.log("[JobWorker] that", that);} // if (that.debug) {console.log("[JobWorker] that.pubChannel", that.pubChannel);} // that.pubChannel.publish(exchange, routingKey, content, { persistent: false }, // function(err, ok) { // callback(err, ok) // // if (err) { // // // if (that.debug) {console.log("[JobWorker] AMQP publish", err);} // // // console.log("[JobWorker] AMQP publish", err); // // // that.offlinePubQueue.push([exchange, routingKey, content]); // // // that.pubChannel.connection.close(); // // } // // console.log("publish OK") // // // if (that.debug) {console.log("[AMQP] publish sent", content);} // }); // } catch (e) { // console.log("[JobWorker] AMQP publish catch", e); // if (this.debug) {console.log("[JobWorker] AMQP publish", e);} // that.offlinePubQueue.push([exchange, routingKey, content]); // } } // A worker that acks messages only if processed succesfully // var channel; startWorker(callback) { var that = this; that.amqpConn.createChannel(function(err, ch) { if (that.closeOnErr(err)) return; ch.on("error", function(err) { if (this.debug) {console.log("[JobWorker] AMQP channel error", err);} }); ch.on("close", function() { if (this.debug) {console.log("[JobWorker] AMQP channel closed");} }); ch.prefetch(10); ch.assertExchange(that.exchange, 'topic', { durable: false }); if (that.debug) {console.log("[JobWorker] AMQP that.topic", that.topic);} ch.assertQueue(that.topic, { durable: false }, function(err, _ok) { if (that.closeOnErr(err)) return; ch.bindQueue(_ok.queue, that.exchange, that.defaultTopic, {}, function(err3, oka) { if (that.debug) {console.log("[JobWorker] Queue bind: "+_ok.queue+ " err: "+err3+ " key: " + that.defaultTopic );} // if (this.debug) {console.log("Data queue", oka) }); ch.bindQueue(_ok.queue, that.exchange, "functions", {}, function(err3, oka) { if (that.debug) {console.log("[JobWorker] Queue bind: "+_ok.queue+ " err: "+err3+ " key: " + "functions" );} // if (this.debug) {console.log("Data queue", oka) }); if (that.debug) {console.log("[JobWorker] AMQP that.topic", that.topic);} ch.consume(that.topic, that.processMsg2, { noAck: true }); // ch.consume("jobs", that.processMsg, { noAck: false }); if (that.debug) {console.log("[JobWorker] Worker is started");} if (callback) { callback(); if (that.debug) {console.log("[JobWorker] called callback worker");} } }); }); } // work(msg, cb) { // const message_string = msg.content.toString(); // const topic = msg.fields.routingKey //.replace(/[.]/g, '/'); // if (this.debug) {console.log("Got msg topic:" + topic); // if (this.debug) {console.log("Got msg:"+ message_string + " topic:" + topic); // if (topic === 'subscription_run') { // if (this.debug) {console.log("here topic:" + topic); // // requestEvent.emit('request.create.queue', msg.content); // subscriptionEvent.emit('subscription.run.queue', JSON.parse(message_string)); // } // cb(true); // if (this.debug) {console.log("okookokkkkkkk msg:"); // } processMsg2(msg) { // console.log("processMsg2:", msg); const message_string = msg.content.toString(); // console.log("processMsg2.1:", msg); const topic = msg.fields.routingKey //.replace(/[.]/g, '/'); // console.log("processMsg2.2:", msg); // if (this.debug) {console.log("Got msg topic:" + topic);} //this is undefined in this method // console.log("Got msg topic:" + topic); // if (this.debug) {console.log("Got msg1:"+ message_string + " topic:" + topic);} // console.log("Got msg1:"+ message_string + " topic:" + topic); if (topic === 'functions') { // if (this.debug) {console.log("Got msg2:"+ JSON.stringify(message_string) + " topic:" + topic);} // console.log("Got msg2:"+ JSON.stringify(message_string) + " topic:" + topic); var fdata = JSON.parse(message_string) // if (this.debug) {console.log("Got msg3:"+ fdata.function + " fdata.function:", fdata.payload);} /* // var fields = Object.keys(fdata.payload).map((key) => [key, fdata.payload[key]]); // var fields = Object.keys(fdata.payload) // if (this.debug) {console.log("Got fields:"+ fields ); // eval(fdata.function) */ if (fdata.function) { var fn = new Function("payload", fdata.function); // if (this.debug) {console.log("Got fn:"+ fn);} /* // var fn = new Function(fields, fdata.function); // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function // var fn = new Function("name",'if (this.debug) {console.log("ciao: " + name);'); // fn("andrea") // var dataArray = Object.keys(fdata.payload).map(function(k){return fdata.payload[k]}); // if (this.debug) {console.log("Got dataArray:", dataArray ); // fn(dataArray); */ var ret = fn(fdata.payload) // if (this.debug) {console.log("Got ret:"+ ret);} // console.log("Got ret:"+ ret); } // else { // console.log("no function found"); // } } // if (topic === 'subscription_run') { // if (this.debug) {console.log("here topic:" + topic); // // requestEvent.emit('request.create.queue', msg.content); // subscriptionEvent.emit('subscription.run.queue', JSON.parse(message_string)); // } // serve? // if (this.debug) {console.log("listeners.length:" + listeners.length);} if (listeners && listeners.length>0) { for( var i = 0; i< listeners.length; i++) { // if (this.debug) {console.log("listeners[i]:" + listeners[i]);} listeners[i](fdata); } } // if (this.debug) {console.log("listeners", this.listeners); } // processMsg(msg) { // if (this.debug) {console.log("processMsg msg:", msg); // var that = this; // that.work(msg, function(ok) { // try { // if (ok) // ch.ack(msg); // else // ch.reject(msg, true); // } catch (e) { // that.closeOnErr(e); // } // }); // } closeOnErr(err) { if (!err) return false; console.error("[JobWorker] AMQP error", err); this.amqpConn.close(); return true; } sendJson(data, topic, callback) { this.publish(this.exchange, topic || this.defaultTopic, Buffer.from(JSON.stringify(data)), (err, ok) => { if (callback) { callback(err, ok); } }); } send(string, topic) { if (this.debug) {console.log("[JobWorker] send(string): ", string);} this.publish(this.exchange, topic || this.defaultTopic, Buffer.from(string)); } on(fn) { listeners.push(fn); } } module.exports = QueueManager;