I recently released an update to BlogCFC. One of the fixes includes a performance update that I'd like to detail. It isn't that big of a deal. In fact, I assume most folks will consider it quite obvious when they see it. But I missed it for years and figured it would be good to share. To give you a clue - the issue only came about when I updated to the latest ColdFish and also involved the large number of subscribers I have at the blog here. I had noticed for a while now that whenever I published a blog entry, it took a good 10-15 seconds to go through. Let me show you the code and tell me if you can see the issue:
2 hint="Handles email for the blog.">
3 <cfargument name="entryid" type="uuid" required="true">
4 <cfset var entry = getEntry(arguments.entryid,true)>
5 <cfset var subscribers = getSubscribers(true)>
6 <cfset var theMessage = "">
7 <cfset var mailBody = "">
8
9 <cfloop query="subscribers">
10
11 <cfsavecontent variable="theMessage">
12 <cfoutput>
13 <h2>#entry.title#</h2>
14 <b>URL:</b> <a href="#makeLink(entry.id)#">#makeLink(entry.id)#</a><br />
15 <b>Author:</b> #entry.name#<br />
16
17 #renderEntry(entry.body,false,entry.enclosure)#<cfif len(entry.morebody)>
18 <a href="#makeLink(entry.id)#">[Continued at Blog]</a></cfif>
19
20 <p>
21 You are receiving this email because you have subscribed to this blog.<br />
22 To unsubscribe, please go to this URL:
23 <a href="#getRootURL()#unsubscribe.cfm?email=#email#&token=#token#">#getRootURL()#unsubscribe.cfm?email=#email#&token=#token#</a>
24 </p>
25 </cfoutput>
26 </cfsavecontent>
27
28 <cfif instance.mailserver is "">
29 <cfmail to="#email#" from="#instance.owneremail#" subject="#variables.utils.htmlToPlainText(htmlEditFormat(instance.blogtitle))# / #variables.utils.htmlToPlainText(entry.title)#" type="html">#theMessage#</cfmail>
30 <cfelse>
31 <cfmail to="#email#" from="#instance.owneremail#" subject="#variables.utils.htmlToPlainText(htmlEditFormat(instance.blogtitle))# / #variables.utils.htmlToPlainText(entry.title)#"
32 server="#instance.mailserver#" username="#instance.mailusername#" password="#instance.mailpassword#" type="html">#theMessage#</cfmail>
33 </cfif>
34 </cfloop>
35
36 </cffunction>
2 <cfset var theLink = makeLink(entry.id)>
3 <cfset var rootURL = getRootURL()>
4
5 <cfloop query="subscribers">
6
7 <cfsavecontent variable="theMessage">
8 <cfoutput>
9 <h2>#entry.title#</h2>
10 <b>URL:</b> <a href="#theLink#">#theLink#</a><br />
11 <b>Author:</b> #entry.name#<br />
12
13 #renderedText#<cfif len(entry.morebody)>
14 <a href="#theLink#">[Continued at Blog]</a></cfif>
15
16 <p>
17 You are receiving this email because you have subscribed to this blog.<br />
18 To unsubscribe, please go to this URL:
19 <a href="#rooturl#unsubscribe.cfm?email=#email#&token=#token#">#rooturl#unsubscribe.cfm?email=#email#&token=#token#</a>
20 </p>
21 </cfoutput>
22 </cfsavecontent>


