<commit_before>
var logger = require('./logging').getLogger(__LOGGER__),
	React = require('react/addons'),
	RequestContext = require('./context/RequestContext'),
	RequestLocalStorage = require('./util/RequestLocalStorage'),
	RLS = RequestLocalStorage.getNamespace(),
	LABString = require('./util/LABString'),
	ClientCssHelper = require('./util/ClientCssHelper'),
	Q = require('q'),
	config = require('./config'),
	ExpressServerRequest = require("./ExpressServerRequest"),
	expressState = require('express-state'),
	cookieParser = require('cookie-parser'),
	PageUtil = require("./util/PageUtil"),
	PromiseUtil = require("./util/PromiseUtil"),
	TritonAgent = require('./util/TritonAgent');


// TODO FIXME ?? 
// It *might* be worthwhile to get rid of all the closure-y things in render()
// https://developers.google.com/speed/articles/optimizing-javascript

var DATA_LOAD_WAIT = 250;

// We'll use this for keeping track of request concurrency per worker.
var ACTIVE_REQUESTS = 0;

/**
 * renderMiddleware entrypoint. Called by express for every request.
 */
module.exports = function(server, routes) {

	expressState.extend(server);

	// parse cookies into req.cookies property
	server.use(cookieParser());

	// sets the namespace that data will be exposed into client-side
	// TODO: express-state doesn't do much for us until we're using a templating library
	server.set('state namespace', '__tritonState');

	server.use((req, res, next) => { RequestLocalStorage.startRequest(() => {
		ACTIVE_REQUESTS++;

		var start = new Date();
		var startHR = process.hrtime();

		logger.debug(`Incoming request for ${req.path}`);

		// Just to keep an eye out for leaks.
		logger.gauge("requestLocalStorageNamespaces", RequestLocalStorage.getCountNamespaces());

		// TODO? pull this context building into its own middleware
		var context = new RequestContext.Builder()
				.setRoutes(routes)
				.setDefaultXhrHeadersFromRequest(req)
				.create({
					// TODO: context opts?
				});

		// This is the default.
		// Can be overridden by the page or middleware.
		context.setDataLoadWait(DATA_LOAD_WAIT)

		// Need this stuff in corvair for logging.
		context.setServerStash({ req, res, start, startHR });

		// setup navigation handler (TODO: should we have a 'once' version?)
		context.onNavigate( (err, page) => {

			if (err) {
				logger.log("onNavigate received a non-2xx HTTP code", err);
				if (err.status && err.status === 404) {
					next();
				} else if (err.status === 301 || err.status === 302) {
					res.redirect(err.status, err.redirectUrl);
				} else {
					next(err);
				}
				handleResponseComplete(page);
				return;
			}

			renderPage(req, res, start, context, page);

		});

		context.navigate(new ExpressServerRequest(req));

	})});
}

function handleResponseComplete(page) {
	logger.gauge(`concurentRequests`, ACTIVE_REQUESTS--);
	if (page) setTimeout(page.handleComplete, 0);
}

