• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

CFINVOKE behaves badly when combined with CFLOCK

Community Beginner ,
Oct 23, 2012 Oct 23, 2012

Copy link to clipboard

Copied

I am using ColdFusion 9 standard on a 32-bit version Windows Server 2008 virtual machine with 6 GB of RAM.

Since migrating an application from a physical server running CF 8 to this new virtual machine running CF 9, I have experienced a very strange behavior.

I am using the CFINVOKE tag (as a web service) to pull down data.  When the web service code is wrapped in a CFLOCK, the request eventually times out with no response.  It appears that the request is stuck waiting to receive the exclusive lock and the ten second window passes.  If I call the web service directly, bypassing the CFLOCK, the request goes through with no problems.

Why would the combination of these thwo tags cause this problem?

Here is what the code looks like in Application.cfm:

<CFLOCK Name="DataPullIntranet" Type="exclusive" TimeOut="10">

  <CFTRY>

    <CFIF IsDefined("URL.ResetData") or

          Len(Application.MediaTrackerCacheDate) is 0 or

          DateCompare(Now(), Application.MediaTrackerCacheDate, "d") is not 0 or

          Not IsDefined("Application.qHomepageNews")

    >

      <!--- cache frequently used queries --->

      <CFINCLUDE Template="RefreshNews.cfm" />

      <!--- reset cache once a day --->

      <CFSET Application.MediaTrackerCacheDate = Now() />

    </CFIF>

    <!--- likely that lock has timed out, initialize data sets to empty --->

    <CFCATCH>

      <CFSET Application.qHomepageNews = QueryNew("NewsID") />

      <CFSET Application.MediaTrackerCacheDate = Now() />

    </CFCATCH>

  </CFTRY>

</CFLOCK>

Here is the web service code in RefreshNews.cfm:

<!--- cache news --->

<CFINVOKE

  WebService="#Application.MediaTrackerServiceURL#"

  Method="GetNewsForHomepage"

  ReturnVariable="Application.qHomepageNews"

>

  <CFINVOKEARGUMENT Name="Domain" Value="#CGI.Server_Name#" />

</CFINVOKE>

Why would the web service time out when combined with a CFLOCK?  The lock is exclusive, but the data refresh should only be triggered by the first request each day.  The rest of the requests should each receive the exclusive lock one at a time, but bypass all the other code and immediately release the lock.  My server is not pegged at 100%, so it does not seem like there are too many requests waiting to gain the exclusive lock.

Any ideas would be appreciated,

Michael Grove

Views

1.5K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 23, 2012 Oct 23, 2012

Copy link to clipboard

Copied

What is the purpose of the lock?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 23, 2012 Oct 23, 2012

Copy link to clipboard

Copied

The purpose of the lock is to prevent multiple requests from triggering the data refresh at the same time.

Here is a test case:

If 500 requests come in simultaniously at midnight, all 500 will try to trigger the data refresh.  The lock allows the first request to pull the data and the other 499 to wait (10 second timeout).  Once the first request has completed, the other 499 requests will each have their turn with the exclusive lock, but discover that no refresh needs to be done and give up the lock.  I am assuming the other 499 requests release the lock quickly and avoid clogging up the lock queue.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 23, 2012 Oct 23, 2012

Copy link to clipboard

Copied

Wouldn't it be simpler to schedule the data refresh and leave the web applications out of the equation?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 23, 2012 Oct 23, 2012

Copy link to clipboard

Copied

That is a good suggestion, but it does not prevent a situation where one or more requests come in while the scheduled data refresh is taking place.

There is one other complication with the scheduling method, which is more of a personal preference (nitpicking).  If I rely on the scheduled task to refresh the data, I eliminate the possibility of being able to install the application by just dropping the files on a new server.  Making one scheduled task entry is not a big deal, but it has always been safer for me to assume that the person installing the application is not sharp enough to read installation instructions.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 23, 2012 Oct 23, 2012

Copy link to clipboard

Copied

In my experience, if I try to select from a table which is being updated, my select query waits until the update is complete.  That will probably happen irrespective of any cf code you have.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 25, 2012 Oct 25, 2012

Copy link to clipboard

Copied

I will do an experiment with removing the lock and see if I get a different behavior.