Comment 1 written by Phillip Senn on 1 January 2010, at 10:47 AM
Comment 2 written by Raymond Camden on 1 January 2010, at 11:00 AM
Comment 3 written by Gary Funk on 1 January 2010, at 11:08 AM
<cfset var renderedText = renderEntry(entry.body,false,entry.enclosure)>
<cfset var theLink = makeLink(entry.id)>
<cfset var rootURL = getRootURL()>
<cfsavecontent variable="theMessage">
<cfoutput>
<h2>#entry.title#</h2>
<b>URL:</b> <a href="#theLink#">#theLink#</a><br />
<b>Author:</b> #entry.name#<br />
#renderedText#<cfif len(entry.morebody)>
<a href="#theLink#">[Continued at Blog]</a></cfif>
<p>
You are receiving this email because you have subscribed to this blog.<br />
To unsubscribe, please go to this URL:
<a href="#rooturl#unsubscribe.cfm?email=#email#&token=#token#">#rooturl#unsubscribe.cfm?email=#email#&token=#token#</a>
</p>
</cfoutput>
</cfsavecontent>
<cfloop query="subscribers">
<cfif instance.mailserver is "">
<cfmail to="#email#" from="#instance.owneremail#" subject="#variables.utils.htmlToPlainText(htmlEditFormat(instance.blogtitle))# / #variables.utils.htmlToPlainText(entry.title)#" type="html">#theMessage#</cfmail>
<cfelse>
<cfmail to="#email#" from="#instance.owneremail#" subject="#variables.utils.htmlToPlainText(htmlEditFormat(instance.blogtitle))# / #variables.utils.htmlToPlainText(entry.title)#"
server="#instance.mailserver#" username="#instance.mailusername#" password="#instance.mailpassword#" type="html">#theMessage#</cfmail>
</cfif>
</cfloop>
Comment 4 written by Raymond Camden on 1 January 2010, at 11:10 AM
Comment 5 written by Raymond Camden on 1 January 2010, at 11:10 AM
p.s. Fixing to go to inlaws for a few hours so replies to comments will be delayed.
Comment 6 written by Gary Funk on 1 January 2010, at 11:17 AM
Comment 7 written by Mikkel Johansen on 2 January 2010, at 6:43 AM
Comment 8 written by Raymond Camden on 2 January 2010, at 8:07 AM
Comment 9 written by Steve 'Cutter' Blades on 3 January 2010, at 4:29 PM
<cfset var renderedText = renderEntry(entry.body,false,entry.enclosure)>
<cfset var theLink = makeLink(entry.id)>
<cfset var rootURL = getRootURL()>
<!--- Let's local scope a few more variables --->
<cfset var theMessage = "">
<cfset var tmp = "">
<cfset var attr = StructNew()>
<!--- Then we'll set the mail body content that doesn't change --->
<cfsavecontent variable="theMessage"><cfoutput>
<h2>#entry.title#</h2>
<b>URL:</b> <a href="#theLink#">#theLink#</a><br />
<b>Author:</b> #entry.name#<br />
#renderedText#<cfif len(entry.morebody)>
<a href="#theLink#">[Continued at Blog]</a></cfif>
<p>
You are receiving this email because you have subscribed to this blog.<br />
To unsubscribe, please go to this URL:
</cfoutput></cfsavecontent>
<!--- Then we'll set the mail attributes that come from the instance, as they won't change on each iteration --->
<cfset attr.from = instance.owneremail>
<cfset attr.subject = variables.utils.htmlToPlainText(htmlEditFormat(instance.blogtitle)) & " / " & variables.utils.htmlToPlainText(entry.title)>
<cfset attr.type = "html">
<!--- We'll add the mail server, if we need it --->
<cfif Len(Trim(instance.mailserver))>
<cfset attr.server = instance.mailserver>
<cfset attr.username = instance.mailusername>
<cfset attr.password = instance.mailpassword>
</cfif>
<cfloop query="subscribers">
<cfset attr.to = email>
<!--- Then we'll concantonate our mail body with the subscriber specific info --->
<cfset tmp = theMessage & "<a href='#rooturl#unsubscribe.cfm?email=#email#&token=#token#'>#rooturl#unsubscribe.cfm?email=#email#&token=#token#</a></p>">
<!--- And use the attribute collection for the cfmail tag, mailserver or not --->
<cfmail attributeCollection="#attr#">#tmp#</cfmail>
</cfloop>
Comment 10 written by Gary Funk on 3 January 2010, at 5:29 PM
Comment 11 written by Steve 'Cutter' Blades on 3 January 2010, at 7:39 PM
(Call me Cutter) Yeah, my feed aggregator hadn't gotten all the comments when I wrote the code block. I didn't see that when I posted.
Great minds... ;)
Comment 12 written by Gary Funk on 3 January 2010, at 8:50 PM
Comment 13 written by Raymond Camden on 3 January 2010, at 8:52 PM
Comment 14 written by Gary Funk on 3 January 2010, at 9:30 PM
Comment 15 written by MikeG on 4 January 2010, at 4:21 PM
<cfloop query="subscribers">
That way, when the blog sends email to 3000 subscribers it will still run in about 0 seconds. No need to join them back, just let them run and die
Comment 16 written by Raymond Camden on 4 January 2010, at 4:37 PM
Comment 17 written by MikeG on 4 January 2010, at 5:36 PM
Comment 18 written by Raymond Camden on 4 January 2010, at 5:38 PM
Comment 19 written by Gary Funk on 4 January 2010, at 6:18 PM
Comment 20 written by Raymond Camden on 4 January 2010, at 6:27 PM
Comment 21 written by Gary Funk on 4 January 2010, at 7:36 PM
[Add Comment] [Subscribe to Comments]