nats-hemera
Advanced tools
Comparing version 5.0.0-rc.2 to 5.0.0-rc.3
@@ -53,3 +53,3 @@ const Joi = require('joi') | ||
.default('insertion'), | ||
// Checks if the pattern is no duplicate based on to the indexing strategy | ||
// Checks if the pattern is no duplicate depends on the indexing strategy | ||
lookupBeforeAdd: Joi.boolean().default(false) | ||
@@ -60,3 +60,3 @@ }) | ||
.keys({ | ||
// Check on every request (server) if the load policy was observed, | ||
// Check on every request (server) if the load policy has changed | ||
checkPolicy: Joi.boolean().default(true), | ||
@@ -63,0 +63,0 @@ process: Joi.object() |
@@ -17,3 +17,2 @@ 'use strict' | ||
const TimeoutError = HemeraError.subclass('TimeoutError') | ||
const ImplementationError = HemeraError.subclass('ImplementationError') | ||
const BusinessError = HemeraError.subclass('BusinessError') | ||
@@ -23,3 +22,2 @@ const PatternNotFound = HemeraError.subclass('PatternNotFound') | ||
const ProcessLoadError = HemeraError.subclass('ProcessLoadError') | ||
const CircuitBreakerError = HemeraError.subclass('CircuitBreakerError') | ||
@@ -31,7 +29,5 @@ module.exports = { | ||
TimeoutError, | ||
ImplementationError, | ||
BusinessError, | ||
PatternNotFound, | ||
ProcessLoadError, | ||
CircuitBreakerError | ||
ProcessLoadError | ||
} |
@@ -12,3 +12,2 @@ 'use strict' | ||
const Constants = require('./constants') | ||
const Errors = require('./errors') | ||
@@ -46,3 +45,3 @@ | ||
if (this._types.indexOf(type) === -1) { | ||
let error = new Errors.HemeraError(Constants.INVALID_EXTENSION, { | ||
let error = new Errors.HemeraError('Extension type is unknown', { | ||
type, | ||
@@ -49,0 +48,0 @@ handler |
@@ -13,3 +13,2 @@ 'use strict' | ||
const Util = require('./util') | ||
const Constants = require('./constants') | ||
const Errors = require('./errors') | ||
@@ -41,4 +40,4 @@ | ||
context.trace$ = { | ||
spanId: pattern.trace$.spanId || Util.randomId(), | ||
traceId: pattern.trace$.traceId || Util.randomId() | ||
spanId: pattern.trace$.spanId || context._idGenerator(), | ||
traceId: pattern.trace$.traceId || context._idGenerator() | ||
} | ||
@@ -49,4 +48,4 @@ context.trace$.parentSpanId = | ||
context.trace$ = { | ||
spanId: parentContext.trace$.spanId || Util.randomId(), | ||
traceId: parentContext.trace$.traceId || Util.randomId() | ||
spanId: parentContext.trace$.spanId || context._idGenerator(), | ||
traceId: parentContext.trace$.traceId || context._idGenerator() | ||
} | ||
@@ -83,8 +82,5 @@ context.trace$.parentSpanId = parentContext.trace$.spanId | ||
let request = { | ||
id: pattern.requestId$ || Util.randomId(), | ||
id: pattern.requestId$ || context._idGenerator(), | ||
parentId: context.request$.id || pattern.requestParentId$, | ||
type: | ||
pattern.pubsub$ === true | ||
? Constants.REQUEST_TYPE_PUBSUB | ||
: Constants.REQUEST_TYPE_REQUEST | ||
type: pattern.pubsub$ === true ? 'pubsub' : 'request' | ||
} | ||
@@ -221,3 +217,2 @@ | ||
if (error) { | ||
context._shouldCrash = context._config.load.shouldCrash | ||
return next(new Errors.ProcessLoadError(error.message, error.data)) | ||
@@ -224,0 +219,0 @@ } |
199
lib/index.js
@@ -27,3 +27,2 @@ /** | ||
const Errors = require('./errors') | ||
const Constants = require('./constants') | ||
const Symbols = require('./symbols') | ||
@@ -45,2 +44,9 @@ const Util = require('./util') | ||
const natsConnCodes = [ | ||
NATS.CONN_ERR, | ||
NATS.SECURE_CONN_REQ, | ||
NATS.NON_SECURE_CONN_REQ, | ||
NATS.CLIENT_CERT_REQ | ||
] | ||
/** | ||
@@ -73,3 +79,3 @@ * @class Hemera | ||
}) | ||
this._topics = {} | ||
this._topics = new Map() | ||
@@ -84,7 +90,8 @@ // special variables for the new execution context | ||
parentId: '', | ||
type: Constants.REQUEST_TYPE_REQUEST, | ||
type: 'request', | ||
id: '' | ||
} | ||
// client and server locales | ||
this.matchedAction = null | ||
this._topic = '' | ||
@@ -98,4 +105,2 @@ this._request = null | ||
this.matchedAction = null | ||
this._clientEncoder = DefaultEncoder.encode | ||
@@ -106,2 +111,3 @@ this._clientDecoder = DefaultDecoder.decode | ||
this._schemaCompiler = null | ||
this._idGenerator = Util.randomId | ||
@@ -183,3 +189,3 @@ // errio settings | ||
if (prop in this) { | ||
throw new Errors.HemeraError(Constants.DECORATION_ALREADY_DEFINED) | ||
throw new Errors.HemeraError(`Decorator '${prop}' is already defined`) | ||
} | ||
@@ -246,3 +252,16 @@ | ||
*/ | ||
setIdGenerator(fn) { | ||
if (typeof fn !== 'function') { | ||
throw new Errors.HemeraError(`IdGenerator must be a function`) | ||
} | ||
this._idGenerator = fn | ||
} | ||
/** | ||
* | ||
* @param {*} fn | ||
*/ | ||
setServerDecoder(fn) { | ||
if (typeof fn !== 'function') { | ||
throw new Errors.HemeraError(`ServerDecoder must be a function`) | ||
} | ||
this._serverDecoder = fn | ||
@@ -256,2 +275,5 @@ } | ||
setServerEncoder(fn) { | ||
if (typeof fn !== 'function') { | ||
throw new Errors.HemeraError(`ServerEncoder must be a function`) | ||
} | ||
this._serverEncoder = fn | ||
@@ -264,2 +286,5 @@ } | ||
setClientDecoder(fn) { | ||
if (typeof fn !== 'function') { | ||
throw new Errors.HemeraError(`ClientDecoder must be a function`) | ||
} | ||
this._clientDecoder = fn | ||
@@ -273,2 +298,5 @@ } | ||
setClientEncoder(fn) { | ||
if (typeof fn !== 'function') { | ||
throw new Errors.HemeraError(`ClientEncoder must be a function`) | ||
} | ||
this._clientEncoder = fn | ||
@@ -375,2 +403,6 @@ } | ||
static createError(name) { | ||
if (typeof name !== 'string') { | ||
throw new Errors.HemeraError(`Error name must be a string`) | ||
} | ||
const ctor = SuperError.subclass(name) | ||
@@ -402,7 +434,3 @@ // Register the class with Errio. | ||
if (typeof handler !== 'function') { | ||
let error = new Errors.HemeraError(Constants.INVALID_EXTENSION_HANDLER, { | ||
type, | ||
handler | ||
}) | ||
throw error | ||
throw new Errors.HemeraError('Extension handler must be a function') | ||
} | ||
@@ -424,2 +452,5 @@ | ||
setSchemaCompiler(fn) { | ||
if (typeof fn !== 'function') { | ||
throw new Errors.HemeraError('SchemaCompiler handler must be a function') | ||
} | ||
this._schemaCompiler = fn | ||
@@ -459,3 +490,3 @@ } | ||
if (prop in this) { | ||
throw new Errors.HemeraError(Constants.DECORATION_ALREADY_DEFINED) | ||
throw new Errors.HemeraError('Decoration has been already added') | ||
} | ||
@@ -478,4 +509,6 @@ | ||
for (var i = 0; i < deps.length; i++) { | ||
if (!(deps in this)) { | ||
throw new Error(Constants.MISSING_DECORATE_DEPENDENCY) | ||
if (!(deps[i] in this)) { | ||
throw new Errors.HemeraError( | ||
`Missing decorator dependency '${deps[i]}'` | ||
) | ||
} | ||
@@ -496,3 +529,5 @@ } | ||
if (!Array.isArray(dependencies)) { | ||
throw new Error(Constants.PLUGIN_DEP_STRINGS) | ||
throw new Errors.HemeraError( | ||
'Plugin dependencies must be an array of strings' | ||
) | ||
} | ||
@@ -502,3 +537,5 @@ | ||
if (this[Symbols.registeredPlugins].indexOf(dependency) === -1) { | ||
throw new Error(`The dependency '${dependency}' is not registered`) | ||
throw new Errors.HemeraError( | ||
`The dependency '${dependency}' is not registered` | ||
) | ||
} | ||
@@ -551,3 +588,3 @@ }) | ||
this._transport.driver.on('error', err => { | ||
this.log.error(err, Constants.NATS_TRANSPORT_ERROR) | ||
this.log.error(err, 'Could not connect to NATS!') | ||
this.log.error("NATS Code: '%s', Message: %s", err.code, err.message) | ||
@@ -557,3 +594,3 @@ | ||
// Authorization and protocol issues don't lead to process termination | ||
if (Constants.NATS_CONN_ERROR_CODES.indexOf(err.code) > -1) { | ||
if (natsConnCodes.indexOf(err.code) > -1) { | ||
// We have no NATS connection and can only gracefully shutdown hemera | ||
@@ -565,19 +602,19 @@ this.close() | ||
this._transport.driver.on('permission_error', err => { | ||
this.log.error(err, Constants.NATS_PERMISSION_ERROR) | ||
this.log.error(err, 'NATS permission error') | ||
}) | ||
this._transport.driver.on('reconnect', () => { | ||
this.log.info(Constants.NATS_TRANSPORT_RECONNECTED) | ||
this.log.info('NATS reconnected!') | ||
}) | ||
this._transport.driver.on('reconnecting', () => { | ||
this.log.warn(Constants.NATS_TRANSPORT_RECONNECTING) | ||
this.log.warn('NATS reconnecting ...') | ||
}) | ||
this._transport.driver.on('disconnect', () => { | ||
this.log.warn(Constants.NATS_TRANSPORT_DISCONNECTED) | ||
this.log.warn('NATS disconnected!') | ||
}) | ||
this._transport.driver.on('close', () => { | ||
this.log.warn(Constants.NATS_TRANSPORT_CLOSED) | ||
this.log.warn('NATS connection closed!') | ||
}) | ||
@@ -587,7 +624,7 @@ | ||
if (this._transport.driver.connected) { | ||
this.log.info(Constants.NATS_TRANSPORT_CONNECTED) | ||
this.log.info('Connected!') | ||
this.bootstrap(cb) | ||
} else { | ||
this._transport.driver.on('connect', () => { | ||
this.log.info(Constants.NATS_TRANSPORT_CONNECTED) | ||
this.log.info('Connected!') | ||
this.bootstrap(cb) | ||
@@ -683,7 +720,7 @@ }) | ||
const pubsub = addDefinition.transport.pubsub | ||
const queueGroup = queue || `${Constants.NATS_QUEUEGROUP_PREFIX}.${topic}` | ||
const queueGroup = queue || `queue.${topic}` | ||
// avoid duplicate subscribers of the emit stream | ||
// we use one subscriber per topic | ||
if (self._topics[topic]) { | ||
if (self._topics.has(topic)) { | ||
return | ||
@@ -720,18 +757,24 @@ } | ||
if (pubsub) { | ||
self._topics[topic] = self._transport.subscribe( | ||
self._topics.set( | ||
topic, | ||
{ | ||
max: maxMessages | ||
}, | ||
handler | ||
self._transport.subscribe( | ||
topic, | ||
{ | ||
max: maxMessages | ||
}, | ||
handler | ||
) | ||
) | ||
} else { | ||
// queue group names allow load balancing of services | ||
self._topics[topic] = self._transport.subscribe( | ||
self._topics.set( | ||
topic, | ||
{ | ||
queue: queueGroup, | ||
max: maxMessages | ||
}, | ||
handler | ||
self._transport.subscribe( | ||
topic, | ||
{ | ||
queue: queueGroup, | ||
max: maxMessages | ||
}, | ||
handler | ||
) | ||
) | ||
@@ -752,3 +795,3 @@ } | ||
const internalError = new Errors.HemeraError( | ||
Constants.EXTENSION_ERROR, | ||
'onServerPreRequest extension', | ||
self.errorDetails | ||
@@ -777,3 +820,3 @@ ).causedBy(extensionError) | ||
const internalError = new Errors.PatternNotFound( | ||
Constants.PATTERN_NOT_FOUND, | ||
'No action found for this pattern', | ||
self.errorDetails | ||
@@ -798,3 +841,3 @@ ) | ||
const internalError = new Errors.HemeraError( | ||
Constants.EXTENSION_ERROR, | ||
'onServerPreHandler extension', | ||
self.errorDetails | ||
@@ -814,3 +857,3 @@ ).causedBy(extensionError) | ||
const internalError = new Errors.HemeraError( | ||
Constants.ADD_MIDDLEWARE_ERROR, | ||
'Action middleware', | ||
self.errorDetails | ||
@@ -825,5 +868,3 @@ ).causedBy(err) | ||
// if request type is 'pubsub' we don't have to reply back | ||
if ( | ||
self._request.payload.request.type === Constants.REQUEST_TYPE_PUBSUB | ||
) { | ||
if (self._request.payload.request.type === 'pubsub') { | ||
action(self._request.payload.pattern) | ||
@@ -858,5 +899,3 @@ self.reply.send() | ||
if (!topic) { | ||
let error = new Errors.HemeraError( | ||
Constants.TOPIC_SID_REQUIRED_FOR_DELETION | ||
) | ||
let error = new Errors.HemeraError('The sid or topic name is required') | ||
self.log.error(error) | ||
@@ -869,3 +908,3 @@ throw error | ||
// when topic name was passed | ||
const subId = self._topics[topic] | ||
const subId = self._topics.get(topic) | ||
@@ -894,3 +933,3 @@ if (subId) { | ||
// release topic so we can add it again | ||
delete this._topics[topic] | ||
delete this._topics.delete(topic) | ||
// remove pattern which belongs to the topic | ||
@@ -914,3 +953,3 @@ this.list().forEach(add => { | ||
if (!definition) { | ||
let error = new Errors.HemeraError(Constants.ADD_PATTERN_REQUIRED) | ||
let error = new Errors.HemeraError('Pattern is required') | ||
this.log.error(error) | ||
@@ -927,6 +966,9 @@ throw error | ||
if (!definition.topic) { | ||
let error = new Errors.HemeraError(Constants.NO_TOPIC_TO_SUBSCRIBE, { | ||
definition, | ||
app: this._config.name | ||
}) | ||
let error = new Errors.HemeraError( | ||
'Topic must not be empty and from type string', | ||
{ | ||
definition, | ||
app: this._config.name | ||
} | ||
) | ||
@@ -967,3 +1009,3 @@ this.log.error(error) | ||
if (this._config.bloomrun.lookupBeforeAdd && handler) { | ||
let error = new Errors.HemeraError(Constants.PATTERN_ALREADY_IN_USE, { | ||
let error = new Errors.HemeraError('Pattern is already in use', { | ||
pattern: addDefinition.pattern | ||
@@ -987,7 +1029,9 @@ }) | ||
this.log.error( | ||
Constants.TRANSPORT_OPTIONS_DIFFER_DESC, | ||
'Could not register pattern "%s" because pattern "%s" has different transport configuration but the same topic. Please use a different topic name!', | ||
Util.pattern(addDefinition.pattern), | ||
Util.pattern(def.pattern) | ||
) | ||
throw new Errors.HemeraError(Constants.TRANSPORT_OPTIONS_DIFFER) | ||
throw new Errors.HemeraError( | ||
'Transport options differs from the first registration of this topic' | ||
) | ||
} | ||
@@ -998,3 +1042,3 @@ | ||
this.log.info(patternOnly, Constants.ADD_ADDED) | ||
this.log.info(patternOnly, 'Server action added') | ||
@@ -1096,3 +1140,3 @@ this.subscribe(addDefinition) | ||
let internalError = new Errors.ParseError( | ||
Constants.PAYLOAD_PARSING_ERROR, | ||
'Client payload decoding', | ||
self.errorDetails | ||
@@ -1126,3 +1170,3 @@ ).causedBy(self._response.error) | ||
const internalError = new Errors.HemeraError( | ||
Constants.EXTENSION_ERROR, | ||
'onClientPostRequest extension', | ||
self.errorDetails | ||
@@ -1139,3 +1183,3 @@ ).causedBy(extensionError) | ||
const internalError = new Errors.BusinessError( | ||
Constants.BUSINESS_ERROR, | ||
'An business error was received', | ||
self.errorDetails | ||
@@ -1163,3 +1207,3 @@ ).causedBy(error) | ||
if (!pattern) { | ||
let error = new Errors.HemeraError(Constants.ACT_PATTERN_REQUIRED) | ||
let error = new Errors.HemeraError('Pattern is required') | ||
this.log.error(error) | ||
@@ -1189,3 +1233,3 @@ throw error | ||
let error = new Errors.HemeraError( | ||
Constants.NO_TOPIC_TO_REQUEST, | ||
'Topic must not be empty and from type string', | ||
hemera.errorDetails | ||
@@ -1204,3 +1248,3 @@ ) | ||
hemera._extensionManager['onClientPreRequest'], | ||
err => hemera._onPreRequestCompleted(err) | ||
err => hemera._onClientPreRequestCompleted(err) | ||
) | ||
@@ -1222,3 +1266,3 @@ } else { | ||
hemera._extensionManager['onClientPreRequest'], | ||
err => hemera._onPreRequestCompleted(err) | ||
err => hemera._onClientPreRequestCompleted(err) | ||
) | ||
@@ -1258,3 +1302,3 @@ | ||
*/ | ||
_onPreRequestCompleted(err) { | ||
_onClientPreRequestCompleted(err) { | ||
const self = this | ||
@@ -1265,5 +1309,5 @@ let m = self._clientEncoder(self._message) | ||
if (m.error) { | ||
let error = new Errors.ParseError( | ||
Constants.PAYLOAD_PARSING_ERROR | ||
).causedBy(m.error) | ||
let error = new Errors.ParseError('Client payload encoding').causedBy( | ||
m.error | ||
) | ||
self.log.error(error) | ||
@@ -1278,3 +1322,3 @@ self.emit('clientResponseError', m.error) | ||
const internalError = new Errors.HemeraError( | ||
Constants.EXTENSION_ERROR | ||
'onClientPreRequest extension' | ||
).causedBy(err) | ||
@@ -1353,6 +1397,3 @@ self.log.error(internalError) | ||
const error = new Errors.TimeoutError( | ||
Constants.ACT_TIMEOUT_ERROR, | ||
self.errorDetails | ||
) | ||
const error = new Errors.TimeoutError('Client timeout', self.errorDetails) | ||
self.log.error(error) | ||
@@ -1382,3 +1423,3 @@ self._response.error = error | ||
const internalError = new Errors.HemeraError( | ||
Constants.EXTENSION_ERROR | ||
'onClientPostRequest extension' | ||
).causedBy(err) | ||
@@ -1424,4 +1465,4 @@ self.log.error(internalError) | ||
removeAll() { | ||
for (const key in this._topics) { | ||
this.remove(key) | ||
for (var topic of this._topics.keys()) { | ||
this.remove(topic) | ||
} | ||
@@ -1428,0 +1469,0 @@ } |
@@ -13,3 +13,2 @@ 'use strict' | ||
const Errors = require('./errors') | ||
const Constants = require('./constants') | ||
const Errio = require('errio') | ||
@@ -100,3 +99,3 @@ | ||
if (self.sent) { | ||
self.log.warn(new Error(Constants.REPLY_ALREADY_SENT)) | ||
self.log.warn(new Errors.HemeraError('Reply already sent')) | ||
return | ||
@@ -156,3 +155,3 @@ } | ||
const internalError = new Errors.HemeraError( | ||
Constants.EXTENSION_ERROR, | ||
'onServerPreResponse extension', | ||
self.hemera.errorDetails | ||
@@ -196,3 +195,3 @@ ).causedBy(extensionError) | ||
let internalError = new Errors.ParseError( | ||
Constants.PAYLOAD_PARSING_ERROR | ||
'Server payload encoding' | ||
).causedBy(msg.error) | ||
@@ -199,0 +198,0 @@ self.log.error(internalError) |
{ | ||
"name": "nats-hemera", | ||
"author": "Dustin Deus (https://github.com/StarpTech)", | ||
"version": "5.0.0-rc.2", | ||
"version": "5.0.0-rc.3", | ||
"main": "lib/index.js", | ||
@@ -6,0 +6,0 @@ "homepage": "https://hemerajs.github.io/hemera/", |
66358
20
2672