Home Reference Source

js-junk-bucket-repo/context.js

/**
 * Provides a construct to attach generic lifecycle events to, such as creation and destruction.
 * @module context
 */

/**
 * @external Logger http://example.com
 */

/**
 * Provides a simple control structure to allow for composition of destruction operation.  The primary intent is to ease
 * the burden of deferrable clean up routines.
 *
 * For example: when creating a temporary directory this may register to cleanup said directory
 */
class Context {
	/**
	 * Creates a new context with the given name and logger.
	 *
	 * @param name the name of the context
	 * @param logger a logger ot use
	 */
	constructor(name, logger){
		/**
		 * The name of the context
		 * @type {string}
		 */
		this.name = name;
		/**
		 * Logger for the specific context.
		 * @type {String}
		 */
		this.logger = logger;
		/**
		 * Callbacks for clean up
		 * @private
		 * @type {Array}
		 */
		this.toCleanup = [];
	}

	/**
	 * Creates a subcontext with the given name.
	 *
	 * @param name {String} the name of the subcontext
	 * @returns {Context} a subcontext registered to be cleaned up in order of registration
	 */
	subcontext( name ){
		const subname = this.name + "/"+ name;
		const newLogger = this.logger.child({subcontext: subname});
		const subcontext = new Context(subname, newLogger);
		this.onCleanup( async function() {
			await subcontext.cleanup();
		});
		return subcontext;
	}

	/**
	 * Registers the given callback to be run when cleaning up this context.
	 *
	 * @param f {Function} a callback to be invoked when cleaning up this module.
	 */
	onCleanup( f ){
		this.toCleanup.unshift(f);
	}

	/**
	 * In reverse order sequentially notifies each callback to cleanup the associated resources.
	 *
	 * @returns {Promise<void>} completes when cleanup is completed
	 */
	async cleanup(){
		for( const f of this.toCleanup ){
			try {
				await f(this);
			}catch( e ){
				this.logger.error("Failed to cleanup", e);
			}
		}
	}
}

module.exports = {
	Context
};