<?xml version="1.0" encoding="utf-8"?>
			
			<rss version="2.0">
			<channel>
			<title>SamSpeak - Web-Applications</title>
			<link>http://sam.curren.ws/index.cfm</link>
			<description>What I Gotta Say</description>
			<language>en-us</language>
			<pubDate>Thu, 09 Sep 2010 02:55:54-0700</pubDate>
			<lastBuildDate>Wed, 17 Mar 2010 08:36:00-0700</lastBuildDate>
			<generator>BlogCFC</generator>
			<docs>http://blogs.law.harvard.edu/tech/rss</docs>
			<managingEditor>telegramsam@byu.edu</managingEditor>
			<webMaster>telegramsam@byu.edu</webMaster>
			
			<item>
				<title>Amazing Things happening at Kynetx - Come to Impact</title>
				<link>http://sam.curren.ws/index.cfm/2010/3/17/Amazing-Things-happening-at-Kynetx--Come-to-Impact</link>
				<description>
				
				Over sushi a few nights ago, I had the opportunity to bring Drummond Reid up to speed with what Kynetx has been doing. After several months in the trenches, it was a revealing experience to climb a tower and see just how far we&apos;ve come. As I unfolded item after item, I was surpised to find another thing to describe.

At our last Impact Conference, we unfolded the Kynetx Engine, and demonstrated some ways to use Kynetx in your quest to do amazing things.

At this next Impact Conference, we will deliver an update on the progress with the engine, the improvement of our tools, and all of the things that have kept us busy over the last few months. If you want to hear about some of the stuff I downloaded to Drummond, you&apos;ll want to attend the conference. If you came to the last Impact, this one will be better. If you didn&apos;t, then it&apos;s time for you to understand what we are doing and what it means for the world.

Oh, and the food will be worth the price of admission alone. Seriously. Sign up for Impact.

&lt;a href=&quot;http://kynetximpactspring2010.eventbrite.com/&quot;&gt;Kynetx Impact Spring 2010&lt;/a&gt;&lt;br/&gt;
April 27-28 2010&lt;br/&gt;
Miller Free Enterprise Center (MFEC)&lt;br/&gt;
at Salt Lake Community College&lt;br/&gt;
9750 South 300 West&lt;br/&gt;
Sandy, UT 84070&lt;br/&gt;

Use Code FOK2010 for a 33% discount on the conference price. 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Development</category>				
				
				<category>Personal</category>				
				
				<category>Technology</category>				
				
				<pubDate>Wed, 17 Mar 2010 08:36:00-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2010/3/17/Amazing-Things-happening-at-Kynetx--Come-to-Impact</guid>
				
			</item>
			
			<item>
				<title>Changing the World at Kynetx</title>
				<link>http://sam.curren.ws/index.cfm/2009/10/20/Changing-the-World-at-Kynetx</link>
				<description>
				
				I&apos;ve been pretty quiet on my blog lately, and I have a really good excuse. Now that I&apos;ve graduated and have time to get involved in some serious endeavors, I&apos;ve joined the folks at &lt;a href=&quot;http://www.kynetx.com&quot;&gt;Kynetx&lt;/a&gt;. I&apos;ve been contributing in their efforts to change the world. Indeed, this does change everything.

&lt;img src=&quot;http://kynetx.com/images/logo.gif&quot;/&gt;