function renderPage(req, res, start, context, page) {

	var routeName = context.navigator.getCurrentRoute().name;

	logger.debug("Route Name: " + routeName);

	var renderTimer = logger.timer("renderFunction");

	// regardless of what happens, write out the header part
	// TODO: should this include the common.js file? seems like it
	// would give it a chance to download and parse while we're loading
	// data
	//
	// Each of these functions has the same signature and returns a
	// promise, so we can chain them up with a promise reduction.
	[
		Q(), // This is just a NOOP lead-in to prime the reduction.
		writeHeader,
		startBody,
		writeBody,
		writeData,
		setupLateArrivals,
	].reduce((chain, func) => chain
		.then(() => func(req, res, context, start, page))
		.then(() => renderTimer.tick(func.name))
	).catch(err => {
		logger.error("Error in renderPage chain", err.stack)

		// Bummer.<commit_msg>Commentary in `handleResponseComplete()`<commit_after>
var logger = require('./logging').getLogger(__LOGGER__),
	React = require('react/addons'),
	RequestContext = require('./context/RequestContext'),
	RequestLocalStorage = require('./util/RequestLocalStorage'),
	RLS = RequestLocalStorage.getNamespace(),
	LABString = require('./util/LABString'),
	ClientCssHelper = require('./util/ClientCssHelper'),
	Q = require('q'),
	config = require('./config'),
	ExpressServerRequest = require("./ExpressServerRequest"),
	expressState = require('express-state'),
	cookieParser = require('cookie-parser'),
	PageUtil = require("./util/PageUtil"),
	PromiseUtil = require("./util/PromiseUtil"),
	TritonAgent = require('./util/TritonAgent');


// TODO FIXME ?? 
// It *might* be worthwhile to get rid of all the closure-y things in render()
// https://developers.google.com/speed/articles/optimizing-javascript

var DATA_LOAD_WAIT = 250;

// We'll use this for keeping track of request concurrency per worker.
var ACTIVE_REQUESTS = 0;

/**
 * renderMiddleware entrypoint. Called by express for every request.
 */
module.exports = function(server, routes) {

	expressState.extend(server);

	// parse cookies into req.cookies property
	server.use(cookieParser());

	// sets the namespace that data will be exposed into client-side
	// TODO: express-state doesn't do much for us until we're using a templating library
	server.set('state namespace', '__tritonState');

	server.use((req, res, next) => { RequestLocalStorage.startRequest(() => {
		ACTIVE_REQUESTS++;

		var start = new Date();
		var startHR = process.hrtime();

		logger.debug(`Incoming request for ${req.path}`);

		// Just to keep an eye out for leaks.
		logger.gauge("requestLocalStorageNamespaces", RequestLocalStorage.getCountNamespaces());

		// TODO? pull this context building into its own middleware
		var context = new RequestContext.Builder()
				.setRoutes(routes)
				.setDefaultXhrHeadersFromRequest(req)
				.create({
					// TODO: context opts?
				});

		// This is the default.
		// Can be overridden by the page or middleware.
		context.setDataLoadWait(DATA_LOAD_WAIT)

		// Need this stuff in corvair for logging.
		context.setServerStash({ req, res, start, startHR });

		// setup navigation handler (TODO: should we have a 'once' version?)
		context.onNavigate( (err, page) => {

			if (err) {
				logger.log("onNavigate received a non-2xx HTTP code", err);
				if (err.status && err.status === 404) {
					next();
				} else if (err.status === 301 || err.status === 302) {
					res.redirect(err.status, err.redirectUrl);
				} else {
					next(err);
				}
				handleResponseComplete(page);
				return;
			}

			renderPage(req, res, start, context, page);

		});

		context.navigate(new ExpressServerRequest(req));

	})});
}

function handleResponseComplete(page) {

	// All intentional response completion should funnel through this
	// function.  If this gauge starts climbing gradually that's an
	// indication that we have some _unintentional_ response completion
	// going on that we should deal with.
	logger.gauge(`concurentRequests`, ACTIVE_REQUESTS--);

	// If this was an error response other server middleware might change
	// the response code or send more data (e.g. a nice 404 page), so
	// we'll defer our call to `handleComplete()` until that's done.
	//
	// If error handling middleware is not synchronous we should use
	// something like `on-finished` to hook into the real response end.
	//
	// Note that if the navigator couldn't even map the request to a page,
	// we won't be able to log our request here.
	//
	if (page) {
		setTimeout(page.handleComplete, 0);
	}
}

function renderPage(req, res, start, context, page) {

	var routeName = context.navigator.getCurrentRoute().name;

	logger.debug("Route Name: " + routeName);

	var renderTimer = logger.timer("renderFunction");

	// regardless of what happens, write out the header part
	// TODO: should this include the common.js file? seems like it
	// would give it a chance to download and parse while we're loading
	// data
	//
	// Each of these functions has the same signature and returns a
	// promise, so we can chain them up with a promise reduction.
	[
		Q(), // This is just a NOOP lead-in to prime the reduction.
		writeHeader,
		startBody,
		writeBody,
		writeData,
		setupLateArrivals,
	].reduce((chain, func) => chain
		.then(() => func(req, res, context, start, page))
		.then(() => renderTimer.tick(func.name))
	).catch(err => {
		logger.error("Error in renderPage chain", err.stack)

		// Bummer.
{'fraction_non_alphanumeric': 0.1311730240344374, 'fraction_numerical': 0.003945952409422456, 'mean_word_length': 3.8798133022170362, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7625202', 'n_tokens_mistral': 2699, 'n_tokens_neox': 2438, 'n_words': 782}