Skip to content

Commit

Permalink
intern test; callback error
Browse files Browse the repository at this point in the history
  • Loading branch information
rjrodger committed Feb 17, 2018
1 parent 112bb0d commit f1c1e37
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 120 deletions.
110 changes: 93 additions & 17 deletions lib/outward.js
Expand Up @@ -8,7 +8,13 @@ var _ = require('lodash')

var Common = require('./common')


// Internal implementations.
var intern = {}


module.exports = {
test$: { intern: intern },
act_cache: outward_act_cache,
res_object: outward_res_object,
act_stats: outward_act_stats,
Expand Down Expand Up @@ -166,26 +172,10 @@ function outward_trace(ctxt, data) {
function outward_act_error(ctxt, data) {
var delegate = ctxt.seneca
var actdef = ctxt.actdef
var origmsg = ctxt.origmsg
var reply = ctxt.reply

var meta = data.meta
var err = data.err
var out = data.out
var actmsg = data.msg

if (meta.error) {
data.error_desc = ctxt.act_error(
delegate,
data,
actdef,
[err, out],
reply,
ctxt.duration,
actmsg,
origmsg,
ctxt.callpoint
)
data.error_desc = intern.act_error(delegate, ctxt, data)

if (meta.fatal) {
// TODO: this should not happen here inside outward processing
Expand Down Expand Up @@ -216,3 +206,89 @@ function outward_res_entity(ctxt, data) {
data.res = delegate.make$(data.res)
}
}


intern.act_error = function(instance, ctxt, data) {
var duration = ctxt.duration
var act_callpoint = ctxt.callpoint
var actdef = ctxt.actdef || {}
var origmsg = ctxt.origmsg
var reply = ctxt.reply

var meta = data.meta
var msg = data.msg

var opts = instance.options()

var call_cb = true

var err = data.res || data.err

if (!err.seneca) {
var details = _.extend({}, err.details, {
message: err.eraro && err.orig ? err.orig.message : err.message,
pattern: actdef.pattern,
fn: actdef.func,
callback: reply,
instance: instance.toString(),
callpoint: act_callpoint
})

if (opts.legacy.error) {
err = ctxt.error(err, 'act_execute', details)
} else {
var seneca_err = ctxt.error('act_execute', {
pattern: actdef.pattern,
message: err.message,
callpoint: act_callpoint
})
delete seneca_err.stack

err.meta$ = err.meta$ || meta || {}
err.meta$.data = instance.util.clean(origmsg)

if (err.meta$.err) {
var errmeta = _.clone(meta)
errmeta.err = seneca_err
err.meta$.err_trace = err.meta$.err_trace || []
err.meta$.err_trace.push(errmeta)
} else {
err.meta$.err = seneca_err
}
}

} else if (
err.orig &&
_.isString(err.orig.code) &&
err.orig.code.indexOf('perm/') === 0
) {
// Special legacy case for seneca-perm
err = err.orig
}

if (opts.legacy.error) {
err.details = err.details || {}
err.details.plugin = err.details.plugin || {}
}

var entry = ctxt.actlog(actdef, msg, meta, origmsg, {
// kind is act as this log entry relates to an action
kind: 'act',
case: 'ERR',
duration: duration
})
entry = ctxt.errlog(err, entry)

instance.log.error(entry)
instance.emit('act-err', msg, err)

// when fatal$ is set, prefer to die instead
if (opts.errhandler && (!msg || !meta.fatal)) {
call_cb = !opts.errhandler.call(instance, err, err.meta$ || meta)
}

return {
call_cb: call_cb,
err: err
}
}
112 changes: 11 additions & 101 deletions seneca.js
Expand Up @@ -224,7 +224,8 @@ var seneca_util = {
},
argprops: Common.argprops,
resolve_option: Common.resolve_option,
flatten: Common.flatten
flatten: Common.flatten,
error: error
}

// Internal implementations.
Expand Down Expand Up @@ -293,7 +294,7 @@ module.exports.test = function top_test() {
}

module.exports.util = seneca_util
module.exports.intern = intern
module.exports.test$ = {intern: intern}

// Create a new Seneca instance.
// * _initial_options_ `o` → instance options
Expand Down Expand Up @@ -1301,7 +1302,8 @@ intern.handle_reply = function(meta, actctxt, actmsg, err, out, reply_meta) {

actctxt.duration = meta.end - meta.start
actctxt.actlog = actlog
actctxt.act_error = intern.act_error
actctxt.errlog = errlog
actctxt.error = error

meta.error = data.res instanceof Error

Expand Down Expand Up @@ -1458,102 +1460,13 @@ intern.process_outward = function(actctxt, data) {
}
}

intern.act_error = function(
instance,
data,
actdef,
result,
cb,
duration,
msg,
origmsg,
act_callpoint
) {
var opts = instance.options()

var call_cb = true
actdef = actdef || {}

var err = data.res || data.err
var meta = data.meta

if (!err.seneca) {
var details = _.extend({}, err.details, {
message: err.eraro && err.orig ? err.orig.message : err.message,
pattern: actdef.pattern,
fn: actdef.func,
cb: cb,
instance: instance.toString(),
callpoint: act_callpoint
})

if (opts.legacy.error) {
err = error(err, 'act_execute', details)
} else {
var seneca_err = error('act_execute', {
pattern: actdef.pattern,
message: err.message,
callpoint: act_callpoint
})
delete seneca_err.stack

err.meta$ = err.meta$ || meta || {}
err.meta$.data = instance.util.clean(origmsg)

if (err.meta$.err) {
var errmeta = _.clone(meta)
errmeta.err = seneca_err
err.meta$.err_trace = err.meta$.err_trace || []
err.meta$.err_trace.push(errmeta)
} else {
err.meta$.err = seneca_err
}
}

result[0] = err
} else if (
err.orig &&
_.isString(err.orig.code) &&
err.orig.code.indexOf('perm/') === 0
) {
// Special legacy case for seneca-perm
err = err.orig
result[0] = err
}

if (opts.legacy.error) {
err.details = err.details || {}
err.details.plugin = err.details.plugin || {}
}

var entry = actlog(actdef, msg, meta, origmsg, {
// kind is act as this log entry relates to an action
kind: 'act',
case: 'ERR',
duration: duration
})
entry = errlog(err, entry)

instance.log.error(entry)
instance.emit('act-err', msg, err)

// when fatal$ is set, prefer to die instead
if (opts.errhandler && (!msg || !meta.fatal)) {
call_cb = !opts.errhandler.call(instance, err, err.meta$ || meta)
}

return {
call_cb: call_cb,
err: err
}
}

intern.callback_error = function(instance, thrown_obj, actctxt, data) {
var duration = actctxt.duration
var act_callpoint = actctxt.callpoint
var actdef = actctxt.actdef || {}
var origmsg = actctxt.origmsg
var reply = actctxt.reply
intern.callback_error = function(instance, thrown_obj, ctxt, data) {
var duration = ctxt.duration
var act_callpoint = ctxt.callpoint
var actdef = ctxt.actdef || {}
var origmsg = ctxt.origmsg
var reply = ctxt.reply

var meta = data.meta
var msg = data.msg
Expand All @@ -1579,9 +1492,6 @@ intern.callback_error = function(instance, thrown_obj, actctxt, data) {
)
}

err.details = err.details || {}
err.details.plugin = err.details.plugin || {}

instance.log.error(
actlog(actdef, msg, meta, origmsg, {
// kind is act as this log entry relates to an action
Expand Down
65 changes: 63 additions & 2 deletions test/error.test.js
@@ -1,15 +1,18 @@
/* Copyright (c) 2014-2017 Richard Rodger, MIT License */
/* Copyright (c) 2014-2018 Richard Rodger, MIT License */
'use strict'

var Assert = require('assert')
var Lab = require('lab')
var Code = require('code')
var Seneca = require('..')
var TransportStubs = require('./stubs/transports')

var lab = (exports.lab = Lab.script())
var describe = lab.describe
var it = lab.it
var expect = Code.expect
var assert = Assert

var testopts = { log: 'silent' }

// Shortcuts
Expand Down Expand Up @@ -42,11 +45,68 @@ describe('error', function() {
it('exec_action_errhandler_result', exec_action_errhandler_result)

it('action_callback', action_callback)
it('action_callback', action_callback_legacy)

it('ready_die', ready_die)

it('legacy_fail', legacy_fail)



function action_callback(fin) {
var si = Seneca({log: 'silent'})

si.add('a:1', function(msg, reply) {
reply({x:1})
})

throw_err_obj()

function throw_err_obj() {
si.error(function(err) {
try {
expect(err.code).equal('act_callback')
expect(err.message).contains('CALLBACK')
throw_obj()
} catch(e) { fin(e) }
})

si.act('a:1', function(err, out) {
throw new Error('CALLBACK')
})
}


function throw_obj() {
si.error(function(err) {
try {
expect(err.code).equal('act_callback')
expect(err.message).contains('CALLBACK')
throw_seneca_error()
} catch(e) { fin(e) }
})

si.act('a:1', function(err, out) {
throw 'CALLBACK'
})
}

function throw_seneca_error() {
si.error(function(err) {
try {
expect(err.code).equal('foo')
expect(err.message).contains('foo')
fin()
} catch(e) { fin(e) }
})

si.act('a:1', function(err, out) {
throw si.util.error('foo')
})
}
}


function fail_assert(done) {
return function(err) {
if (err && 'AssertionError' === err.name) {
Expand Down Expand Up @@ -498,7 +558,8 @@ describe('error', function() {
}
}

function action_callback(done) {

function action_callback_legacy(done) {
var ctxt = { errlog: null }
var si = make_seneca(ctxt)

Expand Down

0 comments on commit f1c1e37

Please sign in to comment.