2016-06-29 20:22:23 +08:00
|
|
|
require('../helper');
|
|
|
|
|
|
|
|
var assert = require('../support/assert');
|
2016-07-22 23:05:01 +08:00
|
|
|
var redisUtils = require('../support/redis_utils');
|
2016-06-29 20:22:23 +08:00
|
|
|
var app = require(global.settings.app_root + '/app/app')();
|
|
|
|
var querystring = require('qs');
|
2016-07-07 20:14:46 +08:00
|
|
|
var redisConfig = {
|
2016-06-29 20:22:23 +08:00
|
|
|
host: global.settings.redis_host,
|
|
|
|
port: global.settings.redis_port,
|
|
|
|
max: global.settings.redisPool,
|
|
|
|
idleTimeoutMillis: global.settings.redisIdleTimeoutMillis,
|
|
|
|
reapIntervalMillis: global.settings.redisReapIntervalMillis
|
2016-07-07 20:14:46 +08:00
|
|
|
};
|
|
|
|
var metadataBackend = require('cartodb-redis')(redisConfig);
|
2016-06-29 20:22:23 +08:00
|
|
|
var batchFactory = require('../../batch');
|
|
|
|
var jobStatus = require('../../batch/job_status');
|
|
|
|
|
2016-06-30 23:41:02 +08:00
|
|
|
describe('Batch API callback templates', function () {
|
2016-06-29 20:22:23 +08:00
|
|
|
|
|
|
|
function createJob(jobDefinition, callback) {
|
|
|
|
assert.response(app, {
|
|
|
|
url: '/api/v2/sql/job?api_key=1234',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
|
|
host: 'vizzuality.cartodb.com'
|
|
|
|
},
|
|
|
|
method: 'POST',
|
|
|
|
data: querystring.stringify(jobDefinition)
|
|
|
|
}, {
|
|
|
|
status: 201
|
|
|
|
}, function (res, err) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
return callback(null, JSON.parse(res.body));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function getJobStatus(jobId, callback) {
|
|
|
|
assert.response(app, {
|
|
|
|
url: '/api/v2/sql/job/' + jobId + '?api_key=1234&',
|
|
|
|
headers: {
|
|
|
|
host: 'vizzuality.cartodb.com'
|
|
|
|
},
|
|
|
|
method: 'GET'
|
|
|
|
}, {
|
|
|
|
status: 200
|
|
|
|
}, function (res, err) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
return callback(null, JSON.parse(res.body));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function getQueryResult(query, callback) {
|
|
|
|
assert.response(app, {
|
|
|
|
url: '/api/v2/sql?' + querystring.stringify({q: query, api_key: 1234}),
|
|
|
|
headers: {
|
|
|
|
host: 'vizzuality.cartodb.com'
|
|
|
|
},
|
|
|
|
method: 'GET'
|
|
|
|
}, {
|
|
|
|
status: 200
|
|
|
|
}, function (res, err) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
return callback(null, JSON.parse(res.body));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function validateExpectedResponse(actual, expected) {
|
|
|
|
actual.query.forEach(function(actualQuery, index) {
|
|
|
|
var expectedQuery = expected.query[index];
|
|
|
|
assert.ok(expectedQuery);
|
|
|
|
Object.keys(expectedQuery).forEach(function(expectedKey) {
|
2016-07-01 00:31:58 +08:00
|
|
|
assert.equal(
|
|
|
|
actualQuery[expectedKey],
|
|
|
|
expectedQuery[expectedKey],
|
|
|
|
'Expected value for key "' + expectedKey + '" does not match: ' + actualQuery[expectedKey] + ' ==' +
|
2016-07-01 01:14:21 +08:00
|
|
|
expectedQuery[expectedKey] + ' at query index=' + index + '. Full response: ' +
|
|
|
|
JSON.stringify(actual, null, 4)
|
2016-07-01 00:31:58 +08:00
|
|
|
);
|
2016-06-29 20:22:23 +08:00
|
|
|
});
|
|
|
|
var propsToCheckDate = ['started_at', 'ended_at'];
|
|
|
|
propsToCheckDate.forEach(function(propToCheckDate) {
|
|
|
|
if (actualQuery.hasOwnProperty(propToCheckDate)) {
|
|
|
|
assert.ok(new Date(actualQuery[propToCheckDate]));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(actual.onsuccess, expected.onsuccess);
|
|
|
|
assert.equal(actual.onerror, expected.onerror);
|
|
|
|
}
|
|
|
|
|
2016-07-07 20:14:46 +08:00
|
|
|
var batch = batchFactory(metadataBackend, redisConfig);
|
2016-06-29 20:22:23 +08:00
|
|
|
|
2016-07-22 20:27:18 +08:00
|
|
|
before(function (done) {
|
2016-06-29 20:22:23 +08:00
|
|
|
batch.start();
|
2016-07-22 20:27:18 +08:00
|
|
|
batch.on('ready', done);
|
2016-06-29 20:22:23 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
after(function (done) {
|
|
|
|
batch.stop();
|
2016-07-22 23:05:01 +08:00
|
|
|
redisUtils.clean('batch:*', done);
|
2016-06-29 20:22:23 +08:00
|
|
|
});
|
|
|
|
|
2016-07-22 20:41:26 +08:00
|
|
|
describe.skip('should use templates for error_message and job_id onerror callback', function () {
|
2016-06-29 20:22:23 +08:00
|
|
|
var jobResponse;
|
|
|
|
before(function(done) {
|
2016-07-01 01:40:36 +08:00
|
|
|
getQueryResult('create table test_batch_errors (job_id text, error_message text)', function(err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
2016-06-29 20:22:23 +08:00
|
|
|
}
|
2016-07-01 01:40:36 +08:00
|
|
|
createJob({
|
|
|
|
"query": {
|
|
|
|
"query": [
|
|
|
|
{
|
|
|
|
"query": "SELECT * FROM invalid_table",
|
2016-07-01 01:49:34 +08:00
|
|
|
"onerror": "INSERT INTO test_batch_errors " +
|
|
|
|
"values ('<%= job_id %>', '<%= error_message %>')"
|
2016-07-01 01:40:36 +08:00
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}, function(err, job) {
|
|
|
|
jobResponse = job;
|
|
|
|
return done(err);
|
|
|
|
});
|
2016-06-29 20:22:23 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should keep the original templated query but use the error message', function (done) {
|
2016-07-01 01:12:45 +08:00
|
|
|
var expectedQuery = {
|
|
|
|
query: [
|
|
|
|
{
|
|
|
|
"query": "SELECT * FROM invalid_table",
|
|
|
|
"onerror": "INSERT INTO test_batch_errors values ('<%= job_id %>', '<%= error_message %>')",
|
|
|
|
status: 'failed',
|
|
|
|
fallback_status: 'done'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
2016-06-29 20:22:23 +08:00
|
|
|
var interval = setInterval(function () {
|
|
|
|
getJobStatus(jobResponse.job_id, function(err, job) {
|
|
|
|
if (job.status === jobStatus.FAILED) {
|
|
|
|
clearInterval(interval);
|
2016-07-01 01:12:45 +08:00
|
|
|
validateExpectedResponse(job.query, expectedQuery);
|
|
|
|
getQueryResult('select * from test_batch_errors', function(err, result) {
|
2016-06-29 20:22:23 +08:00
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2016-06-30 23:41:02 +08:00
|
|
|
assert.equal(result.rows[0].job_id, jobResponse.job_id);
|
2016-06-29 20:22:23 +08:00
|
|
|
assert.equal(result.rows[0].error_message, 'relation "invalid_table" does not exist');
|
2016-07-01 01:12:45 +08:00
|
|
|
getQueryResult('drop table test_batch_errors', done);
|
2016-06-29 20:22:23 +08:00
|
|
|
});
|
|
|
|
} else if (job.status === jobStatus.DONE || job.status === jobStatus.CANCELLED) {
|
|
|
|
clearInterval(interval);
|
|
|
|
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be "failed"'));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}, 50);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-30 23:41:02 +08:00
|
|
|
describe('should use template for job_id onsuccess callback', function () {
|
2016-06-29 20:22:23 +08:00
|
|
|
var jobResponse;
|
|
|
|
before(function(done) {
|
|
|
|
createJob({
|
|
|
|
"query": {
|
|
|
|
"query": [
|
|
|
|
{
|
2016-06-30 23:41:02 +08:00
|
|
|
query: "create table batch_jobs (job_id text)"
|
2016-06-29 20:22:23 +08:00
|
|
|
},
|
|
|
|
{
|
2016-06-30 23:41:02 +08:00
|
|
|
"query": "SELECT 1",
|
|
|
|
"onsuccess": "INSERT INTO batch_jobs values ('<%= job_id %>')"
|
2016-06-29 20:22:23 +08:00
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}, function(err, job) {
|
|
|
|
jobResponse = job;
|
|
|
|
return done(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-30 23:41:02 +08:00
|
|
|
it('should keep the original templated query but use the job_id', function (done) {
|
2016-06-29 20:22:23 +08:00
|
|
|
var expectedQuery = {
|
|
|
|
query: [
|
|
|
|
{
|
2016-06-30 23:41:02 +08:00
|
|
|
query: "create table batch_jobs (job_id text)",
|
2016-06-29 20:22:23 +08:00
|
|
|
status: 'done'
|
|
|
|
},
|
|
|
|
{
|
2016-06-30 23:41:02 +08:00
|
|
|
query: "SELECT 1",
|
|
|
|
onsuccess: "INSERT INTO batch_jobs values ('<%= job_id %>')",
|
|
|
|
status: 'done',
|
2016-06-29 20:22:23 +08:00
|
|
|
fallback_status: 'done'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
var interval = setInterval(function () {
|
|
|
|
getJobStatus(jobResponse.job_id, function(err, job) {
|
2016-06-30 23:41:02 +08:00
|
|
|
if (job.status === jobStatus.DONE) {
|
2016-06-29 20:22:23 +08:00
|
|
|
clearInterval(interval);
|
|
|
|
validateExpectedResponse(job.query, expectedQuery);
|
2016-06-30 23:41:02 +08:00
|
|
|
getQueryResult('select * from batch_jobs', function(err, result) {
|
2016-06-29 20:22:23 +08:00
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2016-06-30 23:41:02 +08:00
|
|
|
assert.equal(result.rows[0].job_id, jobResponse.job_id);
|
|
|
|
getQueryResult('drop table batch_jobs', done);
|
2016-06-29 20:22:23 +08:00
|
|
|
});
|
2016-06-30 23:41:02 +08:00
|
|
|
} else if (job.status === jobStatus.FAILED || job.status === jobStatus.CANCELLED) {
|
2016-06-29 20:22:23 +08:00
|
|
|
clearInterval(interval);
|
2016-06-30 23:41:02 +08:00
|
|
|
done(new Error('Job ' + job.job_id + ' is ' + job.status + ', expected to be "done"'));
|
2016-06-29 20:22:23 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}, 50);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|