First commit
This commit is contained in:
161
node_modules/ldapjs/lib/client/message-tracker/index.js
generated
vendored
Normal file
161
node_modules/ldapjs/lib/client/message-tracker/index.js
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
'use strict'
|
||||
|
||||
const idGeneratorFactory = require('./id-generator')
|
||||
const purgeAbandoned = require('./purge-abandoned')
|
||||
|
||||
/**
|
||||
* Returns a message tracker object that keeps track of which message
|
||||
* identifiers correspond to which message handlers. Also handles keeping track
|
||||
* of abandoned messages.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {string} options.id An identifier for the tracker.
|
||||
* @param {object} options.parser An object that will be used to parse messages.
|
||||
*
|
||||
* @returns {MessageTracker}
|
||||
*/
|
||||
module.exports = function messageTrackerFactory (options) {
|
||||
if (Object.prototype.toString.call(options) !== '[object Object]') {
|
||||
throw Error('options object is required')
|
||||
}
|
||||
if (!options.id || typeof options.id !== 'string') {
|
||||
throw Error('options.id string is required')
|
||||
}
|
||||
if (!options.parser || Object.prototype.toString.call(options.parser) !== '[object Object]') {
|
||||
throw Error('options.parser object is required')
|
||||
}
|
||||
|
||||
let currentID = 0
|
||||
const nextID = idGeneratorFactory()
|
||||
const messages = new Map()
|
||||
const abandoned = new Map()
|
||||
|
||||
/**
|
||||
* @typedef {object} MessageTracker
|
||||
* @property {string} id The identifier of the tracker as supplied via the options.
|
||||
* @property {object} parser The parser object given by the the options.
|
||||
*/
|
||||
const tracker = {
|
||||
id: options.id,
|
||||
parser: options.parser
|
||||
}
|
||||
|
||||
/**
|
||||
* Count of messages awaiting response.
|
||||
*
|
||||
* @alias pending
|
||||
* @memberof! MessageTracker#
|
||||
*/
|
||||
Object.defineProperty(tracker, 'pending', {
|
||||
get () {
|
||||
return messages.size
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Move a specific message to the abanded track.
|
||||
*
|
||||
* @param {integer} msgID The identifier for the message to move.
|
||||
*
|
||||
* @memberof MessageTracker
|
||||
* @method abandon
|
||||
*/
|
||||
tracker.abandon = function abandonMessage (msgID) {
|
||||
if (messages.has(msgID) === false) return false
|
||||
const toAbandon = messages.get(msgID)
|
||||
abandoned.set(msgID, {
|
||||
age: currentID,
|
||||
message: toAbandon.message,
|
||||
cb: toAbandon.callback
|
||||
})
|
||||
return messages.delete(msgID)
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {object} Tracked
|
||||
* @property {object} message The tracked message. Usually the outgoing
|
||||
* request object.
|
||||
* @property {Function} callback The handler to use when receiving a
|
||||
* response to the tracked message.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieves the message handler for a message. Removes abandoned messages
|
||||
* that have been given time to be resolved.
|
||||
*
|
||||
* @param {integer} msgID The identifier for the message to get the handler for.
|
||||
*
|
||||
* @memberof MessageTracker
|
||||
* @method fetch
|
||||
*/
|
||||
tracker.fetch = function fetchMessage (msgID) {
|
||||
const tracked = messages.get(msgID)
|
||||
if (tracked) {
|
||||
purgeAbandoned(msgID, abandoned)
|
||||
return tracked
|
||||
}
|
||||
|
||||
// We sent an abandon request but the server either wasn't able to process
|
||||
// it or has not received it yet. Therefore, we received a response for the
|
||||
// abandoned message. So we must return the abandoned message's callback
|
||||
// to be processed normally.
|
||||
const abandonedMsg = abandoned.get(msgID)
|
||||
if (abandonedMsg) {
|
||||
return { message: abandonedMsg, callback: abandonedMsg.cb }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all message tracks, cleans up the abandoned track, and invokes
|
||||
* a callback for each message purged.
|
||||
*
|
||||
* @param {function} cb A function with the signature `(msgID, handler)`.
|
||||
*
|
||||
* @memberof MessageTracker
|
||||
* @method purge
|
||||
*/
|
||||
tracker.purge = function purgeMessages (cb) {
|
||||
messages.forEach((val, key) => {
|
||||
purgeAbandoned(key, abandoned)
|
||||
tracker.remove(key)
|
||||
cb(key, val.callback)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a message from all tracking.
|
||||
*
|
||||
* @param {integer} msgID The identifier for the message to remove from tracking.
|
||||
*
|
||||
* @memberof MessageTracker
|
||||
* @method remove
|
||||
*/
|
||||
tracker.remove = function removeMessage (msgID) {
|
||||
if (messages.delete(msgID) === false) {
|
||||
abandoned.delete(msgID)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a message handler to be tracked.
|
||||
*
|
||||
* @param {object} message The message object to be tracked. This object will
|
||||
* have a new property added to it: `messageId`.
|
||||
* @param {function} callback The handler for the message.
|
||||
*
|
||||
* @memberof MessageTracker
|
||||
* @method track
|
||||
*/
|
||||
tracker.track = function trackMessage (message, callback) {
|
||||
currentID = nextID()
|
||||
// This side effect is not ideal but the client doesn't attach the tracker
|
||||
// to itself until after the `.connect` method has fired. If this can be
|
||||
// refactored later, then we can possibly get rid of this side effect.
|
||||
message.messageId = currentID
|
||||
messages.set(currentID, { callback, message })
|
||||
}
|
||||
|
||||
return tracker
|
||||
}
|
||||
Reference in New Issue
Block a user