code: function processBatchHeader(state, batch, cb) {
  	if (messageHooks.length === 0) {
  		return cb();
  	}
  
  	var hookData = {};
  	for (var i = 0; i < batch.header.length; i += 1) {
  		var header = batch.header[i];
  		if (header.name) {
  			hookData[header.name] = header;
  		}
  	}
  
  	async.eachSeries(
  		messageHooks,
  		function (hook, cb) {
  			var data = hookData[hook.name];
  
  			if (!data) {
  				// if the hook wasn't mentioned in the RPC call, and it's not required to be executed, ignore it
  				if (!hook.required) {
  					return cb();
  				}
  
  				data = { name: hook.name };
  			}
  
  			hook.fn(state, data, batch, cb);
  		},
  		function (error) {
  			if (error) {
  				// error while handling hooks (probably parse errors)
  
  				return cb(error);
  			}
  
  			// some hooks may have caused mutations (eg: session touch), so distribute these first
  
  			state.archivist.distribute(cb);
  		}
  	);
  }
docs: Calls all message hooks required for a batch.
  
  @param {State}    state                MAGE state object.
  @param {Object}   batch                Command batch object.
  @param {Object}   batch.app            The app object that this batch is for (hooks can filter on app.name).
  @param {string}   batch.rawData        The raw request data (may be useful for hashing).
  @param {Object[]} batch.header         Array of header objects that will be passed to message hook functions.
  @param {Object[]} batch.commands       Array of command objects { name: str, params: Object }
  @param {string[]} batch.commandNames   Array of all command names in the batch, in order.
  @param {Function} cb                   Callback on completion.