The unique identifier string of this Seneca instance.
The start time (in local milliseconds) of this Seneca instance.
The tag string of this Seneca instance, defined by the tag option.
A namespace object for the utility functions.
The current version of Seneca.
Namespace object for options related to debugging. They should all be false
for production deployments.
Namespace for plugin options. Once loaded, plugin options are stored here for ease of shared access.
Namespace object for options related to strict behaviors. Mostly this is for backwards compatibility with older versions of Seneca that were not as strict.
Tag the Seneca instance with a short code that will be added to the instance identifier. Useful for tracing and debugging.
When true
Seneca is in unit testing mode. To enter enter this mode, use the test method.
The global timeout for actions. Once this timeout is exceeded, the sender of the message receives an error response via the callback of the act method.
Create an instance of the Seneca object.
Send a message and receive a response via the callback. If there is no callback the message is asynchronous.
Add an action function to be called when inbound messages match the pattern.
Send outbound messages.
Enter gated mode, where all actions must complete before new actions can start. This is used to give plugin initialization a deterministic order.
List all added patterns that partially match the given pattern.
Listen for inbound messages.
Create log entries.
Get and set options.
Wait for plugins to initialize fully.
Exit gated mode. Actions now execute immediately and do not wait for each other. This is the default mode.
Load a plugin and use the action patterns that it defines. Plugin initialization must complete before further actions are executed.
The full message identifier, which concatenates the message and correlation identifiers.
When true
the message is synchronous, otherwise the message is asynchronous.
If the pattern is not found, provide a default response.
Any errors in this action, or sub actions, will be fatal. Used for plugin definition and initialization.
This action is gated and must complete before any other actions can start.
Specify a local timeout in milliseconds for this particular action execution.
The plugin initialization action. Executed in order deterministically with other plugin initialization actions.
Clean messages by removing metadata and directives. All (and only) top level property names containing a $
character are removed.
Combine the listed objects into one new object, overwriting properties from right to left.
Convert a pattern object into a normalized jsonic String.
The unique identifier string of this Seneca instance.
var seneca = require('seneca')()
// Prints the instance identifier string.
console.log(seneca.id)
The start time (in local milliseconds) of this Seneca instance.
var seneca = require('seneca')()
// Prints the start time of the instance in local milliseconds.
console.log(seneca.start_time)
The tag string of this Seneca instance, defined by the tag option.
var seneca = require('seneca')({tag: 'foo'})
// Prints the tag string of the instance.
console.log(seneca.tag)
A namespace object for the utility functions.
var seneca = require('seneca')()
// Prints the utility functions.
console.log(seneca.util)
The current version of Seneca.
var seneca = require('seneca')()
// Prints the version of the Seneca instance.
console.log(seneca.version)
Namespace object for options related to debugging. They should all be false
for production deployments.
deprecation | Boolean | true | Deprecation warnings are logged at the debug level. Should be false in production. You should update your code. |
undead | Boolean | false | When true , fatal errors will not exit the process. Should only be used for debugging, and fatal errors are fatal because they leave Seneca in an indeterminate invalid state. |
require('seneca')({
// Set option via Seneca constructor.
debug: {
undead: true
}
})
// Test mode has easy to read logs.
.test()
// Normally, this would be fatal, but with debug.undead = true,
// you get error logs instead.
.use(function bad_plugin () {
throw new Error('plugin definition failed')
})
// Add a deprecated action pattern.
.add('a:1,deprecate$:"a:1 is too old"', function (msg, reply) {reply()})
// As debug.deprecation is true by default, you get a deprecation log entry:
// 232/zq act/DEPRECATED ic/rt {a:1} a:1 is too old
.act('a:1')
// Wait for above actions to complete before changing options.
.ready(function () {
this
.options({debug: {deprecation: false}}, true) // (true => chainable)
// Now, no warnings are logged.
.act('a:1')
})
Namespace for plugin options. Once loaded, plugin options are stored here for ease of shared access.
// The foo plugin
function foo (options) {
// Prints: hello Mars
console.log('hello '+options.hello)
// Prints: bye Earth
console.log('bye '+options.bye)
// A plugin can change its own options
this.options({
plugin: {
foo: {
why: 'wait'
}
}
})
}
require('seneca')({
// Namespace for plugin options.
plugin: {
// Preset options for the foo plugin.
foo: {
hello: 'Mars'
}
}
})
// Define the foo plugin
.use(foo, {
bye: 'Earth'
})
.ready(function () {
// Prints: { why: 'wait', hello: 'moon', bye: 'earth' }
console.log(this.options().plugin.foo)
})
Namespace object for options related to strict behaviors. Mostly this is for backwards compatibility with older versions of Seneca that were not as strict.
result | Boolean | true | The result provided by an action must be an Object or an Array that can be fully serialized to JSON. When false scalar values (Strings, Numbers, etc) are permitted. Use only to keep old code working while you migrate. |
require('seneca')({
// Namespace for strict options.
strict: {
// Allow results to be non-Objects.
result: false
}
})
.add('a:1', function (msg, reply) {
// Normally, this would fail, as the response is not an Object.
reply('Hi there!')
})
// Prints null Hi There!
.act('a:1', console.log)
Tag the Seneca instance with a short code that will be added to the instance identifier. Useful for tracing and debugging.
The tag value is a free form String that is appended to the end of the Seneca identifier. It is not meant to be a unique value. You use it identify groups of microservices.
The public member variable Seneca.tag
can be used to retrieve the tag value.
var seneca = require('seneca')({tag: 'foo'})
// prints foo
console.log(seneca.tag)
// prints .../foo
console.log(seneca.id)
When true
Seneca is in unit testing mode. To enter enter this mode, use the test method.
var Seneca = require('seneca')
function unit_test(done) {
var seneca = Seneca().test(done)
// prints true
console.log(true === seneca.options().test)
seneca
.add('a:1', function () {
throw new Error('failed!')
})
.act('a:1')
}
// prints lots of error information
unit_test(console.log)
The global timeout for actions. Once this timeout is exceeded, the sender of the message receives an error response via the callback of the act method.
require('seneca')({
// Change global timeout to 1000 milliseconds.
timeout: 1000
})
// Add an action pattern that takes at least 2000 milliseconds.
.add('a:1', function (msg, reply) {
setTimeout(function () {
reply({z: msg.z})
}, 2000)
})
// Times out and prints an error, as 1000 < 2000 milliseconds.
.act('a:1, z:never', console.log)
// Override the global timeout with the timeout$ directive.
// This message works fine and prints a result:
.act('a:1, z:works, timeout$:3000', console.log)
Create an instance of the Seneca object.
options | Object| String (optional) |
var Seneca = require('seneca')
var senecaA = Seneca()
var senecaB = Seneca({tag: 'foo'})
Send a message and receive a response via the callback. If there is no callback the message is asynchronous.
message | jsonic| Object | The pattern that inbound messages must match to trigger this action. |
sub_message | Object (optional) | A convenience parameter that is merged into the message parameter with lower precedence. |
callback | Function (optional) | The function that executes the action for this pattern. |
require('seneca')()
// Add an action for pattern a:1,b:2.
.add({a: 1, b: 2}, function (msg, reply) {
reply({z: msg.z})
})
// Use a jsonic String as the message. Prints: null { z: 9 }
.act('a:1,b:2,z:9', console.log)
// Use an Object as the message. Prints: null { z: 9 }
.act({a: 1, b: 2, z: 9}, console.log)
// Merge a jsonic String and an Object to form the message. Prints: null { z: 9 }
.act('a:1,b:2', {z: 9}, console.log)
// Merge two Objects. Precedence is left to right. Prints: null { z: 9 }
.act({a: 1, b: 2}, {b: 3, z: 9}, console.log)
Add an action function to be called when inbound messages match the pattern.
pattern | jsonic| Object | The pattern that inbound messages must match to trigger this action. |
sub_pattern | Object (optional) | A convenience parameter that is merged into the pattern parameter with lower precedence. |
action | Function | The function that executes the action for this pattern. |
require('seneca')()
// Add an action for pattern a:1 using an object to define the pattern.
.add({a: 1}, function (msg, reply) {
reply({z: msg.z})
})
// Add an action for pattern a:2, using a jsonic String to define the pattern.
.add('a:2', function (msg, reply) {
reply({y: msg.y})
})
// Add an action for pattern a:3,b:4, merging a jsonic String and an Object to
// define the pattern. Precedence is left to right.
.add('a:3', {a:1, b: 4}, function (msg, reply) {
reply({x: msg.x})
})
// Prints: null { z: 'A' }
.act('a:1,z:A', console.log)
// Prints: null { y: 'B' }
.act('a:2,y:B', console.log)
// Prints: null { x: 'C' }
.act('a:3,b:4,x:C', console.log)
Send outbound messages.
port | Integer| String (optional) | |
host | String (optional) |
var Seneca = require('seneca')
// Create server. Hide logging noise.
Seneca({log:'silent'})
// Define some action patterns.
.add({a: 1}, function (msg, reply) {
reply({z: msg.z})
})
.add({b: 1}, function (msg, reply) {
reply({y: msg.y})
})
// Define an action pattern that fails.
.add({a: 2}, function (msg, reply) {
reply(new Error('bad'))
})
// Listen on localhost:9000 for any messages
.listen(9000)
// Listen on localhost:9001 for any messages that match b:1
.listen({port: 9001, pin: 'b:1'})
// Create client. Hide logging noise.
Seneca({log:'silent'})
// Define a local action.
.add({c: 1}, function (msg, reply) {
reply({x: msg.x})
})
// Send any unrecognized messages to localhost:9000
.client(9000)
// Send any messages that match b:1 to localhost:9001
.client({port: 9001, pin: 'b:1'})
// Executes remotely. Prints: { z: 'A' }
.act('a:1,z:A', Seneca.util.print)
// Executes remotely. Prints: ERROR: seneca: Action a:2 failed: bad.
.act('a:2', Seneca.util.print)
// Executes remotely. Prints: { y: 'B' }
.act('b:1,y:B', Seneca.util.print)
// Executes locally. Prints: { x: 'C' }
.act('c:1,x:C', Seneca.util.print)
Find the unique action metadata for the given pattern. Returns null if the pattern has not been added.
pattern | Object| String |
var seneca = require('seneca')()
.add('a:1', function (msg, reply) { reply() })
.add('b:1', function (msg, reply) { reply() })
// Exact match. Prints: action metadata
console.log(seneca.find('a:1'))
// Exact match. Prints: action metadata
console.log(seneca.find('b:1'))
// Not found. Prints: null
console.log(seneca.find('c:1'))
Enter gated mode, where all actions must complete before new actions can start. This is used to give plugin initialization a deterministic order.
var Seneca = require('seneca')
Seneca()
.test(console.log, 'print')
.add('a:1', function (msg, reply) {
setTimeout(function () {
reply({z: msg.z})
}, 100)
})
.add('b:1', function (msg, reply) {
setTimeout(function () {
reply({y: msg.y})
}, 100)
})
// Wait for initialization log entries to print
.ready(function () {
this
.gate()
.act('a:1,z:A', Seneca.util.print)
.act('b:1,y:B', Seneca.util.print)
.ungate()
.act('a:1,z:AA', Seneca.util.print)
.act('b:1,y:BB', Seneca.util.print)
})
Returns true
if the given pattern has been added.
pattern | Object| String |
var seneca = require('seneca')()
.add('a:1', function (msg, reply) { reply() })
.add('b:1', function (msg, reply) { reply() })
// Exact match. Prints: true
console.log(seneca.has('a:1'))
// Exact match. Prints: true
console.log(seneca.has('b:1'))
// Not found. Prints: false
console.log(seneca.has('c:1'))
List all added patterns that partially match the given pattern.
pattern | Object| String |
var seneca = require('seneca')()
.add('a:1', function (msg, reply) { reply() })
.add('a:2', function (msg, reply) { reply() })
.add('a:1,b:1', function (msg, reply) { reply() })
// Partial match. Prints: [ { a: '1' }, { a: '1', b: '1' } ]
console.log(seneca.list('a:1'))
// Partial match. Prints: [ { a: '1', b: '1' } ]
console.log(seneca.list('b:1'))
// None. Prints: []
console.log(seneca.list('c:1'))
Listen for inbound messages.
port | Integer| String (optional) | |
host | String (optional) |
var Seneca = require('seneca')
// Create server. Hide logging noise.
Seneca({log:'silent'})
// Define some action patterns.
.add({a: 1}, function (msg, reply) {
reply({z: msg.z})
})
.add({b: 1}, function (msg, reply) {
reply({y: msg.y})
})
// Define an action pattern that fails.
.add({a: 2}, function (msg, reply) {
reply(new Error('bad'))
})
// Listen on localhost:9000 for any messages
.listen(9000)
// Listen on localhost:9001 for any messages that match b:1
.listen({port: 9001, pin: 'b:1'})
// Create client. Hide logging noise.
Seneca({log:'silent'})
// Define a local action.
.add({c: 1}, function (msg, reply) {
reply({x: msg.x})
})
// Send any unrecognized messages to localhost:9000
.client(9000)
// Send any messages that match b:1 to localhost:9001
.client({port: 9001, pin: 'b:1'})
// Executes remotely. Prints: { z: 'A' }
.act('a:1,z:A', Seneca.util.print)
// Executes remotely. Prints: ERROR: seneca: Action a:2 failed: bad.
.act('a:2', Seneca.util.print)
// Executes remotely. Prints: { y: 'B' }
.act('b:1,y:B', Seneca.util.print)
// Executes locally. Prints: { x: 'C' }
.act('c:1,x:C', Seneca.util.print)
Create log entries.
object | Object |
var Seneca = require('seneca')
var seneca = Seneca()
seneca.log({level:'info', foo: 1})
seneca.log.info({foo: 2})
Get and set options.
object | Object (optional) | |
chain | Boolean (optional) |
var Seneca = require('seneca')
var seneca = Seneca({foo:1})
// Prints: 1
console.log(seneca.options().foo)
seneca.options({foo: 2, bar: 3})
// Prints: 2
console.log(seneca.options().foo)
// Prints: 3
console.log(seneca.options().bar)
Wait for plugins to initialize fully.
callback | Function |
require('seneca')()
// Define the foo plugin
.use(function foo () {
// The special initialization action, which is automatically gated.
this.add('init:foo', function (msg, reply) {
setTimeout(reply, 100)
})
})
// Define the bar plugin
.use(function bar () {
// The special initialization action, which is automatically gated.
this.add('init:bar', function (msg, reply) {
setTimeout(reply, 100)
})
})
// Called once foo and bar initialization is complete.
.ready(function () {
console.log('Seneca ready!')
})
Enter unit testing mode.
callback | Function | |
logspec | Object| String |
var seneca = require('seneca')()
.test(console.log, 'print')
.add('a:1', function (msg, reply) {
reply()
})
.add('b:1', function (msg, reply) {
reply(new Error('bad'))
})
.act('a:1')
.act('b:1')
Exit gated mode. Actions now execute immediately and do not wait for each other. This is the default mode.
var Seneca = require('seneca')
Seneca()
.test(console.log, 'print')
.add('a:1', function (msg, reply) {
setTimeout(function () {
reply({z: msg.z})
}, 100)
})
.add('b:1', function (msg, reply) {
setTimeout(function () {
reply({y: msg.y})
}, 100)
})
// Wait for initialization log entries to print
.ready(function () {
this
.gate()
.act('a:1,z:A', Seneca.util.print)
.act('b:1,y:B', Seneca.util.print)
.ungate()
.act('a:1,z:AA', Seneca.util.print)
.act('b:1,y:BB', Seneca.util.print)
})
Load a plugin and use the action patterns that it defines. Plugin initialization must complete before further actions are executed.
plugin | String| Function| Object | The plugin definition is either: the name of a module; a file path; an initialization function; or a metadata object. |
options | Object (optional) | The options that control the plugin's behavior. These are placed under the property path plugin.<plugin-name> in the Seneca options object. |
The plugin initialization action. Executed in order deterministically with other plugin initialization actions.
require('seneca')()
// Define the foo plugin
.use(function foo () {
// An external resource that takes time to initialize.
var resource
// An action that depends on the resource.
this.add('a:1', function(msg, reply) {
reply({z: resource[msg.z]})
})
// The special initialization action, which is automatically gated.
this.add('init:foo', function (msg, reply) {
setTimeout(function () {
resource = {
0: 'A'
}
reply()
}, 100)
})
})
// Define the bar plugin
.use(function bar (options) {
// This init action will wait for the foo init action to complete.
// Plugins initiate in the order they are defined.
this.add('init:bar', function (msg, reply) {
var seneca = this
setTimeout(function () {
// Delayed definition of an action.
seneca.add('b:2', function(msg, reply) {
reply({y: options.y[msg.y]})
})
reply()
}, 100)
})
}, {
// The options for the bar plugin
y: {
0: 'B'
}
})
// These actions are gated until the plugin init actions are complete.
// Prints: null { z: 'A' }
.act('a:1,z:0', console.log)
// Prints: null { y: 'B' }
.act('b:2,y:0', console.log)
The full message identifier, which concatenates the message and correlation identifiers.
require('seneca')()
.add('a:1', function (msg, reply) {
// Prints message identifier in format
// message-id/correlation-id
console.log(msg.meta$.id)
reply()
})
.act('a:1')
When true
the message is synchronous, otherwise the message is asynchronous.
require('seneca')()
.add('a:1', function (msg, reply) {
console.log(msg.z+' is synchronous: '+msg.meta$.sync)
if (msg.meta$.sync) {
reply({z: msg.z})
}
else {
// You must always call the reply function even when there is no response
// data, as this lets Seneca know that the action is complete.
reply()
}
})
// Omitting the callback makes a message asynchronous.
// Prints: 0 is synchronous: false
.act('a:1,z:0')
// Providing the callback makes a message synchronous.
// Prints: 1 is synchronous: true
.act('a:1,z:1', console.log)
If the pattern is not found, provide a default response.
require('seneca')({
// run in quiet mode to reduce logging distraction
log: 'silent'
})
.add('a:1', function (msg, reply) {
reply({z: msg.z})
})
// Prints: null { z: 0 }
.act('a:1, z:0', console.log)
// Prints an error
.act('a:2, z:1', console.log)
// Prints: null { z: 9 }
.act('a:2, z:2, default$:{z:9}', console.log)
Any errors in this action, or sub actions, will be fatal. Used for plugin definition and initialization.
When this modifier is true
, Seneca will terminate the Node.js process if an error occurs inside an action, or any actions that that action calls. This prevents a Seneca microservice from continuing to run when a plugin has failed to start up correctly.
For example, if an entity plugin cannot connect to the database, the microservice is not functional, and should die.
On death, Seneca will print out a detailed error message including summary information about the current process.
require('seneca')()
// Add an action pattern that fails
.add('a:1', function (msg, reply) {
throw new Error('something bad happened')
})
// Logs an error, but Seneca process does not die
.act('a:1')
// Seneca causes Node.js process to die
.act('a:1, fatal$:true')
// BUT - you can disable this for testing
require('seneca')({debug: {undead: true}})
.add('a:1', function (msg, reply) {
throw new Error('something bad happened')
})
// Now Seneca won't die
.act('a:1, fatal$:true')
This action is gated and must complete before any other actions can start.
require('seneca')()
.add('a:1', function (msg, reply) {
console.log('STARTING: '+msg.z)
setTimeout(function () {
reply({z: msg.z})
}, 100)
})
.act('a:1, z:0', console.log)
.act('a:1, z:1, gate$:true', console.log)
.act('a:1, z:2', console.log)
// Prints:
// STARTING: 0
// STARTING: 1 <- z:1 does not have to wait for z:0
// null { z: 0 }
// null { z: 1 }
// STARTING: 2 <- z:2 cannot start until z:1 completes
// null { z: 2 }
Specify a local timeout in milliseconds for this particular action execution.
require('seneca')({
// Change global timeout to 1000 milliseconds.
timeout: 1000
})
// Add an action pattern that takes at least 2000 milliseconds.
.add('a:1', function (msg, reply) {
setTimeout(function () {
reply({z: msg.z})
}, 2000)
})
// Times out and prints an error, as 1000 < 2000 milliseconds.
.act('a:1, z:never', console.log)
// Override the global timeout with the timeout$ directive.
// This message works fine and prints a result:
.act('a:1, z:works, timeout$:3000', console.log)
Clean messages by removing metadata and directives. All (and only) top level property names containing a $
character are removed.
message | Object | Message object to clean. |
var Seneca = require('seneca')
var seneca = Seneca()
var cleaned = seneca.util.clean(
{a: 1, b$: 2, c: {d: 3, e$: 4 }}
)
// Prints: { a: 1, c: { d: 3, 'e$': 4 } }
console.log(cleaned)
Combine the listed objects into one new object, overwriting properties from right to left.
object... | Object | Any number of parameters that are Objects. |
var Seneca = require('seneca')
var seneca = Seneca()
var extended = seneca.util.deepextend(
{a: 1, b: 2, c: {d: 3, e: 4}},
{a: 10, c: {d: 30, f: 50}, g: 60}
)
// prints { a: 10, c: { d: 30, f: 50, e: 4 }, g: 60, b: 2 }
console.log(extended)
Convert a pattern object into a normalized jsonic String.
object | Object | An object defining a pattern. |
var Seneca = require('seneca')
var seneca = Seneca()
var jsonic_normal_pattern = seneca.util.pattern({
c: 2,
b: 'z',
a: true
})
// Prints: a:true,b:z,c:2
console.log(jsonic_normal_pattern)
Issues? From spelling errors to broken tutorials and everything in between, report them here.