At Kynetx, we believe that experiences can be made better through better use and understanding of context. (&lt;a href=&quot;http://www.gartner.com/it/page.jsp?id=1190313&quot;&gt;Gartner agrees...&lt;/a&gt;) Context is data in time and space: who we are, what we are doing, and what our purpose is. Kynetx has what we call a Context Automation Engine, which does the heavy lifting required to produce intelligent applications. Using our engine, you can create complex applications easily, and deploy them fast.

I&apos;ll take a break now and again from my work to post more info, including examples and more information about what we are doing. If you want to learn more, attend the &lt;A href=&quot;http://kynetximpact.eventbrite.com/&quot;&gt;Kynetx Impact developer conference&lt;/a&gt; Nov 18-19. We will cover our technology and our vision. 

If you are interested in using our platform to add contextual intelligence to your applications, go &lt;a href=&quot;http://kynetximpact.eventbrite.com/&quot;&gt;sign up&lt;/a&gt;. Use code Windley50 for a 50% discount, and I&apos;ll see you there! 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Development</category>				
				
				<category>Personal</category>				
				
				<category>Technology</category>				
				
				<pubDate>Tue, 20 Oct 2009 16:00:00-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2009/10/20/Changing-the-World-at-Kynetx</guid>
				
			</item>
			
			<item>
				<title>Sam Rides 1000: Augmenting the Web</title>
				<link>http://sam.curren.ws/index.cfm/2009/6/30/Sam-Rides-1000-Augmenting-the-Web</link>
				<description>
				
				&lt;p&gt;In my previous two posts, I introduced my project and described data collection using my G1 and Google Spreadsheets. Today, I&apos;m going to show you how I used Kynetx Network Services to add my ride stats to my personal blog and to the Google homepage.&lt;/p&gt;

&lt;h2&gt;Dataset Conversion&lt;/h2&gt;

&lt;p&gt;Google Spreadsheets, where my stats are calculated, can publish data in a variety of formats. It cannot publish JSON data, so I use Yahoo&apos;s YQL to convert the data from CSV to json, with the following statement:&lt;/p&gt;
&lt;code&gt;
select * from csv where url=&apos;http://spreadsheets.google.com/pub?key=rxzHBMZyj1S-HVLy9lFEU7A&amp;single=true&amp;gid=1&amp;range=A12%3AC16&amp;output=csv&apos; and columns=&apos;period,miles,hours&apos; and period != &quot;&quot;
&lt;/code&gt;
&lt;p&gt;(See the &lt;a href=&quot;http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20csv%20where%20url%3D&apos;http%3A%2F%2Fspreadsheets.google.com%2Fpub%3Fkey%3DrxzHBMZyj1S-HVLy9lFEU7A%26single%3Dtrue%26gid%3D1%26range%3DA12%253AC16%26output%3Dcsv&apos;%20and%20columns%3D&apos;period%2Cmiles%2Chours&apos;%20and%20period%20!%3D%20%22%22&amp;format=json&amp;callback=&quot;&gt;raw JSON results&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;Building the App&lt;/h2&gt;

&lt;p&gt;I then build my Kynetx App in &lt;a href=&quot;http://appbuilder.kynetx.com&quot;&gt;AppBuilder&lt;/a&gt;, defining the following datasource in the Global block:&lt;/p&gt;

&lt;code&gt;
dataset ridestats &lt;- &quot;http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20csv%20where%20url%3D&apos;http%3A%2F%2Fspreadsheets.google.com%2Fpub%3Fkey%3DrxzHBMZyj1S-HVLy9lFEU7A%26single%3Dtrue%26gid%3D1%26range%3DA12%253AC16%26output%3Dcsv&apos;%20and%20columns%3D&apos;period%2Cmiles%2Chours&apos;%20and%20period%20!%3D%20%22%22&amp;format=json&amp;callback=&quot; cachable for 2 hours
&lt;/code&gt;

&lt;p&gt;Since I ride in the morning and the evening, I cache the dataset for 2 hours. This keeps the data fairly current, but still keeps the service fast.&lt;/p&gt;

&lt;h2&gt;Annotating My Blog&lt;/h2&gt;

&lt;p&gt;I have two rules, the first of which adds stats to my personal blog:&lt;/p&gt;
&lt;code&gt;
select using &quot;http://sam.curren.ws/&quot; setting ()

pre {
    daymiles = ridestats.pick(&quot;$..results.row[0].miles&quot;);
    weekmiles = ridestats.pick(&quot;$..results.row[1].miles&quot;);
    monthmiles = ridestats.pick(&quot;$..results.row[2].miles&quot;);
    totalmiles = ridestats.pick(&quot;$..results.row[3].miles&quot;);
milesmessage = &lt;&lt;
&lt;h2&gt;Sam is riding 1,000 miles. Progress:
#{(daymiles &gt; 0 ? daymiles + &quot; Today, &quot; : &quot;&quot;)}
#{(weekmiles &gt; 0 &amp;&amp; weekmiles != daymiles ? weekmiles + &quot; This Week, &quot; : &quot;&quot;)}
#{(monthmiles &gt; 0 ? monthmiles + &quot; This Month, &quot; : &quot;&quot;)}
#{totalmiles} Total.&lt;/h2&gt;
&gt;&gt;

}

replace_html(&quot;#logo h2&quot;, milesmessage);
&lt;/code&gt;

&lt;p&gt;I set the rule to fire on my blog&apos;s domain, and then use the pick() method to extract different totals from the json dataset declared in the Global block. I construct a message string that varies depending on the different stat values. Finally, I replace the text at the top of my blog page with the message.&lt;/p&gt;

&lt;p&gt;To run the Kynetx application on my blog, I plant Kynetx tags on my blog. This enables everyone to see the Kynetx Application with no installs or Action Cards. The html tags are available within AppBuilder, and I simply copied them into the template for my blog.&lt;/p&gt;

&lt;h2&gt;Annotating Google&apos;s Homepage&lt;/h2&gt;

&lt;p&gt;My second rule is activated by an Action Card installed on the user&apos;s computer (instructions for installing this are in my first post). My second rule is very similar to the first rule, with some minor difference in inserted HTML and appending the message to the existing site, instead of replacing anything on the page.&lt;/p&gt;

&lt;code&gt;
select using &quot;http://www.google.com/&quot; setting ()

pre {
    daymiles = ridestats.pick(&quot;$..results.row[0].miles&quot;);
    weekmiles = ridestats.pick(&quot;$..results.row[1].miles&quot;);
    monthmiles = ridestats.pick(&quot;$..results.row[2].miles&quot;);
    totalmiles = ridestats.pick(&quot;$..results.row[3].miles&quot;);
milesmessage = &lt;&lt;
&lt;h2&gt;Sam is riding 1,000 miles.&lt;/h2&gt;&lt;p&gt; Progress:
#{(daymiles &gt; 0 ? daymiles + &quot; Today, &quot; : &quot;&quot;)}
#{(weekmiles &gt; 0 &amp;&amp; weekmiles != daymiles ? weekmiles + &quot; This Week, &quot; : &quot;&quot;)}
#{(monthmiles &gt; 0 ? monthmiles + &quot; This Month, &quot; : &quot;&quot;)}
#{totalmiles} Total.&lt;/p&gt;
&gt;&gt;

}

append(&quot;#body&gt;center&quot;, milesmessage);
&lt;/code&gt;

&lt;p&gt;Activating Kynetx Rules with an Action Card also requires an update to the Dispatch block of the rule, adding this line:&lt;/p&gt;

&lt;code&gt;
domain &quot;www.google.com&quot;
&lt;/code&gt;

&lt;p&gt;I also generate the card inside AppBuilder, providing a custom image that I created using &lt;a href=&quot;http://pixlr.com&quot;&gt;Pixlr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you have it. Sam rides 1000 miles, with automated stats provided by Android MyTracks, Google Spreadsheets, YQL, and Kynetx Network Services.&lt;/p&gt;

&lt;h2&gt;Shameless Plug&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.kynetx.com&quot;&gt;Kynetx&lt;/a&gt; is a cloud based automation engine, capable of doing the things I&apos;ve demonstrated and much, much more. If you&apos;d like to use Kynetx Network Services, &lt;a href=&quot;http://accounts.kynetx.com&quot;&gt;sign up for an account&lt;/a&gt;, and start using &lt;a href=&quot;http://appbuilder.kynetx.com&quot;&gt;AppBuilder&lt;/a&gt;. 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Javascript</category>				
				
				<category>Android</category>				
				
				<category>Development</category>				
				
				<category>Personal</category>				
				
				<category>Technology</category>				
				
				<pubDate>Tue, 30 Jun 2009 09:19:00-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2009/6/30/Sam-Rides-1000-Augmenting-the-Web</guid>
				
			</item>
			
			<item>
				<title>Sam Rides 1000: Collecting Ride Data using the Android Powered G1</title>
				<link>http://sam.curren.ws/index.cfm/2009/6/26/Sam-Rides-1000-Collecting-Ride-Data-using-the-Android-Powered-G1</link>
				<description>
				
				&lt;p&gt;On my Android powered T-Mobile G1, I&apos;m using the free &lt;a href=&quot;http://mytracks.appspot.com/&quot;&gt;My Tracks&lt;/a&gt; application to record my rides. I start recording just before I start, then throw it in my pocket or bag. I stop recording at the end of my ride, then use the Upload to Google option in the map menu. You can upload the track to My Maps within Google Maps, but my rides are very similar, so I usually only upload to Google Spreadsheets.&lt;/p&gt;
&lt;img src=&quot;http://mytracks.appspot.com/images/phones_with_all_views.png&quot;/&gt;
&lt;p&gt;Uploading to Google Spreadsheets creates a new spreadsheet in Google Docs, with one page for ride data, and another for stats. The program creates a new spreadsheet for each activity type, so I make sure and select Cycling when I stop recording at the end of my ride.&lt;/p&gt;

&lt;h2&gt;Additional Stats&lt;/h2&gt;

&lt;p&gt;It&apos;s important not to manually change too much on the Log sheet, as the program will get confused, but everything else in the spreadsheet is open to tinkering. In addition to the total miles and total time stats, I wanted to calculate daily, weekly, and monthly totals.&lt;/p&gt;

&lt;p&gt;Before I computed those stats, I had to handle the date field uploaded by the My Tracks application. Google Spreadsheets cannot parse the provided date as a date value, so I had to help it along. I created a Dates sheet to accomplish that task. Rather then try and explain what I did, see this spreadsheet, which contains my modifications and formulas:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://spreadsheets.google.com/ccc?key=rHobEIYHkJxRwJ8_4EuSNtQ&quot;&gt;Sample Spreadsheet with modifications.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I then added some additional stats, first by calculating the start of the date range I wanted to sum, then using SumIf() to only add the mileage and time from the period I wanted.&lt;/p&gt;

&lt;p&gt;Finally, I published the Stats sheet of my spreadsheet, so I could use it as a dataset for my Kynetx Application, which I&apos;ll explain in a future post.&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Android</category>				
				
				<category>Development</category>				
				
				<category>Personal</category>				
				
				<category>Technology</category>				
				
				<pubDate>Fri, 26 Jun 2009 20:06:00-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2009/6/26/Sam-Rides-1000-Collecting-Ride-Data-using-the-Android-Powered-G1</guid>
				
			</item>
			
			<item>
				<title>Sam Rides 1000: An exercise in collecting data and web augmentation</title>
				<link>http://sam.curren.ws/index.cfm/2009/6/26/Sam-Rides-1000-An-exercise-in-collecting-data-and-web-augmentation</link>
				<description>
				
				&lt;p&gt;May 15, 2009 was National Ride your Bike to Work day, and I pulled out my bike and rode the 6 or so miles between my house and the Kynetx offices at Thanksgiving Point. I enjoyed it, and rode a few more times in the next week. I was musing how many miles I could ride this summer, and mentioned it to my wife. She promptly challenged me to ride 1,000 miles this summer.&lt;/p&gt;
&lt;p&gt;I better say here that I&apos;m not a cyclist. I haven&apos;t ridden 1,000 miles in the past 5 years, all combined together. While 1,000 miles might not be much for a cyclist, it is quite the challenge for me.&lt;/p&gt;

&lt;h2&gt;Tracking My Progress&lt;/h2&gt;

&lt;p&gt;In addition to making a few bike repairs and buying some commuting tires for my mountain bike, I immediately cooked up some geeky ways to track my progress and share my results with my family and friends.&lt;/p&gt;
&lt;p&gt;I&apos;m a (BIG) Android fan, and so I&apos;m using my T-Mobile G1 as a cyclometer. I&apos;m using the &lt;a href=&quot;http://mytracks.appspot.com/&quot;&gt;My Tracks&lt;/a&gt; application, which records both the route of my ride and my ride stats. After my ride, the app uploads my stats to a Google Docs Spreadsheet, where stats are calculated. I&apos;ll share more about that in a future post.&lt;/p&gt;
&lt;p&gt;To share my progress, I&apos;m using &lt;a href=&quot;www.kynetx.com&quot;&gt;Kynetx Network Services&lt;/a&gt; (KNS) to augment my personal blog with my stats. If you are reading this post on my blog, look at just under the title for my updated stats. KNS pulls my ride stats from the Google Spreadsheet and annotates my website. All I had to do was plant some javascript tags in my blog&apos;s template to activate the Kynetx Application that makes the change.&lt;/p&gt;
&lt;p&gt;My friends and family don&apos;t visit my blog EVERY day, so I&apos;ve also produced an Action Card that displays my ride stats on Google&apos;s home page. KNS allows me to augment websites for anyone that has my Action Card installed. I&apos;ll explain more about how I wrote my Kynetx Application in a future blog post, but for now, you can install my &quot;Sam Rides 1000&quot; card to track my progress on Google&apos;s home page.&lt;/p&gt;

&lt;h2&gt;Installing The Action Card&lt;/h2&gt;


&lt;img style=&quot;float:right;&quot; src=&quot;http://sam.curren.ws/images/samrides1000.jpg&quot;/&gt;
&lt;p&gt;An Action Card is a type of Information Card that allows your web experience to be augmented with a Kynetx Application. You activate the application by installing an Action Card Selector if you don&apos;t already have one, and then installing the card. You can disable or remove the card if and when you don&apos;t want to use the application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify you have a supported browser: IE/FF on Win, FF on OSX&lt;/li&gt;
&lt;li&gt;Install &lt;a href=&quot;http://www.azigo.com/&quot;&gt;Azigo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install the &lt;a href=&quot;http://misc.curren.ws/sam/files/SamRides1000.crd&quot;&gt;Sam Rides 1000 Action Card&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then, browse to Google&apos;s main page to see my stats: &lt;a href=&quot;http://www.google.com&quot;&gt;http://www.google.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I finish a ride and update my stats, you&apos;ll see the new numbers. If I&apos;m falling behind, be sure and give me a nudge!&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Development</category>				
				
				<category>Android</category>				
				
				<category>Technology</category>				
				
				<pubDate>Fri, 26 Jun 2009 15:42:00-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2009/6/26/Sam-Rides-1000-An-exercise-in-collecting-data-and-web-augmentation</guid>
				
			</item>
			
			<item>
				<title>Trouble with Random Long-Running request in ColdFusion 8</title>
				<link>http://sam.curren.ws/index.cfm/2009/2/10/Trouble-with-Random-LongRunning-request-in-ColdFusion-8</link>
				<description>
				
				I&apos;ve been experiencing some run-time weirdness with ColdFusion for the past year or so, and I&apos;ve finally decided to post my observations and see if anyone else has been having similar troubles.

The trouble shows up on any number of scripts, but is most likely to appear with scripts that are called frequently. The screenshot I&apos;ve included shows a Slow Request report from the ColdFusion Server Monitor. You can see that this request took &lt;b&gt;110 seconds&lt;/b&gt; to complete. The VERY strange part is that the runtime of the Application.cfc onRequest method (the outermost piece of code to run on any request) took only 468ms to complete. So what happened to the &lt;b&gt;109 seconds&lt;/b&gt; that were not spent executing my request? How can I prevent this from happening?

Also observe the Min/Max/Avg response times for the script. At the time of this screenshot, this script had been called 250 times. Multiplying the average response time (.505 seconds) by the request count (250) tells us that this script has occupied 126.25 seconds of server time. Removing this one long running request (250-1, 126.25-110.234) from the statistics, we find the script has an average running time of 0.064 seconds, which is a more reasonable run-time, considering the reported min response time of 0.015 seconds.

Eliminating these random long-running requests will do great things for the usability of the website, as well as free up server resources.

&lt;img src=&quot;http://sam.curren.ws/images/ColdFusionLongRunningRequest.png&quot;&gt;

&lt;h3&gt;Misc Details&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ColdFusion Enterprise 8,0,1,195765&lt;/li&gt;
&lt;li&gt;Monitoring and Profiling Enabled&lt;/li&gt;
&lt;li&gt;Windows 2003&lt;/li&gt;
&lt;li&gt;Java 1.6.0_04&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Summary&lt;/h3&gt;
Scripts will randomly take MUCH longer then they usually do.

There seems to be a massive discrepancy between the Response Time and the Time Taken by the onRequest method.

Why is this happening, and what can be done about it? 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Development</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Tue, 10 Feb 2009 08:01:00-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2009/2/10/Trouble-with-Random-LongRunning-request-in-ColdFusion-8</guid>
				
			</item>
			
			<item>
				<title>Sorting SimpleDB queries on Multiple Attributes</title>
				<link>http://sam.curren.ws/index.cfm/2009/1/12/Sorting-SimpleDB-queries-on-Multiple-Attributes</link>
				<description>
				
				&lt;div class=&quot;zemanta-img&quot; style=&quot;display: block; float: right; margin: 1em; width: 210px&quot;&gt;&lt;a href=&quot;http://www.crunchbase.com/company/amazon&quot;&gt;&lt;img style=&quot;border-right: medium none; border-top: medium none; display: block; border-left: medium none; border-bottom: medium none&quot; height=&quot;89&quot; alt=&quot;Image representing Amazon as depicted in Crunc...&quot; src=&quot;http://www.crunchbase.com/assets/images/resized/0000/3898/3898v1-max-450x450.jpg&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;     &lt;p class=&quot;zemanta-img-attribution&quot; style=&quot;font-size: 0.8em&quot;&gt;Image via &lt;a href=&quot;http://www.crunchbase.com/&quot;&gt;CrunchBase&lt;/a&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;I was recently working with a dataset in Amazon&#xe2;¬"s &lt;a href=&quot;http://aws.amazon.com/simpledb/&quot;&gt;SimpleDB&lt;/a&gt;, and I needed to be able to sort query results on multiple attributes. SimpleDB currently only allows sorting by a single attribute, so I was stuck. The solution is rather simple: combine the columns that I need to sort on into a single new attribute, and use this new composite attribute to perform my sorting. I kept the existing attributes in their current form, but added a new attribute that is the concatenation of the two attributes I wished to sort.&lt;/p&gt;  &lt;p&gt;SimpleDB sorts lexicographically, so concatenating two fields produces exactly the expected results provided you handle a few situations properly. There are a few things to keep in mind as you produce the multi-sort attribute.&lt;/p&gt;  &lt;h3&gt;Properly pad your fields&lt;/h3&gt;  &lt;p&gt;Sorting numbers in SimpleDB requires some encoding to provide the expected results. The SimpleDB documentation provides &lt;a href=&quot;http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?NumericalData.html&quot;&gt;examples of this&lt;/a&gt;. If you have properly encoded your numeric fields, then the length of each attribute will be the same as all the rest. Each values of an attribute must be the same length to provide consistent results.&lt;/p&gt;  &lt;h3&gt;Align the sort order of each field&lt;/h3&gt;  &lt;p&gt;You can only sort your one field one direction; ascending or descending. If you wish to sort column 1 ascending and column 2 descending, then you must reverse the encoding of field 2 prior to &lt;a class=&quot;zem_slink&quot; title=&quot;Concatenation&quot; href=&quot;http://en.wikipedia.org/wiki/Concatenation&quot; rel=&quot;wikipedia&quot;&gt;concatenation&lt;/a&gt;, then sort the combined column ascending. You could also do the reverse: reverse the encoding of field 1, then sort the combined attribute descending.&lt;/p&gt;  &lt;p&gt;The SimpleDB documentation describes encoding numeric values, but this concept applies to both numeric an alphanumeric fields, as long as the length of the attribute value is either the same, or can be padded to be the same.&lt;/p&gt;  &lt;p&gt;Reversed encoding is nothing more then changing the data to be the reverse of what it really is. A single digit number attribute value could be subtracted from a base value, such that 0 becomes 9, 1 becomes 8, and so on. Characters can be reversed as well, turning a into z, b into y, etc. The exact encoding used will depend on the properties of the data being stored.&lt;/p&gt;  &lt;p&gt;Keep in mind that the value of the multi-sort attribute never needs to be parsed or read: it is only used for sorting results. Even if the translation is an ugly one, it only needs to be done on an update.&lt;/p&gt;  &lt;h3&gt;Concatenate attributes in order of sorting preference&lt;/h3&gt;  &lt;p&gt;If you wish to sort on attribute A, then attribute B, followed by C, your combined attribute must be combined in that order, left to right.&lt;/p&gt;  &lt;h3&gt;Flexibility&lt;/h3&gt;  &lt;p&gt;This approach is fairly flexible, including creating a sorting attribute from any number of attributes and creating multiple sorting attributes, as long as the attribute length and number of attributes fall within the &lt;a href=&quot;http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDBLimits.html&quot;&gt;restrictions of SimpleDB&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;While this technique is not new, I wanted to explain it here to provide hints to others with no idea how to solve the problem. Credit for revealing this concept to me go to &lt;a href=&quot;http://www.windley.com/&quot;&gt;Phil Windley&lt;/a&gt;, who told me that the only reason I don&#xe2;¬"t know it already is that I&#xe2;¬"m &#xe2;¬Stoo young&#xe2;¬? to remember a time when most database platforms carried the same restriction. I&#xe2;¬"m just glad to have experienced old guys to learn from. :)&lt;/p&gt;  &lt;div class=&quot;zemanta-pixie&quot; style=&quot;margin-top: 10px; height: 15px&quot;&gt;&lt;img class=&quot;zemanta-pixie-img&quot; style=&quot;border-right: medium none; border-top: medium none; float: right; border-left: medium none; border-bottom: medium none&quot; src=&quot;http://img.zemanta.com/pixy.gif?x-id=ef456dc1-3028-4623-8c75-d6ad76f64a56&quot; /&gt;&lt;/div&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Amazon Web Services</category>				
				
				<category>Development</category>				
				
				<pubDate>Mon, 12 Jan 2009 16:20:10-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2009/1/12/Sorting-SimpleDB-queries-on-Multiple-Attributes</guid>
				
			</item>
			
			<item>
				<title>Really Bad reasons not to auto-scale cloud based systems</title>
				<link>http://sam.curren.ws/index.cfm/2008/12/6/Really-Bad-reasons-not-to-autoscale-cloud-based-systems</link>
				<description>
				
				&lt;p&gt;O&apos;Reilly writer George Reese posted today what I consider to be &lt;a href=&quot;http://broadcast.oreilly.com/2008/12/why-i-dont-like-cloud-auto-scaling.html&quot;&gt;a poor evaluation of the perils of auto-scaling in the cloud&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;He does mention the concept of using a governor to limit the power of the auto-scale agent to spin up servers (and spend money), but his insight ends there. Anyone following cloudy issues will have read &lt;a href=&quot;http://blogs.smugmug.com/don/2008/06/03/skynet-lives-aka-ec2-smugmug/&quot;&gt;Don MacAskill&apos;s excellent post&lt;/a&gt; this past June, where he explains their auto-scale operation, and the need to set limits.&lt;/p&gt;  &lt;p&gt;George also makes a few arguments against auto-scaling, which I&apos;ll address briefly:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;1. Amazon and other clouds cannot respond fast enough to increased capacity needs.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;George claims that a 10 minute instance spin up time cannot respond fast enough to help. This is only true if you start to spin up your service when the existing is already (or nearly) toast. Common strategies involve already having some extra capacity running, so as to not immediately fold under an increase. Solving this problem is just tuning the thresholds.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;2. Got any disgruntled employees, unhappy customers, or malicious competitors?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;George claims that auto-scaling will waste your money in the event of a denial-of-service attack. What he doesn&apos;t mention is that a &lt;a class=&quot;zem_slink&quot; title=&quot;Denial-of-service attack&quot; href=&quot;http://en.wikipedia.org/wiki/Denial-of-service_attack&quot; rel=&quot;wikipedia&quot;&gt;DoS&lt;/a&gt; on a non-auto-scaled system will likely take it down. At the very least, it will artificially inflate your usage anyway, and you will still have to spin up more resources to handle the load. I&apos;d rather spend a few extra bucks and STAY UP.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;3. So you think you&apos;ll stick some governors in place...&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;George&apos;s main claim here is that your governor is likely to be set at the wrong value. Although he doesn&apos;t explicity say, he seems to be implying that a governor can only be used to limit the total number of machines. &lt;a class=&quot;zem_slink&quot; title=&quot;SmugMug&quot; href=&quot;http://www.smugmug.com/&quot; rel=&quot;homepage&quot;&gt;SmugMug&lt;/a&gt; (in the aforelinked post) indicates that their governor limits the rate at which new machines can be started. Using this strategy, only the &lt;em&gt;rate&lt;/em&gt; of traffic growth. &lt;/p&gt;  &lt;p&gt;&lt;em&gt;4. So what about getting slashdotted?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The main complaint here is that an auto-scale agent cannot tell the difference between true traffic growth and a random spike. Clearly, George has never worked with noise filters, which smooth data to reveal real trends. Evaluating load data from the past few minutes will allow agents to ignore spikes easily. Again, this is reduced to tuning thresholds.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;5. Don&apos;t you lose a key value of the cloud without auto-scaling?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Despite George&apos;s claims that no value is lost, there are clear cases where auto-scaling can save your bacon. He claims that &apos;capacity planning&apos; is the clear answer. I agree with him on the importance of capacity planning, but disagree that proper capacity planning eliminates the need to auto-scale. A good auto-scaling system can save quite a lot of money in cloud processing expenses, which will do wonders for the bottom line.&lt;/p&gt;  &lt;h4&gt;Summary&lt;/h4&gt;  &lt;p&gt;I&apos;m not bashing capacity planning here. I believe that capacity planning concepts work very well with auto-scaling, that that proper user of governors and properly set thresholds are the right way to go.&lt;/p&gt;  &lt;p&gt;I rarely respond to lousily written posts and dumb opinions, but this one irked me for some reason. At this point, I have nothing but logic and the experiences of others to rely upon. Over the next few years, I plan on gaining some extensive experience in auto-scaling cloud based systems, and perhaps then I&apos;ll be in a better position to dish a proper smack-down.&lt;/p&gt;  &lt;div class=&quot;zemanta-pixie&quot; style=&quot;margin-top: 10px; height: 15px&quot;&gt;&lt;img class=&quot;zemanta-pixie-img&quot; style=&quot;border-right: medium none; border-top: medium none; float: right; border-left: medium none; border-bottom: medium none&quot; src=&quot;http://img.zemanta.com/pixy.gif?x-id=43680409-4a62-4fc6-9626-f5ba611dcd26&quot; /&gt;&lt;/div&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Amazon Web Services</category>				
				
				<category>Development</category>				
				
				<category>Technology</category>				
				
				<pubDate>Sat, 06 Dec 2008 19:26:57-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/12/6/Really-Bad-reasons-not-to-autoscale-cloud-based-systems</guid>
				
			</item>
			
			<item>
				<title>Planning Ahead: Resilient Load Variations in Distributed Stream Processing</title>
				<link>http://sam.curren.ws/index.cfm/2008/12/2/Planning-Ahead-Resilient-Load-Variations-in-Distributed-Stream-Processing</link>
				<description>
				
				&lt;p&gt;&lt;em&gt;This post is part of a series of posts relating to distributed system design that I&apos;m completing as part of my Computer Science MS program at BYU. &lt;/em&gt;&lt;/p&gt;  &lt;h2&gt;Background&lt;/h2&gt;  &lt;p&gt;Stream processing systems are used to process data and provide low latency data derived from source streams. Good examples of this processing include stock market updates, highway traffic data, and network traffic analysis. Stream processing systems take a stream of data and run it through a series of operations. Most of these operations perform data conversions or calculations/reductions of the source data. The final result is either a new data stream or an updated data set.&lt;/p&gt;  &lt;p&gt;Small stream processing operations usually operate on a single machine. When the load grows beyond the power of the host machine, the stream processing operations must be distributed between several machines. Adding processing power enables the system to maintain low-latency processing. This latency is the time that data takes to travel from system input to system output. The task of dividing the processing operations onto multiple machines is difficult, particularly in situations with variable load. &lt;/p&gt;  &lt;p&gt;Early &lt;a class=&quot;zem_slink&quot; title=&quot;Distributed computing&quot; href=&quot;http://en.wikipedia.org/wiki/Distributed_computing&quot; rel=&quot;wikipedia&quot;&gt;distributed systems&lt;/a&gt; were managed manually, and changes to the operator spread were difficult and often required downtime. Research into dynamic operator distribution allowed systems to move operators between machines to evenly distribute the processing load in response to changing load.&lt;/p&gt;  &lt;h2&gt;Research&lt;/h2&gt;  &lt;p&gt;In a 2006 paper titled &amp;quot;Providing Resiliency to Load Variations in Distributed Stream Processing&amp;quot; (&lt;a href=&quot;http://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fwww.cs.brown.edu%2Fresearch%2Fdb%2Fpublications%2Fvldb06_yx.pdf&amp;amp;ei=oxQ2SbXDLIyi8QSHx_D3Bw&amp;amp;usg=AFQjCNFKpICq1le8z1z9JNjMSReQ13ltIg&amp;amp;sig2=Wtm2cqpn2RbX_QV0M4VC7Q&quot;&gt;pdf&lt;/a&gt;), Ying Xing et. al. describe a new approach to handling variable load.&lt;/p&gt;  &lt;p&gt;They observe that the cost of moving operators in a dynamic distribution system is very high. They outline a process of choosing an initial operator distribution such that the range of manageable load scenarios is maximized. This reduces the need to migrate operations between machines in a system. By maximizing the range of load that a system is capable of handling, they can reduce and possibly eliminate the need to support dynamic operator migration.&lt;/p&gt;  &lt;p&gt;First, they begin by modeling the operators present in the distributed processing system, and then evaluate different methods of choosing the optimal distribution. In addition to reporting the optimal distribution, their method reports on the range of load that they system can handle without operator migration.&lt;/p&gt;  &lt;p&gt;While their work is designed to reduce the need to migrate operators, they explain that their algorithms cooperate well with dynamic systems. By choosing an initial distribution resilient to load variation, they reduce the need to perform expensive operator migrations. When a migration is needed, these algorithms can be used to recommend the distribution most resilient to the new expected loads.&lt;/p&gt;  &lt;h2&gt;Response&lt;/h2&gt;  &lt;p&gt;This paper, along with the previous work described, operates under the assumption that adding hardware to the cluster is a time consuming operation. This assumption leads to the static thinking that the only operation available is to move operations from one existing node to another.&lt;/p&gt;  &lt;p&gt;&lt;a class=&quot;zem_slink&quot; title=&quot;Cloud computing&quot; href=&quot;http://en.wikipedia.org/wiki/Cloud_computing&quot; rel=&quot;wikipedia&quot;&gt;Cloud computing&lt;/a&gt; allows spinning up hardware in just a few minutes to help in handling variation in system load, and then the ability to shut down the systems when load has decreased to reduce cluster costs. With the concepts in this paper, the system can decide when additional hardware is needed, and choose the best set of operators to migrate to the new hardware to maintain desired latency levels. &lt;/p&gt;  &lt;p&gt;As cloud computing is a fairly recent development, I expect a few years to pass before solid work is published describing cloud friendly methods for load distribution.&lt;/p&gt;  &lt;div class=&quot;zemanta-pixie&quot; style=&quot;margin-top: 10px; height: 15px&quot;&gt;&lt;img class=&quot;zemanta-pixie-img&quot; style=&quot;border-right: medium none; border-top: medium none; float: right; border-left: medium none; border-bottom: medium none&quot; src=&quot;http://img.zemanta.com/pixy.gif?x-id=e0be45fb-bf91-4c8e-bd9e-76fca5ff5ac8&quot; /&gt;&lt;/div&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>School</category>				
				
				<pubDate>Tue, 02 Dec 2008 21:26:11-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/12/2/Planning-Ahead-Resilient-Load-Variations-in-Distributed-Stream-Processing</guid>
				
			</item>
			
			<item>
				<title>Amazon&apos;s Dynamo - Highly Available Key Store</title>
				<link>http://sam.curren.ws/index.cfm/2008/10/28/Amazons-Dynamo--Highly-Available-Key-Store</link>
				<description>
				
				&lt;p&gt;&lt;em&gt;This post is part of a series of posts relating to distributed system design that I&apos;m completing as part of my Computer Science MS program at BYU. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Amazon&apos;s Dynamo is a key-value storage system used internally at Amazon. It provides high-speed simple storage at extremely high levels of availability. The paper is &lt;a href=&quot;http://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fs3.amazonaws.com%2FAllThingsDistributed%2Fsosp%2Famazon-dynamo-sosp2007.pdf&amp;amp;ei=KNsHSaXMLKCSsQOQ7L2-Aw&amp;amp;usg=AFQjCNEpBjuspsc5JvGcLtzw39GGRN-chA&amp;amp;sig2=V7ClnT3k-c9TVQ03owx3CQ&quot;&gt;available online&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;In addition to describing the Dynamo system, this paper is an excellent resource for issues relevant to system design. I&apos;ve selected a few of the topics mentioned in the paper, with some comments on each.&lt;/p&gt;  &lt;h3&gt;Symmetric Nodes&lt;/h3&gt;  &lt;p&gt;Dynamo clusters have two basic duties. Each read or write has a coordinating server, and each read and write uses several storage servers. Rather then form Dynamo into a 2 layer system with a layer of coordinators and a layer of storage servers, they formed the servers to perform both the coordination services and storage services. They cite simplified system provisioning and maintenance as their reasons for this choice.&lt;/p&gt;  &lt;p&gt;This design does make scaling a little easier, as deploying a node adds resources to both services, but I think it applies so well here because of the predictable levels of work and the constant ratio between each of the services. An increase in requests will increase work for both the coordination services and the storage services, and adding additional servers will support both services to approximately the same degree. &lt;/p&gt;  &lt;p&gt;In a system where the processing at each layer is highly variable, this strategy could result in an unbalanced situation, where launching more servers will only support one of the services. As always, considering the characteristics of the service will guide the proper solution.&lt;/p&gt;  &lt;h3&gt;Dynamically Scaling Under Load&lt;/h3&gt;  &lt;p&gt;Throughout the paper, they discuss the requirement that the system be capable of adding and removing nodes under load without impacting the external performance of the system. They noted that their first design required significant background processing, and they had to develop systems to carefully monitor and control the processing power consumed by the background services.&lt;/p&gt;  &lt;p&gt;This issue is a sneaky one, because serving requests must continue during the process of re-distributing data and processing assignments. They mentioned some changes they made to reduce the background processing required, which allowed them to devote more processing time to serving requests.&lt;/p&gt;  &lt;p&gt;Nearly every service will have background processing of some kind, and setting these services to be &apos;kind&apos; to the performance of requests will help improve performance when the system comes under load.&lt;/p&gt;  &lt;h3&gt;Eventual Consistency&lt;/h3&gt;  &lt;p&gt;Dynamo (and several of the public Amazon Web Services) follow an eventually consistent model. By relaxing consistency, they can offer greater levels of availability and speed. Near the end of the paper, they reveal that 99.94% of the read requests had no artifacts of this relaxed requirement. &lt;/p&gt;  &lt;p&gt;Their design leaves the process of conflict resolution to the client, which allows a resolution process specific to the nature of the data. Allowing the most recent write to win will work in many situations, and is easy to resolve. Under more specific requirements, the client may want to combine the conflicting data. Fortunately, passing the resolution buck to the client allows each application to resolve this issue in whatever way is appropriate. (&lt;a href=&quot;http://incubator.apache.org/couchdb/&quot;&gt;CouchDB&lt;/a&gt; follows this same principle.)&lt;/p&gt;  &lt;p&gt;Eventual consistency forces the consideration of failure; when it fails, how hard is it to recover? Understanding the consequences of failure can allow proper tuning of the system, as well as guide resolution processes.&lt;/p&gt;  &lt;h3&gt;Smart Clients&lt;/h3&gt;  &lt;p&gt;The paper describes two methods for distributing requests to the nodes in the cluster: load balancers and smart clients.&lt;/p&gt;  &lt;p&gt;Load balancers are a common solution, and are considered standard fare in most systems. They forward inbound requests evenly among nodes, and then return the node&apos;s response to the client. Most large websites use load balancers to serve traffic, enabling many servers to act like one.&lt;/p&gt;  &lt;p&gt;Smart clients are a powerful tool that can provide the same levels of fail over at increased speeds. If the client is programmable, then it can choose the server to ask itself, and eliminate the need for a load balancer. It chooses it&apos;s node according to embedded logic, and will also fail over to a different node if the first one does not respond. The clients must be &apos;smart&apos; enough to discover cluster nodes and handle failure gracefully. In a load balanced configuration, these tasks are performed by the load balancer.&lt;/p&gt;  &lt;p&gt;Smart Dynamo clients poll a random cluster node every 10 seconds to retrieve a list of nodes. The clients will also retrieve a new list if they detect a failure situation.&lt;/p&gt;  &lt;p&gt;In many applications of smart clients, an update frequency of 10 seconds is far too fast and can be reduced to match the speed of adding or removing nodes. Smart clients can also choose cluster nodes based on network speed, allowing easy geographic load balancing.&lt;/p&gt;  &lt;p&gt;The speed gains measured through the user of smart clients is remarkable. response times were more then 50% shorter as a result of removing the load balancer from the picture.&lt;/p&gt;  &lt;h3&gt;Thoughts&lt;/h3&gt;  &lt;p&gt;Each of these concepts, and others in the paper, can be applied to a wide variety of systems. I&apos;m grateful to the Amazon team that published this paper, and I&apos;m grateful for the insight it provides.&lt;/p&gt;  &lt;p&gt;smart clients - improved performance by half by removing the load balancer. they polled frequently 10s for server lists, could be much longer. smart polling on failure.&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Amazon Web Services</category>				
				
				<category>Development</category>				
				
				<category>School</category>				
				
				<pubDate>Tue, 28 Oct 2008 20:41:25-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/10/28/Amazons-Dynamo--Highly-Available-Key-Store</guid>
				
			</item>
			
			<item>
				<title>Android + Google Contacts API = Awesome</title>
				<link>http://sam.curren.ws/index.cfm/2008/9/30/Android--Google-Contacts-API--Awesome</link>
				<description>
				
				&lt;p&gt;Android&apos;s address book syncs with the configured GMail account&apos;s address book. The GMail address book provides a group feature, allowing you to group your contacts together for easy management. Android can sync with some or all of these groups.&lt;/p&gt;  &lt;p&gt;This allows entering phone numbers online instead of using the phone&apos;s small keyboard and screen. It also allows entering an email address from your phone, and having that available the next time you send an email from your desktop. In addition, you can import contacts into the address book from a CSV file. All these features are available right now, with no programming required.&lt;/p&gt;  &lt;p&gt;While this is pretty cool by itself, it is made more powerful by the &lt;a href=&quot;http://code.google.com/apis/contacts/&quot;&gt;Google Contacts API&lt;/a&gt;, which allows programmatic access to your GMail address book. This opens all sorts of cool features that are not natively part of the address book on either GMail or an Android phone.&lt;/p&gt;  &lt;p&gt;Businesses can sync the company address book to employee phones, including updates made on the phone. Those changes can then be synced to other employee phones very quickly.&lt;/p&gt;  &lt;p&gt;Using a third party service, you could also allow shared groups between individuals, so my wife and I can share the &apos;family&apos; group, and both always have current numbers, no matter who enters the information.&lt;/p&gt;  &lt;p&gt;Perhaps the most powerful possibility is the integration between your address book and existing social networks. When I update my contact information, that information can be automatically updated in the contact lists of my authorized friends, and that information is quickly synced to their mobile phone.&lt;/p&gt;  &lt;p&gt;The Contacts API uses &lt;a href=&quot;http://oauth.net/&quot;&gt;oAuth&lt;/a&gt;, a mechanism for allowing access to your contacts without giving up your password. This standard access method means that you can use 3rd party services without worrying about your email being compromised, or unauthorized access to your Google Checkout purchases.&lt;/p&gt;  &lt;p&gt;I&apos;m looking forward to the options available as I seek to make my contact list management a little nicer.&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Android</category>				
				
				<category>Technology</category>				
				
				<pubDate>Tue, 30 Sep 2008 11:51:44-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/9/30/Android--Google-Contacts-API--Awesome</guid>
				
			</item>
			
			<item>
				<title>Missing Pieces of Cloud Computing</title>
				<link>http://sam.curren.ws/index.cfm/2008/8/21/Missing-Pieces-of-Cloud-Computing</link>
				<description>
				
				&lt;p&gt;Between Google&apos;s &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;AppEngine&lt;/a&gt; and Amazon&apos;s &lt;a href=&quot;http://www.amazon.com/gp/browse.html?node=3435361&quot;&gt;Web Services&lt;/a&gt; platform, you can build almost everything you need to run a scalable system. The &apos;almost&apos; is what is currently preventing these platforms from supporting truly beautiful cloud systems. I believe that the two most important pieces of Cloud Computing are scheduled processes and load balancing. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Scheduled Processes&lt;/strong&gt; in a cloud computing application are necessary for tasks both simple and complex. On the simple side, a task can be used to send reminder emails to system users, or generate periodic reports based on system data. On the complex side, scheduled processes might communicate with a processing grid via asynchronous queues, or perform orchestration functions to manage a scalable computing cluster. The best provider of this service is likely to be Google&apos;s AppEngine.&lt;/p&gt;  &lt;p&gt;During an AppEngine session at &lt;a href=&quot;http://code.google.com/events/io/&quot;&gt;Google IO&lt;/a&gt;, the presenter did mention that offline processing was a planned (and often requested) feature, but they did not give details. Their offline processing may only be the ability to launch threads and return rapidly to the user, but I hope it also contains some mechanism for the timing of script execution.&lt;/p&gt;  &lt;p&gt;In the meantime, it is possible to invoke processing scripts from an automated system, either running on hardware you own or a service such as &lt;a href=&quot;http://www.webcron.org/index.php?&amp;lang;=en&quot;&gt;WebCron&lt;/a&gt;, but it will be nice to have a more elegant solution.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Load Balancing&lt;/strong&gt; allows for a group of computers to be joined into a cluster, allowing service of more requests then a single machine can handle. While AppEngine does not require load balancing to scale, clusters within &lt;a href=&quot;http://www.amazon.com/EC2-AWS-Service-Pricing/b/ref=sc_fe_l_2?ie=UTF8&amp;amp;node=201590011&amp;amp;no=3435361&amp;amp;me=A36L942TSJ2AJA&quot;&gt;EC2&lt;/a&gt; need this functionality if they service public requests. Load balancers exist in both hardware and software form, and generally provide several methods of load distribution, system failure handling, and sometimes SSL termination for secure connections. Currently, software load balancers must be used to load balance within the EC2 environment, and at least 2 of these machines are required to gracefully handle machine failures.&lt;/p&gt;  &lt;p&gt;Providing this service in a scalable way would greatly simplify the design of computing clusters within the EC2 environment. It would also make managing public IP addresses a little easier, as only the load balancing service needs a public address. Amazon is currently testing a form of persistent storage within their EC2 environment, and I imagine that a load balancing solution could be offered in a similar form. Amazon may decide not to offer this service, preferring 3rd party solutions.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In Summary&lt;/strong&gt;, I look forward to the future of cloud infrastructure. I&apos;m excited to be able to develop to these platforms, and I expect great things in the future from both of these companies and others as well.&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Amazon Web Services</category>				
				
				<category>Development</category>				
				
				<category>Technology</category>				
				
				<pubDate>Thu, 21 Aug 2008 09:00:56-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/8/21/Missing-Pieces-of-Cloud-Computing</guid>
				
			</item>
			
			<item>
				<title>jEditable TinyMCE Plugin</title>
				<link>http://sam.curren.ws/index.cfm/2008/6/12/jEditable-TinyMCE-Plugin</link>
				<description>
				
				&lt;p&gt;Over the past view weeks, I&apos;ve been working with &lt;a href=&quot;http://www.appelsiini.net/&quot;&gt;Mika Tuupola&lt;/a&gt;, author of the &lt;a href=&quot;http://www.appelsiini.net/projects/jeditable&quot;&gt;jEditable&lt;/a&gt; &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt; extension. jEditable makes edit in place forms easy, and is itself extensible, allowing the creation of custom edit types, such as a date picker.&lt;/p&gt;  &lt;p&gt;I&apos;ve been using &lt;a href=&quot;http://tinymce.moxiecode.com/&quot;&gt;TinyMCE&lt;/a&gt; as a richtext editor, and decided to create a custom edit type for jEditable that makes TinyMCE easy. Mike added a few additional customization hooks that enabled me to complete the plugin, and I&apos;ve included example code below. This example is not meant to be a full and complete explanation, so make sure you dig into the jEditable and TinyMCE documentation.&lt;/p&gt;  &lt;p&gt;A big thanks to Mike for his help. He has &lt;a href=&quot;http://www.appelsiini.net/2008/7/jeditable-and-tinymce&quot;&gt;released the updated jEditable code&lt;/a&gt; that contains some additional hooks needed by my example code below.&lt;/p&gt;
&lt;p&gt;First, I include the necessary javascript files for each library. Your specific versions or names may vary:&lt;/p&gt;
&lt;code&gt;
&lt;script src=&quot;/resource/tiny_mce/tiny_mce_src.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;/resource/jquery/jquery-1.2.3.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;/resource/jquery/jquery.jeditable.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;/code&gt;
&lt;p&gt;Then, I setup TinyMCE, and the TinyMCE jEditable plugin as well:&lt;/p&gt;
&lt;code&gt;
&lt;script type=&quot;text/javascript&quot;&gt;

$.fn.tinymce = function(options){
	return this.each(function(){ 
		tinyMCE.execCommand(&quot;mceAddControl&quot;, true, this.id);
	});
}

function initMCE(){
	tinyMCE.init({mode : &quot;none&quot;,
		theme : &quot;advanced&quot;,
		theme_advanced_toolbar_location : &quot;top&quot;,
		theme_advanced_toolbar_align : &quot;left&quot;,
		theme_advanced_statusbar_location : &quot;bottom&quot;,
		theme_advanced_buttons1 : &quot;bold,italic,underline,strikethrough,separator,bullist,numlist,undo,redo,link,unlink&quot;,
		theme_advanced_buttons2 : &quot;&quot;,
		theme_advanced_buttons3 : &quot;&quot;,
		theme_advanced_resizing : true});
}

initMCE();


$.editable.addInputType(&apos;mce&apos;, {
	element : function(settings, original) {
		var textarea = $(&apos;&lt;textarea id=&quot;&apos;+$(original).attr(&quot;id&quot;)+&apos;_mce&quot;/&gt;&apos;);
		if (settings.rows) {
			textarea.attr(&apos;rows&apos;, settings.rows);
		} else {
			textarea.height(settings.height);
		}
		if (settings.cols) {
			textarea.attr(&apos;cols&apos;, settings.cols);
		} else {
			textarea.width(settings.width);
		}
		$(this).append(textarea);
			return(textarea);
		},
	plugin : function(settings, original) {
		tinyMCE.execCommand(&quot;mceAddControl&quot;, true, $(original).attr(&quot;id&quot;)+&apos;_mce&apos;);
		},
	submit : function(settings, original) { 
		tinyMCE.triggerSave();
		tinyMCE.execCommand(&quot;mceRemoveControl&quot;, true, $(original).attr(&quot;id&quot;)+&apos;_mce&apos;);
		},
	reset : function(settings, original) {
		tinyMCE.execCommand(&quot;mceRemoveControl&quot;, true, $(original).attr(&quot;id&quot;)+&apos;_mce&apos;);
		original.reset(); 
	}
});
&lt;/script&gt;
&lt;/code&gt;
&lt;p&gt;This next block of code initializes TinyMCE, first as a regular jQuery plugin (not in place editable), and then as the jEditable enabled in place editor:

&lt;code&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(function(){
	$(&apos;#foo&apos;).tinymce();
	
	$(&quot;#bar&quot;).editable(function(value, settings){
		console.log(this, value, settings);
		return value;
	
	}, { 
		type      : &apos;mce&apos;,
		submit    : &apos;OK&apos;,
		indicator : &quot;Saving...&quot;,
		tooltip   : &apos;Click to edit...&apos;,
		width     : &apos;500px&apos;,
		height    : &apos;100px&apos;
	});
});

&lt;/script&gt;
&lt;/code&gt;
&lt;p&gt;In this example, both of the selected elements are HTML textareas. Clearly, your settings for jEditable and TinyMCE will change with your own needs, but this should get you started.&lt;/p&gt;
&lt;p&gt;Finally, a big thanks to Mike, for writing the jEditable plugin in the first place, and for being so supportive and patient in helping me write this TinyMCE plugin!&lt;/p&gt;
&lt;p&gt;Edited 24Jan09: Applied IE6 Fix as recommended by Rick in comments.&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Javascript</category>				
				
				<category>Development</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Thu, 12 Jun 2008 13:25:00-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/6/12/jEditable-TinyMCE-Plugin</guid>
				
			</item>
			
			<item>
				<title>Google IO: The really cool thing about Android</title>
				<link>http://sam.curren.ws/index.cfm/2008/5/30/Google-IO-The-really-cool-thing-about-Android</link>
				<description>
				
				&lt;p&gt;The most interesting part of my Google IO experience was learning more about Android. While Google believes that most mobile apps will be delivered through the browser, mobile browsers really do suck (Webkit excluded). Android is their way of bringing mobile connectivity to the developer community.&lt;/p&gt;  &lt;p&gt;The really amazing part of Android isn&apos;t the &lt;a href=&quot;http://sam.curren.ws/index.cfm/2008/5/30/Google-IO-Androids-Magic-Status-Bar&quot;&gt;cool expandable status bar&lt;/a&gt;, or the nice UI shown in the keynote address. The really cool part of Android is the architecture.&lt;/p&gt;  &lt;p&gt;When I think of an application, I think of something that I write and compile, and that runs on the target platform as a unit. You start an application, use it, and then shut it down. Many mobile platforms currently follow the same model. My experience with Windows Mobile is riddled with &apos;out of memory&apos; errors that occur when too many applications have been opened. Trouble is, they don&apos;t give you a good way to shut applications down. &lt;/p&gt;  &lt;p&gt;Android applications are really a collection of components, each with different purposes, that work together to perform the duties of an application. Activities are things you interact with, Services run in the background, Content Providers feed data to UI components, and they are all tied together with a message passing architecture. &lt;/p&gt;  &lt;p&gt;By relying on messages to navigate an application, the Android platform can decide which applications to shut down to free memory. Before a component is killed, it is given the opportunity to serialize it&apos;s state, so that when it is brought back onto the stack it can restore itself. This means that the user will never be confronted with the task of managing memory themselves.&lt;/p&gt;  &lt;p&gt;The component architecture also allows a developer to replace portions of the phone&apos;s software, or even portions of other developers software, with a custom built version. This is very powerful, as it allows deep customization of the phone&apos;s interface and user experience.&lt;/p&gt;  &lt;p&gt;I&apos;m excited. I think the Android platform is the best thing to ever happen to mobile device and application development. Give me one already!&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Development</category>				
				
				<category>Technology</category>				
				
				<pubDate>Fri, 30 May 2008 22:46:24-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/5/30/Google-IO-The-really-cool-thing-about-Android</guid>
				
			</item>
			
			<item>
				<title>Google IO: Android&apos;s Magic Status Bar</title>
				<link>http://sam.curren.ws/index.cfm/2008/5/30/Google-IO-Androids-Magic-Status-Bar</link>
				<description>
				
				&lt;p&gt;One of the coolest things shown in the &lt;a href=&quot;http://sam.curren.ws/index.cfm/2008/5/28/Google-IO-Keynote&quot;&gt;Google IO Keynote&lt;/a&gt; was the expandable status bar on the Android platform. The part I&apos;m referring to is about minute 24 in the &lt;a href=&quot;http://www.youtube.com/watch?v=vk1HvP7NO5w&quot;&gt;keynote video&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The status bar of a phone is where the phone alerts you to messages, alarms, and other notifications. The status bar is quite small, so to not crowd the main part of the screen, so icons and status symbols must be small to fit in the provided space. &lt;/p&gt;  &lt;p&gt;Applications developed on the &lt;a href=&quot;http://code.google.com/android/&quot;&gt;Android platform&lt;/a&gt; have the option of pushing notifications to the user. While this is very powerful, it creates a learning problem for phone users. Each symbol will mean something new, and guessing what each one means will be difficult.&lt;/p&gt;  &lt;p&gt;By &apos;pulling&apos; down the status bar with a vertical stroke on the screen, the user can reveal a full screen display of status notifications. This allows detailed information, such as the number of unread emails, instead of just indicating that there is at least one.&lt;/p&gt;  &lt;p&gt;The really powerful part of this design is that users can discover and learn what the status symbols mean, and even jump from an alert right to the relevant application. Providing a way for users to discover the abilities of new applications will go a long way toward helping users be satisfied with their experience.&lt;/p&gt; 
				</description>
				
				<category>Web-Applications</category>				
				
				<category>Development</category>				
				
				<category>Technology</category>				
				
				<pubDate>Fri, 30 May 2008 20:45:16-0700</pubDate>
				<guid>http://sam.curren.ws/index.cfm/2008/5/30/Google-IO-Androids-Magic-Status-Bar</guid>
				
			</item>
			</channel></rss>