Navigation Menu

Skip to content

Commit

Permalink
inline docs for .add and .act; fix xward seneca reference bug
Browse files Browse the repository at this point in the history
  • Loading branch information
rjrodger committed Sep 30, 2016
1 parent 7e75a05 commit d28f43b
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 64 deletions.
47 changes: 21 additions & 26 deletions lib/actions.js
Expand Up @@ -8,7 +8,6 @@ var Assert = require('assert')

var _ = require('lodash')
var Jsonic = require('jsonic')
var Lrucache = require('lru-cache')


var Common = require('./common')
Expand Down Expand Up @@ -212,12 +211,10 @@ function inward_act_cache (ctxt, data) {
var so = ctxt.options
var msg = data.msg

var actid = msg.id$ || msg.actid$
var actid = msg.meta$.id
var private$ = ctxt.seneca.private$

if (actid != null && so.actcache.active) {
private$.actcache = private$.actcache || Lrucache({ max: so.actcache.size })

var actdetails = private$.actcache.get(actid)

if (actdetails) {
Expand Down Expand Up @@ -247,6 +244,26 @@ function inward_act_cache (ctxt, data) {
}


// Store result in action cache
function outward_act_cache (ctxt, data) {
var so = ctxt.options
var msg = data.msg
var res = data.res
var err = data.err

var actid = msg.meta$.id
var private$ = ctxt.seneca.private$

if (actid != null && so.actcache.active) {
private$.actcache.set(actid, {
result: [err, res],
actmeta: ctxt.actmeta,
when: Date.now()
})
}
}


function inward_warnings (ctxt, data) {
var so = ctxt.options

Expand Down Expand Up @@ -276,28 +293,6 @@ function inward_msg_meta (ctxt, data) {
}


// Store result in action cache
function outward_act_cache (ctxt, data) {
var so = ctxt.options
var msg = data.msg
var res = data.res
var err = data.err

var actid = msg.meta$.id
var private$ = ctxt.seneca.private$

if (actid != null && so.actcache.active) {
private$.actcache = private$.actcache || Lrucache({ max: so.actcache.size })

private$.actcache.set(actid, {
result: [err, res],
actmeta: ctxt.actmeta,
when: Date.now()
})
}
}


function outward_res_object (ctxt, data) {
var so = ctxt.options
var msg = data.msg
Expand Down
3 changes: 2 additions & 1 deletion lib/common.js
Expand Up @@ -59,7 +59,8 @@ exports.argprops = function argprops (defaults, args, fixed, omits) {

// string args override object args
exports.parsePattern = function parse_pattern (instance, args, normaspec, fixed) {
args = Norma('{strargs:s? objargs:o? moreobjargs:o? ' + (normaspec || '') + '}', args)
args =
Norma('{strargs:s? objargs:o? moreobjargs:o? ' + (normaspec || '') + '}', args)

try {
return _.extend(
Expand Down
17 changes: 17 additions & 0 deletions lib/print.js
@@ -1,10 +1,17 @@
/* Copyright (c) 2015 Richard Rodger, MIT License */
'use strict'


// Node API modules
var Util = require('util')


// External modules.
var _ = require('lodash')
var Archy = require('archy')
var Minimist = require('minimist')


/** Handle command line specific functionality */
module.exports = function (seneca) {
var argv = Minimist(process.argv.slice(2))
Expand Down Expand Up @@ -36,6 +43,16 @@ module.exports = function (seneca) {
}
}


module.exports.print_options = function print_options (options) {
if (options.debug.print.options) {
console.log('\nSeneca Options (' + root.id + '): before plugins\n' + '===\n')
console.log(Util.inspect(options, { depth: null }))
console.log('')
}
}


function print_tree (seneca, cmdspec) {
var tree = {
label: 'Seneca action patterns for instance: ' + seneca.id,
Expand Down
156 changes: 120 additions & 36 deletions seneca.js
@@ -1,11 +1,13 @@
/* Copyright (c) 2010-2016 Richard Rodger and other contributors, MIT License */
'use strict'

// Node API modules

// Node API modules.
var Assert = require('assert')
var Events = require('events')
var Util = require('util')


// External modules.
var _ = require('lodash')
var Eraro = require('eraro')
Expand All @@ -17,6 +19,7 @@ var Norma = require('norma')
var Patrun = require('patrun')
var Stats = require('rolling-stats')
var Ordu = require('ordu')
var Lrucache = require('lru-cache')


// Internal modules.
Expand All @@ -35,6 +38,7 @@ var Transport = require('./lib/transport')
var errlog = Common.make_standard_err_log_entry
var actlog = Common.make_standard_act_log_entry


var internals = {
error: Eraro({
package: 'seneca',
Expand Down Expand Up @@ -165,6 +169,8 @@ var internals = {
}
}


// Utility functions exposed by Seneca via `seneca.util`.
var seneca_util = {
deepextend: Common.deepextend,
recurse: Common.recurse,
Expand All @@ -179,6 +185,7 @@ var seneca_util = {
argprops: Common.argprops
}


// Seneca is an EventEmitter.
function Seneca () {
Events.EventEmitter.call(this)
Expand All @@ -187,22 +194,18 @@ function Seneca () {
Util.inherits(Seneca, Events.EventEmitter)


// Create a Seneca instance.
module.exports = function init (seneca_options, more_options) {
// Create instance.
var seneca = make_seneca(_.extend({}, seneca_options, more_options))
var options = seneca.options()

seneca.log.info({kind: 'notice', notice: 'seneca started'})
seneca.log.info({kind: 'notice', notice: 'hello'})

// The 'internal' key of options is reserved for objects and functions
// that provide functionality, and are thus not really printable
seneca.log.debug({kind: 'notice', options: _.omit(options, ['internal'])})

if (options.debug.print.options) {
console.log('\nSeneca Options (' + root.id + '): before plugins\n' + '===\n')
console.log(Util.inspect(options, { depth: null }))
console.log('')
}
Print.print_options(options)

// TODO: these are core API and should not be decorations
seneca.decorate('hasplugin', Plugins.api_decorations.hasplugin)
Expand Down Expand Up @@ -289,9 +292,96 @@ function make_seneca (initial_options) {
root.context = {}
root.version = Package.version

private$.actcache = Lrucache({ max: so.actcache.size })


// Seneca methods. Official API.
root.add = api_add // Add a message pattern and action.

// # seneca.add
//
// Add a message pattern and action.
// * `pattern` <small>_string|object_</small> &rarr;
// Pattern definition as
// [jsonic](https://github.com/rjrodger/jsonic) string or object.
//
// * `action` <small>_function (optional)_</small> &rarr;
// Action function.
//
// When a message that matches the pattern is submitted inward using
// `seneca.act`, the action function is called with parameters:
// * `message` <small>_object_</small> &rarr; Message object.
// * `reply` <small>_function_</small> &rarr; Callback function.
//
// The `reply` callback is used to provide a response to the
// message. If the action function is not provided, the pattern
// will be added with a default action function that does
// nothing. The `reply` callback has parameters:
// * `error` <small>_Error (optional)_</small> &rarr;
// Provide this value if you wish to provide an error response to the message.
// * `response` <small>_object|array (optional)_</small> &rarr;
// Response data to the message.
//
// **The action function is not a lambda, and the `=>` function
// syntax should not be used.** The context `this` of the action
// function is a reference to the current Seneca instance, tha
// should always be used for subsequent `seneca.act` calls, as this
// enables accurate tracing of actions.
//
// If the pattern added has been added previously, then the new
// action function overrides the old action function. The old action
// function is available via the `seneca.prior` method of the
// current Seneca instance (`this` in the new action function). A
// chain of priors is formed if additional action functions with the
// same pattern are added. There is a tutorial on [Seneca
// priors](http://senecajs.org/tutorials/priors.html).
root.add = api_add

// # Seneca.act
//
// Send a message. If the message matches a pattern, execute the
// action function.
// * `msg` <small>_object_</small> &rarr;
// The message data. Only data that can be fully represented as JSON is valid.
// * `callback` <small>_function (optional)_</small> &rarr;
// The callback function that will receive the response to the
// message, generated by the action function.
//
// The message data may contain control properties, indicated by a
// `$` suffix. These are described in the [control properties
// reference](http://senecajs.org/documentation/control-properties.html)
//
// **The callback function should not be a lambda (`=>`)**. The current
// Seneca instance is provided via `this`, and should be used for
// subsequent `seneca.act` calls, as this enables accurate tracing
// of actions.
//
// If the callback function is provided, then the message
// interaction is assumed to be synchronous, and a response from the
// action function will be expected. If the callback function is not
// provided, the interaction is assumed to be asynchronous, and no
// response is expected.
//
// The callback function has parameters:
// * `error` <small>_Error_</small> &rarr; If an error occurred,
// an Error object will be provided, otherwise this is `null`. If
// the action times out, an error will be provided.
// * `response` <small>_object|array_</small> &rarr;
// The response data from the action function, if any.
//
// For convenience, you can build the full message from separate
// parts, including [jsonic](https://github.com/rjrodger/jsonic)
// strings. The full set of parameters to `seneca.act` is:
// * `jsonic` <small>_string (optional)_</small> &rarr;
// Message properties in jsonic format. These have precedence over
// other message parts.
// * `part1` <small>_object (optional)_</small> &rarr;
// Message data having precedence over `part2`.
// * `part2` <small>_object (optional)_</small> &rarr;
// Message data.
// * `callback` <small>_function (optional)_</small> &rarr;
// As previously described.
root.act = api_act // Perform action that matches pattern.

root.sub = api_sub // Subscribe to a message pattern.
root.use = api_use // Define a plugin.
root.listen = Transport.listen(callpoint) // Listen for inbound messages.
Expand Down Expand Up @@ -944,9 +1034,23 @@ function make_seneca (initial_options) {
function execute_action (act_instance, msg, action_done) {
actmeta = actmeta || act_instance.find(msg, {catchall: so.internal.catchall})

action_ctxt.seneca = act_instance
// build msg
// remove actid so that user manipulation of msg for subsequent use does
// not cause inadvertent hit on existing action
delete msg.id$
delete msg.actid$ // legacy alias

msg.meta$.start = actstart
msg.meta$.entry = prior_ctxt.entry
msg.meta$.chain = prior_ctxt.chain
msg.meta$.sync = is_sync

var delegate =
act_make_delegate(act_instance, msg, actmeta, prior_ctxt, do_act)

action_ctxt.seneca = delegate
action_ctxt.actmeta = actmeta
action_ctxt.options = act_instance.options()
action_ctxt.options = delegate.options()
action_ctxt.callpoint = act_callpoint

var inwardres = private$.inward.process(action_ctxt, {msg: msg})
Expand Down Expand Up @@ -975,20 +1079,6 @@ function make_seneca (initial_options) {
}
}

// build msg
// remove actid so that user manipulation of msg for subsequent use does
// not cause inadvertent hit on existing action
delete msg.id$
delete msg.actid$ // legacy alias

msg.meta$.start = actstart
msg.meta$.entry = prior_ctxt.entry
msg.meta$.chain = prior_ctxt.chain
msg.meta$.sync = is_sync

var delegate =
act_make_delegate(act_instance, msg, actmeta, prior_ctxt, do_act)

action_done = action_done.bind(delegate)

msg = _.extend({}, msg, delegate.fixedargs, {tx$: msg.meta$.tx})
Expand Down Expand Up @@ -1514,16 +1604,6 @@ function make_callpoint (active) {


function make_log (instance, modifier) {
/*
var log = _.noop
log.debug = _.noop
log.info = _.noop
log.warn = _.noop
log.error = _.noop
log.fatal = _.noop
return log
*/

var log = instance.log || function log (data) {
instance.private$.logger(this, data)
}
Expand Down Expand Up @@ -1575,6 +1655,8 @@ function default_log_modifier (data) {


function act_make_delegate (instance, msg, actmeta, prior_ctxt, do_act) {
actmeta = actmeta || {}

var delegate_args = {
plugin$: {
name: actmeta.plugin_name,
Expand All @@ -1585,7 +1667,9 @@ function act_make_delegate (instance, msg, actmeta, prior_ctxt, do_act) {
var delegate = instance.delegate(delegate_args)

// special overrides
if (msg.meta$.tx) { delegate.fixedargs.tx$ = msg.meta$.tx }
if (msg.meta$.tx) {
delegate.fixedargs.tx$ = msg.meta$.tx
}

// automate actid log insertion

Expand Down
2 changes: 1 addition & 1 deletion test/cli.test.js
Expand Up @@ -18,7 +18,7 @@ describe('cli', function () {
it('won\'t display action patterns message when they aren\'t provided', function (done) {
ChildProcess.exec(process.argv[0] + ' ' + launchPath, function (err, stdout, stderr) {
expect(err).to.not.exist()
expect(stdout).to.contain('seneca started')
expect(stdout).to.contain('hello')
done()
})
})
Expand Down

0 comments on commit d28f43b

Please sign in to comment.