diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0b850e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.idea +/node_modules \ No newline at end of file diff --git a/index.js b/index.js index 81a19ef..73a7e54 100644 --- a/index.js +++ b/index.js @@ -1,39 +1,38 @@ - var net = require('net'); var Client = module.exports = { - DEFAULT_ADDR : '127.0.0.1', - DEFAULT_PORT : 11300, - LOWEST_PRIORITY : 4294967295, - - connect : function(server, callback) { - var server_tokens, host, port; - - if (server) { - server_tokens = server.split(':'); - host = server_tokens[0]; - port = server_tokens[1]; - } - - //use defaults for address/port if not specified - host || (host = Client.DEFAULT_ADDR); - port || (port = Client.DEFAULT_PORT); - - //establish tcp connection - var stream = net.createConnection(port, host); - - stream.on('connect', function() { - //successfully connected. remove the error listener. - stream.removeAllListeners('error'); - - return callback(null, new Connection(stream)); - }); - - stream.on('error', function(err) { - return callback(err); - }); - } + DEFAULT_ADDR: '127.0.0.1', + DEFAULT_PORT: 11300, + LOWEST_PRIORITY: 4294967295, + + connect: function (server, callback) { + var server_tokens, host, port; + + if (server) { + server_tokens = server.split(':'); + host = server_tokens[0]; + port = server_tokens[1]; + } + + //use defaults for address/port if not specified + host || (host = Client.DEFAULT_ADDR); + port || (port = Client.DEFAULT_PORT); + + //establish tcp connection + var stream = net.createConnection(port, host); + + stream.on('connect', function () { + //successfully connected. remove the error listener. + stream.removeAllListeners('error'); + + return callback(null, new Connection(stream)); + }); + + stream.on('error', function (err) { + return callback(err); + }); + } }; @@ -41,63 +40,67 @@ var Client = module.exports = { * Connection */ function Connection(stream) { - this.stream = stream; - this.data = ''; - this.handlers = []; - - var self = this; - - self.stream.on('data', function(data) { - self.data += data; - - while(self.data.length && self._tryToRespond()); - }); - - //register error listeners on stream - self.stream.on('error', function(err) { - self._last_error = err; - }); - self.stream.on('close', function(had_error) { - var err = had_error ? self._last_error : new Error('connection closed'); - - //relay the error to all pending callback's inside handlers - self.handlers.forEach(function(handler) { - handler[1](err); - }); - - self.handlers = []; - }); + this.stream = stream; + this.data = ''; + this.handlers = []; + + var self = this; + + self.stream.on('data', function (data) { + self.data += data; + + while (self.data.length && self._tryToRespond()) ; + }); + + //register error listeners on stream + self.stream.on('error', function (err) { + self._last_error = err; + }); + self.stream.on('close', function (had_error) { + var err = had_error ? self._last_error : new Error('connection closed'); + + //relay the error to all pending callback's inside handlers + self.handlers.forEach(function (handler) { + handler[1](err); + }); + + self.handlers = []; + }); }; -Connection.prototype._tryToRespond = function() { - var handler = this.handlers[0]; - - var response = handler[0]; - var callback = handler[1]; - - response.parse(this.data); - - if (response.complete) { - this.data = this.data.substr(response.consumed_data_length); - this.handlers.shift(); - - if (response.success) { - callback.apply(null, [false].concat(response.args)); - } else { - callback.call(null, response.args[0]); - } - } - - return response.complete; +Connection.prototype._tryToRespond = function () { + var handler = this.handlers[0]; + + var response = handler[0]; + var callback = handler[1]; + + response.parse(this.data); + + if (response.complete) { + this.data = this.data.substr(response.consumed_data_length); + this.handlers.shift(); + + if (response.success) { + if (response.receives_yaml) { + callback.apply(null, [false].concat(response.yaml_data)); + } else { + callback.apply(null, [false].concat(response.args)); + } + } else { + callback.call(null, response.args[0]); + } + } + + return response.complete; }; -Connection.prototype.send = function(args) { - var packet = args.join(' ') + '\r\n'; - this.stream.write(packet); +Connection.prototype.send = function (args) { + var packet = args.join(' ') + '\r\n'; + this.stream.write(packet); }; -Connection.prototype.end = function() { - this.stream.end(); +Connection.prototype.end = function () { + this.stream.end(); }; //submitting jobs @@ -119,105 +122,142 @@ Connection.prototype.peek_delayed = makeCommandMethod('peek-delayed', 'FOUND'); Connection.prototype.peek_buried = makeCommandMethod('peek-buried', 'FOUND'); Connection.prototype.kick = makeCommandMethod('kick', 'KICKED'); Connection.prototype.stats_job = makeCommandMethod('stats-job', 'OK'); -Connection.prototype.stats_tube = makeCommandMethod('stats-tube', 'OK'); +Connection.prototype.stats_tube = makeCommandMethod('stats-tube', 'OK', false, true); Connection.prototype.stats = makeCommandMethod('stats', 'OK'); -function makeCommandMethod(command_name, expected_response, sends_data) { - return function() { - var args = Array.prototype.slice.call(arguments); - args.unshift(command_name); - - var callback = args.pop(); - - //add a response handler for this command - var handler = [new Response(expected_response), callback]; - this.handlers.push(handler); - - if (sends_data) { - //first send header with length of data in bytes. then send data. - var data = args.pop(); - args.push(Buffer.byteLength(data, 'utf8')); - this.send(args); - this.send([data]) - } else { - this.send(args); - } - }; -}; +function makeCommandMethod(command_name, expected_response, sends_data, receives_yaml) { + return function () { + var args = Array.prototype.slice.call(arguments); + args.unshift(command_name); + + var callback = args.pop(); + //add a response handler for this command + var handler = [new Response(expected_response, receives_yaml), callback]; + this.handlers.push(handler); + + if (sends_data) { + //first send header with length of data in bytes. then send data. + var data = args.pop(); + args.push(Buffer.byteLength(data, 'utf8')); + this.send(args); + this.send([data]) + } else { + this.send(args); + } + }; +}; /** * Response handler */ -function Response(success_code) { - this.success_code = success_code; +function Response(success_code, receives_yaml = false) { + this.success_code = success_code; + this.receives_yaml = receives_yaml; }; -Response.prototype.reset = function() { - this.complete = false; - this.success = false; - this.args = undefined; - this.header = undefined; - this.body = undefined; - this.consumed_data_length = 0; +Response.prototype.reset = function () { + this.complete = false; + this.success = false; + this.args = undefined; + this.header = undefined; + this.body = undefined; + this.consumed_data_length = 0; }; Response.prototype.CODES_REQUIRING_BODY = { - 'RESERVED' : true + 'RESERVED': true }; -Response.prototype.parse = function(data) { - this.reset(); - - var i = data.indexOf('\r\n'); - - if (i < 0) { - return; //response is not yet complete - } - - this.header = data.substr(0, i); - this.args = this.header.split(' '); - - var code = this.args[0]; - - if (code === this.success_code) { - this.args.shift(); - //don't include the code in the success args, but do in the err args - this.success = true; - } - - if ((this.CODES_REQUIRING_BODY[code])) { - this.complete = this.parseBody(data.substr(i + 2)) ? true: false; - } else { - this.complete = true; - } - - if (this.complete) { - this.consumed_data_length = this.header.length + 2; - - if (this.body) { - this.consumed_data_length += this.body.length + 2; - } - } +Response.prototype.parse = function (data) { + this.reset(); + + var i = data.indexOf('\r\n'); + + if (i < 0) { + return; //response is not yet complete + } + + this.header = data.substr(0, i); + this.args = this.header.split(' '); + + var code = this.args[0]; + + if (code === this.success_code) { + this.args.shift(); + //don't include the code in the success args, but do in the err args + this.success = true; + } + + if (this.receives_yaml) { + this.complete = !!this.parseYaml(data.substr(i + 2)); + } else if ((this.CODES_REQUIRING_BODY[code])) { + this.complete = !!this.parseBody(data.substr(i + 2)); + } else { + this.complete = true; + } + + + if (this.complete) { + this.consumed_data_length = this.header.length + 2; + + if (this.body) { + this.consumed_data_length += this.body.length + 2; + } + if (this.yaml_data) { + this.consumed_data_length += this.yaml_data_length + 2; + } + } +}; + +Response.prototype.parseYaml = function (data) { + if (data === "") { + this.yaml_data = null; + return true + } + var lines = data.split('\n'); + if (!lines || (!!lines && lines.length <= 0)) { + this.yaml_data = null; + return true; + } + var last_arg = this.args[this.args.length - 1]; + var expected_bodylength_inbytes = parseInt(last_arg, 10); + var yaml = {}; + lines.forEach(line => { + var lineParts = line.split(':'); + if (lineParts.length === 2) { + var value = lineParts[1].trim(); + var asInt = parseInt(value); + if (!isNaN(asInt)) { + value = asInt; + } + yaml[lineParts[0]] = value; + } + }); + this.body = null; + this.args.pop(); + this.yaml_data = yaml; + this.yaml_data_length = expected_bodylength_inbytes; + return true; }; -Response.prototype.parseBody = function(data) { - var last_arg = this.args[this.args.length - 1]; - - var expected_bodylength_inbytes = parseInt(last_arg, 10); - var available_data_inbytes = Buffer.byteLength(data, 'utf8') - - if (available_data_inbytes >= (expected_bodylength_inbytes + 2)) { - this.body = (new Buffer(data)).toString('utf8', 0, expected_bodylength_inbytes); - - //response args : remove the length and add the data - this.args.pop(); - this.args.push(this.body); - - return true; - } +Response.prototype.parseBody = function (data) { + var last_arg = this.args[this.args.length - 1]; + + var expected_bodylength_inbytes = parseInt(last_arg, 10); + var available_data_inbytes = Buffer.byteLength(data, 'utf8') + + if (available_data_inbytes >= (expected_bodylength_inbytes + 2)) { + this.body = (new Buffer(data)).toString('utf8', 0, expected_bodylength_inbytes); + + //response args : remove the length and add the data + this.args.pop(); + this.args.push(this.body); + + return true; + } }; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b208ff3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,261 @@ +{ + "name": "beanstalkc", + "version": "0.0.4", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/chai": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", + "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "dev": true + }, + "@types/mocha": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", + "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "commander": { + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 1ec33c8..a4aac07 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,21 @@ -{ - "name": "beanstalkc", - "version": "0.0.3", +{ + "name": "node-beanstalkd-client", + "version": "1.0.0", "description": "Easy to use beanstalkd client library for node.js", - "author": "Jayy Vis ", - "dependencies": {}, + "author": "Luiz Eduardo Carneiro ", + "dependencies": {}, + "scripts": { + "test": "mocha --exit" + }, "repository": { - "type" : "git", - "url" : "http://github.com/jayyvis/node-beanstalkc.git" + "type": "git", + "url": "http://github.com/lscarneiro/node-beanstalkc.git" }, - "license": "MIT" + "license": "MIT", + "devDependencies": { + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.5", + "chai": "^4.2.0", + "mocha": "^5.2.0" + } } - diff --git a/ref/beanstalk_client.js b/ref/beanstalk_client.js index cf07fa5..c947fea 100644 --- a/ref/beanstalk_client.js +++ b/ref/beanstalk_client.js @@ -1,166 +1,167 @@ -(function(){ - var Client, Connection, ResponseHandler, make_command_method, net; - var __slice = Array.prototype.slice, __bind = function(func, obj, args) { - return function() { - return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments); - }; - }; - net = require('net'); - Client = { - DEFAULT_ADDR: '127.0.0.1', - DEFAULT_PORT: 11300, - LOWEST_PRIORITY: 4294967295, - connect: function(server, callback) { - var _a, addr, port, stream; - if (server) { - _a = server.split(':'); - addr = _a[0]; - port = _a[1]; +(function () { + var Client, Connection, ResponseHandler, make_command_method, net; + var __slice = Array.prototype.slice, __bind = function (func, obj, args) { + return function () { + return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments); + }; + }; + net = require('net'); + Client = { + DEFAULT_ADDR: '127.0.0.1', + DEFAULT_PORT: 11300, + LOWEST_PRIORITY: 4294967295, + connect: function (server, callback) { + var _a, addr, port, stream; + if (server) { + _a = server.split(':'); + addr = _a[0]; + port = _a[1]; + } + !addr ? (addr = Client.DEFAULT_ADDR) : null; + !port ? (port = Client.DEFAULT_PORT) : null; + stream = net.createConnection(port, addr); + stream.on('connect', function () { + return callback(false, new Connection(stream)); + }); + stream.on('error', function (err) { + return callback(err); + }); + return stream.on('close', function (has_error) { + }); + //todo } - !addr ? (addr = Client.DEFAULT_ADDR) : null; - !port ? (port = Client.DEFAULT_PORT) : null; - stream = net.createConnection(port, addr); - stream.on('connect', function() { - return callback(false, new Connection(stream)); - }); - stream.on('error', function(err) { - return callback(err); - }); - return stream.on('close', function(has_error) { }); - //todo - } - }; - make_command_method = function(command_name, expected_response, sends_data) { - return function() { - var args, data; - var _a = arguments.length, _b = _a >= 2, callback = arguments[_b ? _a - 1 : 0]; - args = __slice.call(arguments, 0, _a - 1); - args.unshift(command_name); - if (sends_data) { - data = args.pop(); - args.push(data.length); - } - this.send.apply(this, args); - data ? this.send(data) : null; - return this.handlers.push([new ResponseHandler(expected_response), callback]); - }; - }; - Connection = function(stream) { - this.stream = stream; - this.buffer = ''; - this.handlers = []; - this.stream.on('data', __bind(function(data) { - this.buffer += data; - return this.try_handling_response(); + }; + make_command_method = function (command_name, expected_response, sends_data) { + return function () { + var args, data; + var _a = arguments.length, _b = _a >= 2, callback = arguments[_b ? _a - 1 : 0]; + args = __slice.call(arguments, 0, _a - 1); + args.unshift(command_name); + if (sends_data) { + data = args.pop(); + args.push(data.length); + } + this.send.apply(this, args); + data ? this.send(data) : null; + return this.handlers.push([new ResponseHandler(expected_response), callback]); + }; + }; + Connection = function (stream) { + this.stream = stream; + this.buffer = ''; + this.handlers = []; + this.stream.on('data', __bind(function (data) { + this.buffer += data; + return this.try_handling_response(); }, this)); - return this; - }; - Connection.prototype.end = function() { - return this.stream.end(); - }; - Connection.prototype.try_handling_response = function() { - var _a, callback, handler; - _a = this.handlers[0]; - handler = _a[0]; - callback = _a[1]; - if ((typeof handler !== "undefined" && handler !== null)) { - handler.handle(this.buffer); - if (handler.complete) { - this.finished_handling_response(); - if (handler.success) { - return callback.call.apply(callback, [null, false].concat(handler.args)); - } else { - return callback.call(null, handler.args[0]); - } - } else { - return handler.reset(); + return this; + }; + Connection.prototype.end = function () { + return this.stream.end(); + }; + Connection.prototype.try_handling_response = function () { + var _a, callback, handler; + _a = this.handlers[0]; + handler = _a[0]; + callback = _a[1]; + if ((typeof handler !== "undefined" && handler !== null)) { + handler.handle(this.buffer); + if (handler.complete) { + this.finished_handling_response(); + if (handler.success) { + return callback.call.apply(callback, [null, false].concat(handler.args)); + } else { + return callback.call(null, handler.args[0]); + } + } else { + return handler.reset(); + } } - } - }; - Connection.prototype.finished_handling_response = function() { - var hp; - this.buffer = ''; - hp = this.handlers.shift(); - hp = null; - return hp; - }; - Connection.prototype.send = function() { - var args; - var _a = arguments.length, _b = _a >= 1; - args = __slice.call(arguments, 0, _a - 0); - return this.stream.write(args.join(' ') + "\r\n"); - }; - //submitting jobs - Connection.prototype.use = make_command_method('use', 'USING'); - Connection.prototype.put = make_command_method('put', 'INSERTED', true); - //handling jobs - Connection.prototype.watch = make_command_method('watch', 'WATCHING'); - Connection.prototype.ignore = make_command_method('ignore', 'WATCHING'); - Connection.prototype.reserve = make_command_method('reserve', 'RESERVED'); - Connection.prototype.reserve_with_timeout = make_command_method('reserve-with-timeout', 'RESERVED'); - Connection.prototype.destroy = make_command_method('delete', 'DELETED'); - Connection.prototype.release = make_command_method('release', 'RELEASED'); - Connection.prototype.bury = make_command_method('bury', 'BURIED'); - Connection.prototype.touch = make_command_method('touch', 'TOUCHED'); - //other stuff - Connection.prototype.peek = make_command_method('peek', 'FOUND'); - Connection.prototype.peek_ready = make_command_method('peek-ready', 'FOUND'); - Connection.prototype.peek_delayed = make_command_method('peek-delayed', 'FOUND'); - Connection.prototype.peek_buried = make_command_method('peek-buried', 'FOUND'); - Connection.prototype.kick = make_command_method('kick', 'KICKED'); - Connection.prototype.stats_job = make_command_method('stats-job', 'OK'); - Connection.prototype.stats_tube = make_command_method('stats-tube', 'OK'); - Connection.prototype.stats = make_command_method('stats', 'OK'); + }; + Connection.prototype.finished_handling_response = function () { + var hp; + this.buffer = ''; + hp = this.handlers.shift(); + hp = null; + return hp; + }; + Connection.prototype.send = function () { + var args; + var _a = arguments.length, _b = _a >= 1; + args = __slice.call(arguments, 0, _a - 0); + return this.stream.write(args.join(' ') + "\r\n"); + }; + //submitting jobs + Connection.prototype.use = make_command_method('use', 'USING'); + Connection.prototype.put = make_command_method('put', 'INSERTED', true); + //handling jobs + Connection.prototype.watch = make_command_method('watch', 'WATCHING'); + Connection.prototype.ignore = make_command_method('ignore', 'WATCHING'); + Connection.prototype.reserve = make_command_method('reserve', 'RESERVED'); + Connection.prototype.reserve_with_timeout = make_command_method('reserve-with-timeout', 'RESERVED'); + Connection.prototype.destroy = make_command_method('delete', 'DELETED'); + Connection.prototype.release = make_command_method('release', 'RELEASED'); + Connection.prototype.bury = make_command_method('bury', 'BURIED'); + Connection.prototype.touch = make_command_method('touch', 'TOUCHED'); + //other stuff + Connection.prototype.peek = make_command_method('peek', 'FOUND'); + Connection.prototype.peek_ready = make_command_method('peek-ready', 'FOUND'); + Connection.prototype.peek_delayed = make_command_method('peek-delayed', 'FOUND'); + Connection.prototype.peek_buried = make_command_method('peek-buried', 'FOUND'); + Connection.prototype.kick = make_command_method('kick', 'KICKED'); + Connection.prototype.stats_job = make_command_method('stats-job', 'OK'); + Connection.prototype.stats_tube = make_command_method('stats-tube', 'OK'); + Connection.prototype.stats = make_command_method('stats', 'OK'); - ResponseHandler = function(success_code) { - this.success_code = success_code; - return this; - }; - ResponseHandler.prototype.reset = function() { - this.complete = false; - this.success = false; - this.args = undefined; - this.header = undefined; - this.body = undefined; - return this.body; - }; - ResponseHandler.prototype.CODES_REQUIRING_BODY = { - 'RESERVED': true - }; - ResponseHandler.prototype.handle = function(data) { - var code, i; - i = data.indexOf("\r\n"); - if (i >= 0) { - this.header = data.substr(0, i); - this.body = data.substr(i + 2); - this.args = this.header.split(' '); - code = this.args[0]; - if (code === this.success_code) { - this.args.shift(); - //don't include the code in the success args, but do in the err args - this.success = true; - } - if ((this.CODES_REQUIRING_BODY[code])) { - return this.parse_body(); - } else { - this.complete = true; - return this.complete; + ResponseHandler = function (success_code) { + this.success_code = success_code; + return this; + }; + ResponseHandler.prototype.reset = function () { + this.complete = false; + this.success = false; + this.args = undefined; + this.header = undefined; + this.body = undefined; + return this.body; + }; + ResponseHandler.prototype.CODES_REQUIRING_BODY = { + 'RESERVED': true + }; + ResponseHandler.prototype.handle = function (data) { + var code, i; + i = data.indexOf("\r\n"); + if (i >= 0) { + this.header = data.substr(0, i); + this.body = data.substr(i + 2); + this.args = this.header.split(' '); + code = this.args[0]; + if (code === this.success_code) { + this.args.shift(); + //don't include the code in the success args, but do in the err args + this.success = true; + } + if ((this.CODES_REQUIRING_BODY[code])) { + return this.parse_body(); + } else { + this.complete = true; + return this.complete; + } } - } - }; - ResponseHandler.prototype.parse_body = function() { - var _a, body_length; - if ((typeof (_a = this.body) !== "undefined" && _a !== null)) { - body_length = parseInt(this.args[this.args.length - 1], 10); - if (this.body.length === (body_length + 2)) { - this.args.pop(); - //removed the length and add the data - this.args.push(this.body.substr(0, this.body.length - 2)); - this.complete = true; - return this.complete; + }; + ResponseHandler.prototype.parse_body = function () { + var _a, body_length; + if ((typeof (_a = this.body) !== "undefined" && _a !== null)) { + body_length = parseInt(this.args[this.args.length - 1], 10); + if (this.body.length === (body_length + 2)) { + this.args.pop(); + //removed the length and add the data + this.args.push(this.body.substr(0, this.body.length - 2)); + this.complete = true; + return this.complete; + } } - } - }; + }; - exports.Client = Client; + exports.Client = Client; })(); diff --git a/test/test.js b/test/test.js index 7a6add8..a9fa8f8 100644 --- a/test/test.js +++ b/test/test.js @@ -1,111 +1,151 @@ -var assert = require('assert'); -var beanstalkc = require('../index'); +// const assert = require('assert'); +const beanstalkc = require('../index'); +const mocha = require('mocha'); +const describe = mocha.describe; +const chai = require('chai'); +const should = chai.should(); -var connection; +let connection; -var job_data = { - "type" : "test" +const job_data = { + "type": "test" }; locals = {}; +describe('beanstalkc:', function () { + before('connect()', function (done) { + beanstalkc.connect('127.0.0.1:11300', function (err, conn) { + should.not.exist(err); + conn.should.be.not.null; + connection = conn; + done(); + }); + }); -describe('beanstalkc:', function() { - before('connect()', function(done) { - beanstalkc.connect('127.0.0.1:4242', function(err, conn) { - assert(!err, 'err:'+err); - assert(conn); - connection = conn; - done(); - }); - }); - - describe('put()', function() { - it('puts a job into the tube', function(done) { - connection.put(0, 0, 1, JSON.stringify(job_data), function(err, job_id) { - assert(!err, 'err:'+err); - assert(job_id); - done(); - }); - }); - }); - - describe('reserve()', function() { - it('gets a ready job from the tube', function(done) { - connection.reserve(function(err, job_id, job_json) { - assert(!err, 'err:'+err); - assert(job_id); - assert.equal(job_json, JSON.stringify(job_data)); - - locals.job_id = job_id; - - done(); - }); - }); - }) - - describe('destroy()', function() { - it('destroys given job from the tube', function(done) { - connection.destroy(locals.job_id, function(err) { - assert(!err, 'err:'+err); - done(); - }); - }); - }); - - describe('utf8 jobs:', function() { - it('puts utf8 string', function(done) { - connection.put(0, 0, 1, 'latin À', function(err, job_id) { - assert(!err, 'err:'+err); - assert(job_id); - done(); - }); - }); - - it('gets utf8 string', function(done) { - connection.reserve(function(err, job_id, job_string) { - assert(!err, 'err:'+err); - assert(job_id); - assert.equal(job_string, 'latin À'); - - connection.destroy(job_id, function(err) { - assert(!err, 'err:'+err); - done(); - }); - }); - }); - }) - - describe('parallel jobs:', function() { - it('puts 3 jobs parallely', function(done) { - var count = 0; - - connection.put(0, 0, 1, 'job1', function(err, job_id) { - assert(!err, 'err:'+err); - assert(job_id); - - count += 1; - if (count === 3) done(); - }); - - connection.put(0, 0, 1, 'job2', function(err, job_id) { - assert(!err, 'err:'+err); - assert(job_id); - - count += 1; - if (count === 3) done(); - }); - - connection.put(0, 0, 1, 'job3', function(err, job_id) { - assert(!err, 'err:'+err); - assert(job_id); - - count += 1; - if (count === 3) done(); - }); - }); - }) - -}) + describe('put()', function () { + it('puts a job into the tube', function (done) { + connection.put(0, 0, 1, JSON.stringify(job_data), function (err, job_id) { + err.should.be.false; + should.exist(job_id); + job_id.should.be.a('string'); + done(); + }); + }); + }); + + describe('reserve()', function () { + it('gets a ready job from the tube', function (done) { + connection.reserve(function (err, job_id, job_json) { + err.should.be.false; + job_id.should.be.a('string'); + job_json.should.be.equal(JSON.stringify(job_data)); + + locals.job_id = job_id; + + done(); + }); + }); + }); + + describe('destroy()', function () { + it('destroys given job from the tube', function (done) { + connection.destroy(locals.job_id, function (err) { + err.should.be.false; + done(); + }); + }); + }); + + describe('utf8 jobs:', function () { + it('puts utf8 string', function (done) { + connection.put(0, 0, 1, 'latin À', function (err, job_id) { + err.should.be.false; + job_id.should.be.a('string'); + done(); + }); + }); + + it('gets utf8 string', function (done) { + connection.reserve(function (err, job_id, job_string) { + err.should.be.false; + job_id.should.be.a('string'); + job_string.should.be.equal('latin À'); + + connection.destroy(job_id, function (err) { + err.should.be.false; + done(); + }); + }); + }); + }); + + describe('parallel jobs:', function () { + it('puts 3 jobs parallely', function (done) { + let count = 0; + + connection.put(0, 0, 1, 'job1', function (err, job_id) { + err.should.be.false; + job_id.should.be.a('string'); + + count += 1; + if (count === 3) done(); + }); + + connection.put(0, 0, 1, 'job2', function (err, job_id) { + err.should.be.false; + job_id.should.be.a('string'); + + count += 1; + if (count === 3) done(); + }); + + connection.put(0, 0, 1, 'job3', function (err, job_id) { + err.should.be.false; + job_id.should.be.a('string'); + + count += 1; + if (count === 3) done(); + }); + }); + }); + + describe('stats-tube', function () { + it('gets tube statistics', function (done) { + connection.stats_tube('default', (err, result) => { + err.should.be.false; + result.should.have.property('name'); + result.should.have.property('current-jobs-ready'); + result.name.should.be.equal('default'); + done(); + }) + }) + }); + + after('clean jobs',function (done) { + function cleanTube(end) { + connection.stats_tube('default', (err, result) => { + if (result['current-jobs-ready'] > 0) { + connection.reserve(function (err, job_id, job_json) { + if (!err) { + if (job_id) { + connection.destroy(job_id, function (err) { + cleanTube(end); + }); + } else { + end(); + } + } else { + end(); + } + }); + } else { + end(); + } + }) + } + cleanTube(done); + }); +});