Compare commits
6 Commits
bd76402586
...
5149cd8f99
Author | SHA1 | Date |
---|---|---|
Anurag Mittal | 5149cd8f99 | |
Anurag Mittal | 71243b6859 | |
Anurag Mittal | 7a9fe38957 | |
Anurag Mittal | eff398ba0f | |
Nicolas Humbert | da3aecdbe1 | |
Nicolas Humbert | 1042394f9a |
|
@ -148,7 +148,7 @@ export class IndexTransaction {
|
||||||
'missing condition for conditional put'
|
'missing condition for conditional put'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (typeof condition.notExists !== 'string') {
|
if (typeof condition.notExists !== 'string' && typeof condition.exists !== 'string') {
|
||||||
throw propError(
|
throw propError(
|
||||||
'unsupportedConditionalOperation',
|
'unsupportedConditionalOperation',
|
||||||
'missing key or supported condition'
|
'missing key or supported condition'
|
||||||
|
|
|
@ -90,12 +90,6 @@ export class ProbeServer extends httpServer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const probeResponse = this._handlers.get(req.url!)!(res, log);
|
this._handlers.get(req.url!)!(res, log);
|
||||||
if (probeResponse !== undefined && probeResponse !== '') {
|
|
||||||
// Return an internal error with the response
|
|
||||||
errors.InternalError
|
|
||||||
.customizeDescription(probeResponse)
|
|
||||||
.writeResponse(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
},
|
},
|
||||||
"version": "7.10.46",
|
"version": "7.10.46-2",
|
||||||
"description": "Common utilities for the S3 project components",
|
"description": "Common utilities for the S3 project components",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -53,12 +53,21 @@ function checkKeyNotExistsInDB(db, key, cb) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
return cb(errors.PreconditionFailed);
|
return cb(errors.EntityAlreadyExists);
|
||||||
}
|
}
|
||||||
return cb();
|
return cb();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkKeyExistsInDB(db, key, callback) {
|
||||||
|
return db.get(key, err => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err.notFound ? errors.NoSuchEntity : err);
|
||||||
|
}
|
||||||
|
return callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class ConditionalLevelDB {
|
class ConditionalLevelDB {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.db = createDb();
|
this.db = createDb();
|
||||||
|
@ -70,6 +79,9 @@ class ConditionalLevelDB {
|
||||||
case ('notExists' in cond):
|
case ('notExists' in cond):
|
||||||
checkKeyNotExistsInDB(this.db, cond.notExists, asyncCallback);
|
checkKeyNotExistsInDB(this.db, cond.notExists, asyncCallback);
|
||||||
break;
|
break;
|
||||||
|
case ('exists' in cond):
|
||||||
|
checkKeyExistsInDB(this.db, cond.exists, asyncCallback);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
asyncCallback(new Error('unsupported conditional operation'));
|
asyncCallback(new Error('unsupported conditional operation'));
|
||||||
}
|
}
|
||||||
|
@ -425,7 +437,7 @@ describe('IndexTransaction', () => {
|
||||||
value: value3,
|
value: value3,
|
||||||
});
|
});
|
||||||
return transaction.commit(err => {
|
return transaction.commit(err => {
|
||||||
if (!err || !err.is.PreconditionFailed) {
|
if (!err || !err.is.EntityAlreadyExists) {
|
||||||
return done(new Error('should not be able to conditional put for duplicate key'));
|
return done(new Error('should not be able to conditional put for duplicate key'));
|
||||||
}
|
}
|
||||||
return async.parallel([
|
return async.parallel([
|
||||||
|
@ -457,11 +469,87 @@ describe('IndexTransaction', () => {
|
||||||
it('should not allow batch operation with unsupported condition', done => {
|
it('should not allow batch operation with unsupported condition', done => {
|
||||||
const transaction = new IndexTransaction();
|
const transaction = new IndexTransaction();
|
||||||
try {
|
try {
|
||||||
transaction.addCondition({ exists: key1 });
|
transaction.addCondition({ like: key1 });
|
||||||
done(new Error('should fail for unsupported condition, currently supported - notExists'));
|
done(new Error('should fail for unsupported condition, currently supported - notExists'));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
assert.strictEqual(err.unsupportedConditionalOperation, true);
|
assert.strictEqual(err.unsupportedConditionalOperation, true);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should allow batch operation with key specified in exists condition is present in db', done => {
|
||||||
|
const db = new ConditionalLevelDB();
|
||||||
|
const { client } = db;
|
||||||
|
let transaction = new IndexTransaction(db);
|
||||||
|
transaction.put(key1, value1);
|
||||||
|
return async.series([
|
||||||
|
next => transaction.commit(next),
|
||||||
|
next => client.get(key1, next),
|
||||||
|
], err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
// create new transaction as previous transaction is already committed
|
||||||
|
transaction = new IndexTransaction(db);
|
||||||
|
transaction.addCondition({ exists: key1 });
|
||||||
|
transaction.push({
|
||||||
|
type: 'put',
|
||||||
|
key: key1,
|
||||||
|
value: value2,
|
||||||
|
});
|
||||||
|
return async.series([
|
||||||
|
next => transaction.commit(next),
|
||||||
|
next => client.get(key1, next),
|
||||||
|
], (err, res) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.strictEqual(res[1], value2);
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow batch operation with key specified in exists condition is not in db', done => {
|
||||||
|
const db = new ConditionalLevelDB();
|
||||||
|
const { client } = db;
|
||||||
|
const transaction = new IndexTransaction(db);
|
||||||
|
transaction.addCondition({ exists: key1 });
|
||||||
|
transaction.push({
|
||||||
|
type: 'put',
|
||||||
|
key: key1,
|
||||||
|
value: value1,
|
||||||
|
});
|
||||||
|
return transaction.commit(err => {
|
||||||
|
assert.strictEqual(err && err.NoSuchEntity, true);
|
||||||
|
return checkKeyNotExistsInDB(client, key1, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle batch operations with multiple conditions correctly', done => {
|
||||||
|
const db = new ConditionalLevelDB();
|
||||||
|
const { client } = db;
|
||||||
|
let transaction = new IndexTransaction(db);
|
||||||
|
transaction.put(key1, value1);
|
||||||
|
return async.series([
|
||||||
|
next => transaction.commit(next),
|
||||||
|
next => client.get(key1, next),
|
||||||
|
], err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
// create new transaction as previous transaction is already committed
|
||||||
|
transaction = new IndexTransaction(db);
|
||||||
|
transaction.addCondition({ exists: key1 });
|
||||||
|
transaction.addCondition({ notExists: key2 });
|
||||||
|
transaction.push({
|
||||||
|
type: 'put',
|
||||||
|
key: key1,
|
||||||
|
value: value2,
|
||||||
|
});
|
||||||
|
|
||||||
|
return async.series([
|
||||||
|
next => transaction.commit(next),
|
||||||
|
next => client.get(key1, next),
|
||||||
|
], (err, res) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.strictEqual(res[1], value2);
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,16 +89,34 @@ describe('network.probe.ProbeServer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('500 response on bad probe', done => {
|
it('500 response on bad probe', done => {
|
||||||
server.addHandler('/check', () => 'check failed');
|
const failedMessage = 'failed_message';
|
||||||
|
server.addHandler('/check', res => {
|
||||||
|
res.writeHead(500);
|
||||||
|
res.end(failedMessage);
|
||||||
|
});
|
||||||
makeRequest('GET', '/check', (err, res) => {
|
makeRequest('GET', '/check', (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.strictEqual(res.statusCode, 500);
|
assert.strictEqual(res.statusCode, 500);
|
||||||
res.setEncoding('utf8');
|
res.setEncoding('utf8');
|
||||||
res.on('data', body => {
|
res.on('data', body => {
|
||||||
assert.strictEqual(
|
assert.strictEqual(body, failedMessage);
|
||||||
body,
|
done();
|
||||||
'{"errorType":"InternalError","errorMessage":"check failed"}',
|
});
|
||||||
);
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('500 response on bad async probe', done => {
|
||||||
|
const failedMessage = 'failed_message';
|
||||||
|
server.addHandler('/check', async res => {
|
||||||
|
res.writeHead(500);
|
||||||
|
res.end(failedMessage);
|
||||||
|
});
|
||||||
|
makeRequest('GET', '/check', (err, res) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.strictEqual(res.statusCode, 500);
|
||||||
|
res.setEncoding('utf8');
|
||||||
|
res.on('data', body => {
|
||||||
|
assert.strictEqual(body, failedMessage);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue