Hello,

I'm getting my feet wet using Async Gateways with CF8, and I have created a loop which calls the gateway X amount of times.
The gateway request then logs the data, however, it is logging X requests, but only the actual data from the last request in the loop. Thus, it's populating the table with duplicate records of the last request X amount of time from the loop.

I may be mistaken, but it seems as though it's sharing the same thread as it is being overwritten with the latest request, rather than creating individual threads for each request.
To the best of my knowledge, I have declared all vars within the cfc method with 'var', except for the query names. Could it be that the query names need to be localized somehow?

Do I need to add something like cfthread? I'm not exactly sure why I'm still getting unreliable results. Some of the code is below.

Any feedback is welcomed!

Thanks,
Ryan

<cfcomponent output="no">
	<cffunction name="scoresummary" returntype="void" output="no">
		<cfargument name="cfevent" required="yes">

		<!---Keeps our position as we search through the response--->
		<cfset var lnIndex = 0>
		
		<!---Begin the index point after the meaningless header content junk by searching for the tag below--->
		<cfset var lcBeginContentStartSearch = '<div class="fctitle">Scoring Summary</div>'>
		<cfset var lcEndContentSearch = "</table>">
		<cfset var lcquarterTRtag = "align=left class=bg1">		
		
		<!---Locates Game Quarters and Overtime--->
		<cfset var summary 	= arraynew(1)>
		<cfset var scores 	= arraynew(2)>
		<cfset var game		= structnew()>
		<cfset var x 		= 0>
		<cfset var y 		= 0>
		<cfset var z		= 1> <!--- Since this code was placed into a gateway, the 'z' incremental loop variable is not needed to store all website requests. Permanently mark as 1. --->
		<cfset var db 		= arguments.cfevent.data>
		<cfset var lccontent = ''>
		<cfset var lnendindex = 0>
		
		<!---Locates anchor tags for extraction--->
		<cfset var lcanchortag = "<a">
		<cfset var lctagend = ">">
		<cfset var lcendtag = "</">
		
		<!---Locates each scoring row--->
		<cfset var lcTRtag = "<tr">
		<cfset var lcendTRtag = "</tr>">
		<cfset var lcTDtag = "<td">
		<cfset var lcTDendtag = "</td>">
		
		<!---Find Starting Point--->
		<cfset var maxloop = 4>
		<cfset var lnnextquarterindexTR = 0>
		<cfset var lnindexTR = 0>
		<cfset var thehttp = ''>
		<cfset var teamid = 0>
		<cfset var sumidx = 0>
		<cfset var score = 0>
		<cfset var extrapoint = 0>
		<cfset var extratype = 0>
		
		<!---Get Request--->
		<!---Get the website content from lcquery above. --->
		<cfhttp 
			result		= "local.thehttp"
			url 		= "http://www.websitename.com/#db.gamename#"
			method 		= "get"
			resolveurl 	= "yes">
		</cfhttp>
		
		<!---Get essential HTML--->
		<cfset lccontent	= local.thehttp.filecontent>
		<cfset lnindex		= findnocase(lcBeginContentStartSearch, lccontent)>
		<cfset lnendindex 	= findnocase(lcendcontentsearch, lccontent, lnindex) + len(lcendcontentsearch)>
		<cfset lccontent	= mid(lccontent, lnindex, lnendindex - lnindex)>
		<cfset db.content	= lccontent>
		
		<cfloop from="1" to="#maxloop#" index="x">
			<cfset lnindexTR			= findnocase(lcquarterTRtag, lccontent, lnindexTR) + len(lcquarterTRtag)>
			<cfif lnindexTR lte 0>
				<cfexit>
			</cfif>
			<cfset lnindex 				= findnocase(db[x]['searchstring'], lcContent, lnindexTR) + len(db[x]['searchstring'])>
			<cfset lnnextquarterindexTR	= findnocase(lcquarterTRtag, lccontent, lnindex) + len(lcquarterTRtag)>
			<cfif lnnextquarterindexTR lt lnindex>
				<cfset lnnextquarterindexTR = len(lccontent)>
			</cfif>
			<cfset lnnextquarterindex	= iif(x eq maxloop, de(len(lccontent)), de(findnocase(db[x + 1]['searchstring'], lcContent, lnnextquarterindexTR)))>
			
			<cfset lnindex 				= findnocase(lctdtag, lccontent, lnindex)>
			<cfset y = 0>
			<cfloop condition="lnindex lt lnnextquarterindexTR">
				<cfset y = y + 1>
				
				<!--- First TD: Scoring Team --->
				<cfset lntempindex 				= findnocase(lctagend, lccontent, lnindex) + len(lctagend)>
				<cfset lnindex					= findnocase(lcendtag, lccontent, lntempindex)>
				<cfset scores[y][1] 			= mid(lccontent, lntempindex, lnindex - lntempindex)>			
				
				<cfif scores[y][1] neq 'None'>
					<cfset lnindex				= findnocase('.gif', lccontent, lntempindex)>
					<cfif lnindex gt 0>
						<cfset scores[y][1] 	= arraytolist(rematchnocase('[A-Za-z]+', mid(lccontent, lnindex - 3, 3)))>
					<cfelse>
						<cfset scores[y][1]		= -1>
					</cfif>
					<!--- Scoring Team ID --->
					<cfif lcase(trim(scores[y][1])) eq lcase(trim(db.hometeam))>
						<cfset teamid			= db.hometeam_id>
					<cfelse>
						<cfset teamid			= db.awayteam_id>
					</cfif>
					<cfset scores[y][11]		= teamid>
					
					<!---Team[#lnindex#]: #scores[y][1]#<br>--->
					
					<!--- Second TD: Type of Score --->
					<cfset lntempindex 			= findnocase(lctdtag, lccontent, lnindex)>
					<cfset lnindex 				= findnocase(lctagend, lccontent, lntempindex) + len(lctagend)>
					<cfset lntempindex			= findnocase(lcendtag, lccontent, lnindex)>
					<cfset scores[y][2] 		= mid(lccontent, lnindex, lntempindex - lnindex)>
					<cfset lnindex				= lntempindex>
					
					<!--- Third TD: Summary of Score --->
					<cfset lntempindex 			= findnocase(lctdtag, lccontent, lnindex)>
					<cfset lnindex 				= findnocase(lctagend, lccontent, lntempindex) + len(lctagend)>
					<cfset lntempindex			= val(findnocase(lcTDendtag, lccontent, lnindex))>
					<!--- Remove all anchor tag data from the summary--->
					<cfset summary 				= mid(lccontent, lnindex, lntempindex - lnindex)>
					<cfset lnindex				= lntempindex>
					<cfset lnsummaryindex		= findnocase(lcanchortag, summary)>
					
					<!---Remove all anchor end tags in summary variable--->
					<cfif lnsummaryindex neq 0>
						<cfset summary			= replacenocase(summary, '</a>', '', 'all')>
					</cfif>
					<cfloop condition="lnsummaryindex neq 0">
						<cfset lcsummaryvalue	= mid(summary, lnsummaryindex, findnocase(lctagend, summary, lnsummaryindex) - lnsummaryindex + 1)>
						<cfset summary			= replacenocase(summary, lcsummaryvalue, '')>
						<cfset lnsummaryindex	= findnocase(lcanchortag, summary)>
					</cfloop>
					
					<!--- yards --->
					<cfset scores[y][3]			= summary>
					<cfset sumidx 				= findnocase(' yards', summary)>
					<cfif sumidx gt 0>
						<cfset scores[y][4]		= trim(mid(summary, sumidx - 2, 2))> 
					<cfelse>
						<cfset scores[y][4] 	= 0>
					</cfif>
					
					<!--- clock time --->
					<cfset sumidx 				= findnocase(':', summary)>
					<cfif sumidx gt 0>
						<cfset scores[y][5]		= trim(mid(summary, sumidx - 2, 5))> 
					<cfelse>
						<cfset scores[y][5] 	= ''>
					</cfif>
					
					<!--- drive time --->
					<cfset sumidx				= findnocase('in ', summary)>
					<cfif sumidx gt 0>
						<cfset scores[y][6]		= trim(mid(summary, sumidx + 2, 5))> 
					<cfelse>
						<cfset scores[y][6] 	= ''>
					</cfif>
					
					<!--- plays --->
					<cfset sumidx 				= findnocase(' plays', summary)>
					<cfif sumidx gt 0>
						<cfset scores[y][7]		= trim(mid(summary, sumidx - 2, 2))> 
					<cfelse>
						<cfset scores[y][7] 	= 0>
					</cfif>
					
					<!--- Points Scored --->
					<cfswitch expression="#scores[y][2]#">
						<cfcase value="TD">
							<cfset score		= 6>
						</cfcase>
						<cfcase value="FG">
							<cfset score		= 3>
						</cfcase>
						<cfcase value="SAFETY">
							<cfset score		= 2>
						</cfcase>
						<cfdefaultcase>
							<cfset score		= 0>
						</cfdefaultcase>
					</cfswitch>
					<cfset scores[y][8]			= score>
					
					<!--- Extra Point(s) and Type of Extra Score --->
					<cfset sumidx 				= findnocase('(', summary) + 1>
					<cfif sumidx gt 1>
						<cfset extrapoint 		= lcase(mid(summary, sumidx, findnocase(')', summary) - sumidx))>
						<cfif findnocase('kick is good', extrapoint)>
							<cfset extrapoint 	= 1>
							<cfset extratype	= 'Kick'>
						<cfelseif findnocase('2 pt. conversion', summary)>
							<cfif findnocase('failed', summary)>
								<cfset extrapoint 	= 0>
							<cfelse>
								<cfset extrapoint	= 2>
							</cfif>
							<cfset extratype	= '2pt Conversion'>
						<cfelse>
							<cfset extrapoint 	= 0>
							<cfset extratype	= ''>
						</cfif>
					<cfelse>
						<cfset extrapoint 		= 0>
						<cfset extratype		= ''>
					</cfif>
					<cfset scores[y][9]			= extrapoint>
					<cfset scores[y][10]		= extratype>
				</cfif>
				
				<cfset lnindex 					= findnocase(lctdtag, lccontent, lnindex)>
				
				<cfif lnindex eq 0>
					<cfbreak>
				</cfif>
			</cfloop>
			
			<cfset db[x]['value'] 			= scores>
			<cfset arrayclear(scores)>
			<cfif lnindexTR lte 0>
				<cfexit>
			</cfif>
		</cfloop>
		<cfset game.game_id						= db.game_id>
		<cfset game.data						= db>
		<cfset ss[z]	 						= game>
		
		<!--- INSERT DATA TO SCORESUMMARY TABLE --->
		<cfif arraylen(ss) gt 0>
			<cftransaction>
			<cfquery name="getscores_#game.game_id#" datasource="datasource">
				SELECT	*
				FROM	scoresummary s
				WHERE	<cfif len(ss[z]['data']['game_id'])>
						s.game_id = #ss[z]['data']['game_id']#
						<cfelse>
						1 = 0
						</cfif>
			</cfquery>
			<cfloop from="1" to="#arraylen(ss)#" index="x">
				<cfloop from="1" to="5" index="y">
					<cfif isarray(ss[x]['data'][y]['value'])>
						<cfloop from="1" to="#arraylen(ss[x]['data'][y]['value'])#" index="z">
							<cfparam name="#ss[x]['data'][y]['value'][z][1]#" default="none">
							<cfif ss[x]['data'][y]['value'][z][1] neq 'none'>
								<cfset timescored = ss[x]['data'][y]['value'][z][5]>
								
								<cfquery name="getscore_#game.game_id#" dbtype="query">
									SELECT	*
									FROM	getscores_#game.game_id#
									WHERE	clock = '#timescored#'
											AND quarter = #val(y)#
								</cfquery>
								
								<cfif variables['getscore_#ss[x]['game_id']#'].recordcount>
									<!--- DO NOT UPDATE FOR NOW BECAUSE THIS MAY SLOW DOWN RENDERING TOO MUCH
									 UPDATE	#scoresummary#
									--->
								<cfelse>
									<cfquery name="insertScoreSummary_#game.game_id#" datasource="datasource">
										INSERT
										INTO	scoresummary (
												game_id,
												team_id,
												team_short,
												score_type,
												points,
												extra_points,
												summary,
												quarter,
												drive_time,
												clock,
												plays,
												yards
										)
										VALUES (
												#ss[x]['game_id']#, 					<!---game ID--->
												#ss[x]['data'][y]['value'][z][11]#,		<!---team ID--->
												'#ss[x]['data'][y]['value'][z][1]#', 	<!---team short--->
												'#ss[x]['data'][y]['value'][z][2]#', 	<!---score type--->
												#ss[x]['data'][y]['value'][z][8]#, 		<!---points--->
												#ss[x]['data'][y]['value'][z][9]#, 		<!---extra points--->
												'#ss[x]['data'][y]['value'][z][3]#', 	<!---summary--->
												'#y#', 									<!---quarter--->
												'#ss[x]['data'][y]['value'][z][6]#', 	<!---drive time--->
												'#ss[x]['data'][y]['value'][z][5]#', 	<!---game clock--->
												#ss[x]['data'][y]['value'][z][7]#, 		<!---plays--->
												#ss[x]['data'][y]['value'][z][4]# 		<!---yards--->
										)
									</cfquery>
								</cfif>
							</cfif>
						</cfloop>
					</cfif>
				</cfloop>
			</cfloop>
			</cftransaction>
		</cfif>
		
	</cffunction>
</cfcomponent>

To be honest, it's actually quite difficult to read the code. Try and break it down into logical segments ( i.e. retrieving data, extracting data, update data ) and it may be easier to track whats done where.
One thing I've asked people to try before is to use <cflog> just prior to the point they are getting the error. This allows them to see the values that the system is expecting to use, which isn't always what they were expecting and they find they've done some minor error.
One thing from coding point of view, you should be using <cfqueryparam> for all of your parameters to any query. This can be both for performance and security reasons ( stops SQL injection for example and annoying problems with quotes in strings! ).

Nige

Hello Nige,

Thank you for the reply.

The code is quite large, sorry for that, and I expected others not to really understand exactly what was going on with it. It's difficult to understand simply because it's a screen-scrape, full of findnocase() functions, and makes it proprietary code. Although, I do believe what you're saying is completely correct, the code actually works fine outside of an event gateway.
I'm attempting to get more of a guidance on the potential problems between the gateway and the code, since the code works outside of the gateway method.

I'm feeling the issue are the declarations of the variables by needing to localize them, and I thought I had localized them all, but it was recently pointed out that i missed a couple, as well as needing to localize the query names, to boot.

With cfqueryparam, I am also a firm believer in that, too. I just hadn't gotten to working it into the query yet. Thanks for noticing it. :-)

I will post the results of the new changes, and hopefully it will work!

Thanks again, Nige. I will attempt to do better with the notations.

This article has been dead for over six months. Start a new discussion instead.