<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>addons/Twitter/source/.gitsidumb</filename>
    </added>
    <added>
      <filename>addons/VertexDB/source/.gitisdumb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,11 +1,10 @@
 AddonBuilder clone do(
 	if(platform == &quot;darwin&quot;, 
-		//appendHeaderSearchPath(&quot;/opt/local/include/mysql5/mysql&quot;)
-		//appendLibSearchPath(&quot;/opt/local/lib/mysql5/mysql&quot;),
-		
-
-		appendHeaderSearchPath(&quot;/usr/local//mysql/include&quot;)
-		appendLibSearchPath(&quot;/usr/local/mysql/lib&quot;),
+		appendHeaderSearchPath(&quot;/opt/local/include/mysql5/mysql&quot;)
+		appendHeaderSearchPath(&quot;/usr/local/mysql/include&quot;)
+		//appendLibSearchPath(&quot;/usr/local/mysql/lib&quot;)
+		appendLibSearchPath(&quot;/opt/local/lib/mysql5/mysql&quot;)
+	,
 
 		headerSearchPaths foreach(headerSearchPath, appendHeaderSearchPath(headerSearchPath .. &quot;/mysql&quot;))
 	)</diff>
      <filename>addons/MySQL/build.io</filename>
    </modified>
    <modified>
      <diff>@@ -26,6 +26,8 @@ MySQL do(
 SqlTable := Object clone do(
 	db ::= nil
 	name ::= nil
+where ::= &quot;&quot;
+//TODO: Refactor where
 
 	fetchColumnNames := method(
 		self columnNames := db query(&quot;SHOW columns FROM &quot; .. name) map(first) flatten
@@ -46,7 +48,8 @@ SqlTable := Object clone do(
 		increment := foreachCacheSize
 		loop(
 			write(&quot; &lt;sql&quot;); File standardOutput flush
-			rows := db queryThenMap(&quot;SELECT * FROM &quot; .. name .. &quot; LIMIT &quot; .. start .. &quot;, &quot; .. increment)
+			writeln(&quot;SELECT * FROM &quot; .. name .. where .. &quot; LIMIT &quot; .. start .. &quot;, &quot; .. increment)
+			rows := db queryThenMap(&quot;SELECT * FROM &quot; .. name .. where .. &quot; LIMIT &quot; .. start .. &quot;, &quot; .. increment)
 			write(&quot;&gt;&quot;); File standardOutput flush
 			if(rows size == 0, break)
 			rows foreach(row, </diff>
      <filename>addons/MySQL/io/MySQL_extras.io</filename>
    </modified>
    <modified>
      <diff>@@ -28,6 +28,8 @@ TwitterAccount := Object clone do(
 			TwitterException clone setIsRateLimited(true) raise
 		)
 		request execute
+		debugWriteln(request response body)
+		debugWriteln(request response statusCode)
 		
 		if(request response rateLimitRemaining,
 			setRateLimitRemaining(request response rateLimitRemaining asNumber)
@@ -59,7 +61,7 @@ TwitterAccount := Object clone do(
 	)
 	
 	hasProtectedUpdates := method(aScreenName,
-		show(aScreenName) at(&quot;protected&quot;)
+		showUser(aScreenName) at(&quot;protected&quot;)
 	)
 	
 	/* for testing
@@ -74,8 +76,7 @@ TwitterAccount := Object clone do(
 		//Could not follow user: You have been blocked from following this account at the request of the user.
 		//Could not follow user: This account is currently suspended and is being investigated due to strange activity
 		//raiseFollowException for testing
-		resultsFor(request asCreateFriendship setScreenName(aScreenName))
-		self
+		resultsFor(request asCreateFriendship setScreenName(aScreenName)) at(&quot;protected&quot;)
 	)
 	
 	unfollow := method(aScreenName,
@@ -85,14 +86,26 @@ TwitterAccount := Object clone do(
 		self
 	)
 	
-	followerIds := method(
+	followerIdsCursor ::= &quot;-1&quot;
+	resetFollowerIdsCursor := method(
+		setFollowerIdsCursor(&quot;-1&quot;)
+	)
+	followerIds := method(aScreenName,
 		//&quot;Not authorized&quot;
-		resultsFor(request asFollowerIds setScreenName(screenName))
+		result := resultsFor(request asFollowerIds dontAuthenticate setScreenName(aScreenName) setCursor(followerIdsCursor))
+		setFollowerIdsCursor(result at(&quot;next_cursor&quot;))
+		result at(&quot;ids&quot;)
 	)
 	
-	friendIds := method(
+	friendIdsCursor ::= &quot;-1&quot;
+	resetFriendIdsCursor := method(
+		setFriendIdsCursor(&quot;-1&quot;)
+	)
+	friendIds := method(aScreenName,
 		//&quot;Not authorized&quot;
-		resultsFor(request asFriendIds setScreenName(screenName))
+		result := resultsFor(request asFriendIds dontAuthenticate setScreenName(aScreenName) setCursor(friendIdsCursor))
+		setFriendIdsCursor(result at(&quot;next_cursor&quot;))
+		result at(&quot;ids&quot;)
 	)
 	
 	updateStatus := method(message,
@@ -107,6 +120,18 @@ TwitterAccount := Object clone do(
 		resultsFor(request asShow setScreenName(aScreenName))
 	)
 	
+	showUserWithId := method(anId,
+		resultsFor(request asShow setUserId(anId))
+	)
+	
+	isSuspended := method(aScreenName,
+		handleErrors(showUser(aScreenName)) ifIsSuspended(
+			return(true)
+		) else(
+			return(false)
+		)
+	)
+	
 	ExceptionConditional := Object clone do(
 		exception ::= nil
 		result ::= nil
@@ -162,13 +187,17 @@ TwitterAccount := Object clone do(
 					if(e isOverloaded or e isDown or e isInternalError,
 						attempts = attempts + 1
 					,
-						return(ExceptionConditional clone setException(e))
+						return(TwitterAccount ExceptionConditional clone setException(e))
 					)
 				,
-					e pass
+					if(list(&quot;Connection reset by peer&quot;, &quot;Timeout&quot;) detect(m, e error containsSeq(m)),
+						attempts = attempts + 1
+					,
+						e pass
+					)
 				)
 			,
-				return(ExceptionConditional clone setResult(result) setDone(true))
+				return(TwitterAccount ExceptionConditional clone setResult(result) setDone(true))
 			)
 		)
 		</diff>
      <filename>addons/Twitter/io/TwitterAccount.io</filename>
    </modified>
    <modified>
      <diff>@@ -17,40 +17,33 @@ TwitterAccountProfile := Object clone do(
 	tilesBackgroundImage ::= nil
 	
 	update := method(
-		account request asUpdateAccountProfile\
+		account resultsFor(account request asUpdateAccountProfile\
 			setName(name)\
 			setUrl(url)\
 			setLocation(location)\
-			setDescription(description)\
-			resultsOrError returnIfError
-		
+			setDescription(description))
 		self
 	)
 	
 	updateColors := method(
-		account request asUpdateAccountProfileColors\
+		account resultsFor(account request asUpdateAccountProfileColors\
 			setProfileBackgroundColor(backgroundColor)\
 			setProfileTextColor(textColor)\
 			setProfileLinkColor(linkColor)\
 			setProfileSidebarFillColor(sidebarFillColor)\
-			setProfileSidebarBorderColor(sidebarBorderColor)\
-			resultsOrError returnIfError
-		
+			setProfileSidebarBorderColor(sidebarBorderColor))
 		self
 	)
 	
 	updateImage := method(
-		account request asUpdateAccountProfileImage\
-			setImage(imageFile)\
-			resultsOrError returnIfError
+		account resultsFor(account request asUpdateAccountProfileImage setImage(imageFile))
 		self
 	)
 	
 	updateBackgroundImage := method(
-		account request asUpdateAccountProfileBackgroundImage\
+		account resultsFor(account request asUpdateAccountProfileBackgroundImage\
 			setImage(backgroundImageFile)\
-			setTile(tilesBackgroundImage)\
-			resultsOrError returnIfError
+			setTile(tilesBackgroundImage))
 		self
 	)
 )
\ No newline at end of file</diff>
      <filename>addons/Twitter/io/TwitterAccountProfile.io</filename>
    </modified>
    <modified>
      <diff>@@ -51,7 +51,7 @@ TwitterRequest := Object clone do(
 		
 		url := URL with(&quot;http://&quot; .. host .. path .. &quot;.json&quot; .. queryString) setFollowRedirects(false)
 		
-		//writeln(url asString)
+		debugWriteln(url asString)
 		
 		if(username and password,
 			url setUsesBasicAuthentication(true)
@@ -62,7 +62,7 @@ TwitterRequest := Object clone do(
 		headers := Map clone
 		
 		if(fileParamName and file := self perform(fileParamName),
-			ext := file path pathExtension
+			ext := file path pathExtension asLowercase
 			if(ext == &quot;jpg&quot;) then(
 				type := &quot;image/jpg&quot;
 			) elseif(ext == &quot;gif&quot;) then(
@@ -126,6 +126,10 @@ TwitterRequest := Object clone do(
 		self
 	)
 	
+	dontAuthenticate := method(
+		setUsername(nil) setPassword(nil)
+	)
+	
 	asShowFriendship := method(
 		setPath(&quot;/friendships/show&quot;)
 		addQuerySlots(&quot;source_id source_screen_name target_id target_screen_name&quot;)
@@ -156,12 +160,12 @@ TwitterRequest := Object clone do(
 	
 	asFriendIds := method(
 		setPath(&quot;/friends/ids&quot;)
-		addQuerySlots(&quot;user_id screen_name&quot;)
+		addQuerySlots(&quot;user_id screen_name cursor&quot;)
 	)
 	
 	asFollowerIds := method(
 		setPath(&quot;/followers/ids&quot;)
-		addQuerySlots(&quot;user_id screen_name&quot;)
+		addQuerySlots(&quot;user_id screen_name cursor&quot;)
 	)
 	
 	asUpdateAccountProfile := method(</diff>
      <filename>addons/Twitter/io/TwitterRequest.io</filename>
    </modified>
    <modified>
      <diff>@@ -18,6 +18,7 @@ TwitterResponse := Object clone do(
 			Exception raise(e message)
 		)
 		
+		//Could not find both specified users
 		if(statusCode == 400) then(
 			TwitterException clone setIsBadRequest(true) raise(body)
 		) elseif(statusCode == 401) then(
@@ -30,13 +31,15 @@ TwitterResponse := Object clone do(
 				) elseif(errorMessage containsSeq(&quot;You have been blocked&quot;)) then(
 					e setIsBlocked(true)
 				) elseif(errorMessage containsSeq(&quot;You do not have permission to retrieve following status for both specified users&quot;)) then(
-					setIsBlockedOrSuspendedOrProtected(true)
+					e setIsBlockedOrSuspendedOrProtected(true)
 				) elseif(errorMessage containsSeq(&quot;This account is currently suspended&quot;)) then(
 					e setIsSuspended(true)
 				) elseif(errorMessage containsSeq(&quot;You are not friends with the specified user&quot;)) then(
 					e setWasntFriend(true)
 				) elseif(errorMessage containsSeq(&quot;You are unable to follow more people at this time&quot;)) then(
 					e setIsFollowLimit(true)
+				) elseif(errorMessage containsSeq(&quot;Could not find both specified users&quot;)) then(
+					e setUserIsMissing(true)
 				)
 			,
 				errorMessage := body</diff>
      <filename>addons/Twitter/io/TwitterResponse.io</filename>
    </modified>
    <modified>
      <diff>@@ -21,4 +21,34 @@ TwitterSearch := Object clone do(
 	cursor := method(
 		TwitterSearchCursor clone setSearch(self clone setPage(0))
 	)
+	
+	handleErrors := method( //TODO: Unify this with account
+		attempts := 0
+
+		while(attempts &lt; 3,
+			e := try(
+				result := self doMessage(call message arguments at(0), call sender)
+			)
+
+			if(e,
+				if(e hasProto(TwitterException),
+					if(e isOverloaded or e isDown or e isInternalError,
+						attempts = attempts + 1
+					,
+						return(TwitterAccount ExceptionConditional clone setException(e))
+					)
+				,
+					if(list(&quot;Connection reset by peer&quot;, &quot;Timeout&quot;) detect(m, e error containsSeq(m)),
+						attempts = attempts + 1
+					,
+						e pass
+					)
+				)
+			,
+				return(TwitterAccount ExceptionConditional clone setResult(result) setDone(true))
+			)
+		)
+
+		e pass
+	)
 )
\ No newline at end of file</diff>
      <filename>addons/Twitter/io/TwitterSearch.io</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,7 @@ TwitterSearchCursor := Object clone do(
 	)
 	
 	fetchNext := method(
-		results appendSeq(search setPage(search page + 1) results)
+		search setPage(search page + 1) handleErrors(results) else(searchResults, results appendSeq(searchResults))
 		self
 	)
 )
\ No newline at end of file</diff>
      <filename>addons/Twitter/io/TwitterSearchCursor.io</filename>
    </modified>
    <modified>
      <diff>@@ -7,9 +7,12 @@ VertexDB Queue := Object clone do(
 	target ::= nil
 	messageName ::= nil
 	expiresActive ::= true
-	concurrency ::= 10
+	concurrency ::= 1
 	node ::= nil
 	qNodes ::= nil
+	itemsPerProcess ::= nil //if non nil then process at most itemsPerProcess
+	jobs ::= nil
+	processedCount ::= 0
 	
 	waitingNode ::= method(node nodeAt(&quot;waiting&quot;))
 	activeNode ::= method(node nodeAt(&quot;active&quot;))
@@ -52,12 +55,17 @@ VertexDB Queue := Object clone do(
 	
 	jobError ::= nil
 	
+	processCountLimited := method(
+		if(itemsPerProcess, processedCount &gt;= itemsPerProcess, false)
+	)
+	
 	process := method(
 		setJobError(nil)
 		if(expiresActive, expireActive)
 		processedOne := false
-		self jobs := List clone
-		while(k := waitingNode queueToNode(activeNode),
+		setJobs(List clone)
+		setProcessedCount(0)
+		while(processCountLimited not and (k := waitingNode queueToNode(activeNode)),
 			debugWriteln(&quot;waitingNode&lt;&quot;, waitingNode path, &quot;&gt; queueToNode(&lt;&quot;, activeNode path, &quot;&gt;) == &lt;&quot;, k, &quot;&gt;&quot;)
 			if(k == nil, break)
 			debugWriteln(&quot;jobs size: &quot;, jobs size)
@@ -113,6 +121,7 @@ VertexDB Queue := Object clone do(
 	)
 	
 	finishedJob := method(job,
+		setProcessedCount(processedCount + 1)
 		self jobs remove(job)
 	)
 	
@@ -120,4 +129,8 @@ VertexDB Queue := Object clone do(
 		count := activeNode queueExpireToNode(waitingNode)
 		count
 	)
+	
+	hasKey := method(k,
+		qNodes detect(hasKey(k))
+	)
 )</diff>
      <filename>addons/VertexDB/io/protos/Queue.io</filename>
    </modified>
    <modified>
      <diff>@@ -40,6 +40,11 @@ VertexDB Request := Object clone do(
 
 	execute := method(
 		url := URL with(&quot;http://&quot; .. host .. &quot;:&quot; .. port asString .. resource) setFollowRedirects(false)
+		if(VertexDB Settings username,
+			url setUsername(VertexDB Settings username)
+			url setPassword(VertexDB Settings password)
+			url setUsesBasicAuthentication(true)
+		)
 		
 		debugWriteln(url url)
 		if(body size &gt; 0,</diff>
      <filename>addons/VertexDB/io/protos/Request.io</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,7 @@
 VertexDB Settings := Object clone do(
 	host ::= &quot;localhost&quot;
 	port ::= 8080
+	username ::= nil
+	password ::= nil
 	raisesOnError ::= true
 )
\ No newline at end of file</diff>
      <filename>addons/VertexDB/io/protos/Settings.io</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>a6672c1d1c8d94f72eb021c8d9cc81a3a85b7f1c</id>
    </parent>
    <parent>
      <id>1a80de3bc5e0ef53e8e4cb4bdd601ada2b7d3b40</id>
    </parent>
  </parents>
  <author>
    <name>Steve Dekorte</name>
    <email>steve@StevesLaptop-7.local</email>
  </author>
  <url>http://github.com/stevedekorte/io/commit/e8b4edef6cb9eb21f0de279bd761bee0b89f5ecb</url>
  <id>e8b4edef6cb9eb21f0de279bd761bee0b89f5ecb</id>
  <committed-date>2009-11-04T18:19:25-08:00</committed-date>
  <authored-date>2009-11-04T18:19:25-08:00</authored-date>
  <message>Merge branch 'master' of git://github.com/richcollins/io</message>
  <tree>19f5ba06c78f7917153d33519c77e96988ee9532</tree>
  <committer>
    <name>Steve Dekorte</name>
    <email>steve@StevesLaptop-7.local</email>
  </committer>
</commit>
