Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

Recursive / Nested CFThreads Can Get Around CFSetting RequestTimeout In Lucee CFML 5.3.7.47

By Ben Nadel on
Tags: ColdFusion

A couple of months, I demonstrated that the request timeout of the parent page also affects the execution of CFThread tags in that same request in Lucee CFML. To get around that, within that post, we were using the CFSetting tag to override the requestTimeout value from within the asynchronous thread. In yesterday's post, I started to look at implementing "tail recursion" using CFThread tags in Lucee CFML. Which got me wondering as to how recursive and / or nested CFThread tags would interact with the requestTimeout setting in Lucee CFML 5.3.7.47.

To test this, I created a ColdFusion page with a 2-second request timeout. Then, I spawned two sets of CFThread tags:

  • A "control" thread that will run for 10-seconds which we are expecting to timeout and get interrupted - the "known case", so to speak.

  • A "recursive" thread that will only run for 1-second - less that the requestTimeout value; but, which will call itself 10-times, recursively.

The goal here being to see if the 10-second recursive thread gets interrupted? Or, if it's allowed to finish:

<cfscript>

	// Let's set the overall request timeout to 2-seconds. This affects both the top-
	// level page as well as any asynchronous CFThread tags spawned during this request.
	setting
		requestTimeout = 2
	;

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	// Let's spawn a "control" thread - one that we know will run longer than the
	// designated timeout. We're EXPECTING this thread to timeout and be INTERRUPTED.
	thread
		name = "controlThread"
		cutoffAt = ( getTickCount() + 10000 )
		{

		systemOutput( "Spawning control thread.", true, true );

		while ( getTickCount() < cutoffAt ) {

			sleep( 50 );

		}

		systemOutput( "Control thread completed.", true, true );

	}

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	recurseThread( 10 );

	// Now, let's spawn a series of recursive threads. Each individual thread will run
	// for LESS THAN the request TIMEOUT. However, in aggregate, all of the recursive
	// threads will run for MORE THAN the request timeout.
	public void function recurseThread( required numeric count ) {

		thread
			name = "recursiveThread.#createUniqueId()#"
			count = count
			{

			systemOutput( "Spawning recursive thread for count, #count#.", true, true );
			sleep( 1000 );

			if ( count <= 0 ) {

				systemOutput( "Recursive thread completed.", true, true );
				return;

			}

			recurseThread( count - 1 );

		}

	}

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	echo( "Top-level page done." );

</cfscript>

Now, if we run this ColdFusion code, we get the following terminal output:

Control and Recursive CFThreads being run in a short request timeout in Lucee CFML.

As you can (sort of) see, the "control" CFThread execution is interrupted by the ColdFusion runtime a few seconds after the request is initiated. This is because it exceeded the 2-second requestTimeout setting for the request. The recursive CFThread, on the other hand, is allowed to complete its execution. This is because each invocation of the recursive thread only ran for about 1-second, despite the fact that - in aggregate - the recursive algorithm far exceeded the 2-second requestTimeout setting.

There's nothing too shocking in this post. This exploration is really just laying the ground-work for asynchronous processing that I want to do in Lucee CFML. And, it's important to understand the difference between a "long running algorithm" and a "long running thread"; and how that difference plays-out in terms of request timeouts.



Reader Comments

What has two thumbs and hopes you leave a comment? This Guy! (Ben Nadel).

Post A Comment

You — Get Out Of My Dreams, Get Into My Blog
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.