Compare commits

..

No commits in common. "5149cd8f9933a70663bf55d8d8bbf632786cef17" and "bd76402586f1b5117ada9857a9e437727562d55a" have entirely different histories.

5 changed files with 17 additions and 117 deletions

View File

@ -148,7 +148,7 @@ export class IndexTransaction {
'missing condition for conditional put' 'missing condition for conditional put'
); );
} }
if (typeof condition.notExists !== 'string' && typeof condition.exists !== 'string') { if (typeof condition.notExists !== 'string') {
throw propError( throw propError(
'unsupportedConditionalOperation', 'unsupportedConditionalOperation',
'missing key or supported condition' 'missing key or supported condition'

View File

@ -90,6 +90,12 @@ export class ProbeServer extends httpServer {
return; return;
} }
this._handlers.get(req.url!)!(res, log); const probeResponse = this._handlers.get(req.url!)!(res, log);
if (probeResponse !== undefined && probeResponse !== '') {
// Return an internal error with the response
errors.InternalError
.customizeDescription(probeResponse)
.writeResponse(res);
}
} }
} }

View File

@ -3,7 +3,7 @@
"engines": { "engines": {
"node": ">=16" "node": ">=16"
}, },
"version": "7.10.46-2", "version": "7.10.46",
"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": {

View File

@ -53,21 +53,12 @@ function checkKeyNotExistsInDB(db, key, cb) {
return cb(err); return cb(err);
} }
if (value) { if (value) {
return cb(errors.EntityAlreadyExists); return cb(errors.PreconditionFailed);
} }
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();
@ -79,9 +70,6 @@ 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'));
} }
@ -437,7 +425,7 @@ describe('IndexTransaction', () => {
value: value3, value: value3,
}); });
return transaction.commit(err => { return transaction.commit(err => {
if (!err || !err.is.EntityAlreadyExists) { if (!err || !err.is.PreconditionFailed) {
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([
@ -469,87 +457,11 @@ 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({ like: key1 }); transaction.addCondition({ exists: 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();
});
});
});
}); });

View File

@ -89,34 +89,16 @@ describe('network.probe.ProbeServer', () => {
}); });
it('500 response on bad probe', done => { it('500 response on bad probe', done => {
const failedMessage = 'failed_message'; server.addHandler('/check', () => 'check failed');
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(body, failedMessage); assert.strictEqual(
done(); body,
}); '{"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();
}); });
}); });