Merge pull request #1694 from spurreiter/operation-hook-error
feat: call after operation hook in case of errors
This commit is contained in:
commit
acb667b73d
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
|
const debug = require('debug')('loopback:observer');
|
||||||
|
|
||||||
module.exports = ObserverMixin;
|
module.exports = ObserverMixin;
|
||||||
|
|
||||||
|
@ -232,7 +233,24 @@ ObserverMixin.notifyObserversAround = function(operation, context, fn, callback)
|
||||||
|
|
||||||
function cbForWork(err) {
|
function cbForWork(err) {
|
||||||
const args = [].slice.call(arguments, 0);
|
const args = [].slice.call(arguments, 0);
|
||||||
if (err) return callback.apply(null, args);
|
if (err) {
|
||||||
|
// call observer in case of error to hook response
|
||||||
|
context.error = err;
|
||||||
|
self.notifyObserversOf('after ' + operation + ' error', context,
|
||||||
|
function(_err, context) {
|
||||||
|
if (_err && err) {
|
||||||
|
debug(
|
||||||
|
'Operation %j failed and "after %s error" hook returned an error too. ' +
|
||||||
|
'Calling back with the hook error only.' +
|
||||||
|
'\nOriginal error: %s\nHook error: %s\n',
|
||||||
|
err.stack || err,
|
||||||
|
_err.stack || _err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
callback.call(null, _err || err, context);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Find the list of params from the callback in addition to err
|
// Find the list of params from the callback in addition to err
|
||||||
const returnedArgs = args.slice(1);
|
const returnedArgs = args.slice(1);
|
||||||
// Set up the array of results
|
// Set up the array of results
|
||||||
|
|
|
@ -325,6 +325,86 @@ describe('async observer', function() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call after operation hook on error', function(done) {
|
||||||
|
const context = {
|
||||||
|
req: {},
|
||||||
|
};
|
||||||
|
const operationError = new Error('The operation failed without result');
|
||||||
|
let callCount = 0;
|
||||||
|
|
||||||
|
function fail(context, done) {
|
||||||
|
process.nextTick(() => {
|
||||||
|
done(operationError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TestModel.observe('after execute error', function(ctx, next) {
|
||||||
|
callCount++;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
TestModel.notifyObserversAround('execute', context, fail, (err, ctx) => {
|
||||||
|
callCount.should.eql(1);
|
||||||
|
err.message.should.eql(operationError.message);
|
||||||
|
ctx.error.message.should.eql(operationError.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call after operation hook on error while overwriting error', function(done) {
|
||||||
|
const context = {
|
||||||
|
req: {},
|
||||||
|
};
|
||||||
|
const operationError = new Error('The operation failed without result');
|
||||||
|
const overwriteError = new Error('Overwriting the original error');
|
||||||
|
let callCount = 0;
|
||||||
|
|
||||||
|
function fail(context, done) {
|
||||||
|
process.nextTick(() => {
|
||||||
|
done(operationError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TestModel.observe('after execute error', function(ctx, next) {
|
||||||
|
callCount++;
|
||||||
|
next(overwriteError);
|
||||||
|
});
|
||||||
|
|
||||||
|
TestModel.notifyObserversAround('execute', context, fail, (err, ctx) => {
|
||||||
|
callCount.should.eql(1);
|
||||||
|
err.message.should.eql(overwriteError.message);
|
||||||
|
ctx.error.message.should.eql(operationError.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call after operation hook on error while allowing to change err', function(done) {
|
||||||
|
const context = {
|
||||||
|
req: {},
|
||||||
|
};
|
||||||
|
const operationError = new Error('The operation failed without result');
|
||||||
|
let callCount = 0;
|
||||||
|
|
||||||
|
function fail(context, done) {
|
||||||
|
process.nextTick(() => {
|
||||||
|
done(operationError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TestModel.observe('after execute error', function(ctx, next) {
|
||||||
|
callCount++;
|
||||||
|
const err = ctx.error;
|
||||||
|
next(err, ctx);
|
||||||
|
});
|
||||||
|
|
||||||
|
TestModel.notifyObserversAround('execute', context, fail, (err, ctx) => {
|
||||||
|
callCount.should.eql(1);
|
||||||
|
err.message.should.eql(operationError.message);
|
||||||
|
ctx.error.message.should.eql(operationError.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function pushAndNext(array, value) {
|
function pushAndNext(array, value) {
|
||||||
|
|
Loading…
Reference in New Issue