I am just not sure how the server will handle multiple requests trying to set an application variable at the same time.

I will posts my results here.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 25, 2012 Oct 25, 2012

Copy link to clipboard

Copied

asdfdsafsdfssdfdfdsad123 wrote:

I am just not sure how the server will handle multiple requests trying to set an application variable at the same time.

Why, that is known already. Each request will, in turn, update the value of the application variable, with or without a lock.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 31, 2012 Oct 31, 2012

Copy link to clipboard

Copied

I have discovered that when I move the lock inside of the <CFIF> statement, my manual refreshes both work properly.

Here is what the code looks like:

<!--- reset data cache once a day --->

<CFTRY>

  <CFIF IsDefined("URL.ResetData") or

        Len(Application.MediaTrackerCacheDate) is 0 or

        DateCompare(Now(), Application.MediaTrackerCacheDate, "d") is not 0 or

        Not IsDefined("Application.qHomepageNews")

  >

    <CFLOCK Name="DataPullIntranet" Type="exclusive" TimeOut="10">

      <!--- cache frequently used queries --->

      <CFINCLUDE Template="#Application.CFMPath#/RefreshNews.cfm" />

    </CFLOCK>

    <!--- reset MediaTracker cache once a day --->

    <CFSET Application.MediaTrackerCacheDate = Now() />

  </CFIF>

  <!--- likely that lock has timedout, initialize data sets to empty --->

  <CFCATCH>

    <CFSET Application.qHomepageNews = QueryNew("NewsID") />

    <CFSET Application.MediaTrackerCacheDate = Now() />

  </CFCATCH>

</CFTRY>

I am curious if the <CFLOCK> is even required at this point.  I will preform another test without the <CFLOCK> to see if the server behaves any differently.

Thanks everyone for the help and suggestions.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 30, 2012 Nov 30, 2012

Copy link to clipboard

Copied

LATEST

I have finished my testing and it appears that using Dan Bracuk's suggestion of scheduling ColdFusion to refresh the data sets does eliminate the problem I was having.  This method fixed the problem because it eliminated the need for the <CFLOCK>, since only one call is made to this routine (instead of relying on the first user request after midnight to trigger the data refresh).

Unfortunately, I ran into one problem with this method.

Occasionally, the server runs its automated maintenance task which installs windows updates.  This usually requires a server restart early in the morning.  In a situation like this the data refresh has already run, but the server restart wipes that out.  So the server starts back up with no cached data, and if not manually corrected, it will not have data until the next scheduled data refresh occurs at midnight the following day.

This situation leads me back to the situation I was having before where I am relying on triggering a refresh based on a user request.  This is not a problem by itself, but it brings me back to the issues with <CFINVOKE> and <CFLOCK>.

On a side note: I am still puzzled by this stalling behavior when these two tags are nested.  I might just have to eliminate the <CFLOCK> tag and accept the fact that some users could potentially get errors for the first few minutes after midnight, because the data refresh has not completed.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 24, 2012 Oct 24, 2012

Copy link to clipboard

Copied

ColdFusion is just doing as it is told. As you yourself say, when subsequent requests arrive at the lock, they will wait until the lock is released. However, some of the variables which determine the conditions for release(Application.qHomepageNews, Application.MediaTrackerCacheDate) are updated within the lock. This results in the lock's timeout exception never being caught.

In my opinion, that update should be done outside the lock. For example, like this

<CFTRY>

<CFLOCK Name="DataPullIntranet" Type="exclusive" TimeOut="10">

    <CFIF IsDefined("URL.ResetData") or

          Len(Application.MediaTrackerCacheDate) is 0 or

          DateCompare(Now(), Application.MediaTrackerCacheDate, "d") is not 0 or

          Not IsDefined("Application.qHomepageNews")

    >

      <!--- cache frequently used queries --->

      <CFINCLUDE Template="RefreshNews.cfm" />

      <!--- reset cache once a day --->

      <CFSET Application.MediaTrackerCacheDate = Now() />

    </CFIF>

</CFLOCK>

<!--- likely that lock has timed out, initialize data sets to empty --->

<CFCATCH>

<CFSET Application.qHomepageNews = QueryNew("NewsID") />

<CFSET Application.MediaTrackerCacheDate = Now() />

</CFCATCH>

</CFTRY>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation