[tomboy] Pull latest-sync-revision out of more JSON responses, use that to verify revision instead of repeate



commit f6b21fa253cc355fdb3da9b2c0a27c5372442ba3
Author: Sandy Armstrong <sanfordarmstrong gmail com>
Date:   Tue May 19 12:39:25 2009 -0700

    Pull latest-sync-revision out of more JSON responses, use that to verify revision instead of repeatedly requesting the User resource.
---
 Tomboy/Addins/WebSyncService/Api/UserInfo.cs  |   55 ++++++++++++++++++-------
 Tomboy/Addins/WebSyncService/WebSyncServer.cs |   52 ++++++++++++-----------
 2 files changed, 67 insertions(+), 40 deletions(-)

diff --git a/Tomboy/Addins/WebSyncService/Api/UserInfo.cs b/Tomboy/Addins/WebSyncService/Api/UserInfo.cs
index beaaa93..69118e3 100644
--- a/Tomboy/Addins/WebSyncService/Api/UserInfo.cs
+++ b/Tomboy/Addins/WebSyncService/Api/UserInfo.cs
@@ -97,12 +97,12 @@ namespace Tomboy.WebSync.Api
 
 		public ResourceReference Friends { get; private set; }
 
-		public IList<NoteInfo> GetNotes (bool includeContent)
+		public IList<NoteInfo> GetNotes (bool includeContent, out int? latestSyncRevision)
 		{
-			return GetNotes (includeContent, -1);
+			return GetNotes (includeContent, -1, out latestSyncRevision);
 		}
 
-		public IList<NoteInfo> GetNotes (bool includeContent, int sinceRevision)
+		public IList<NoteInfo> GetNotes (bool includeContent, int sinceRevision, out int? latestSyncRevision)
 		{
 			// TODO: Error-handling in GET and Deserialize
 			WebHelper helper = new WebHelper ();
@@ -117,21 +117,29 @@ namespace Tomboy.WebSync.Api
 			
 			jsonString = helper.Get (BaseUrl + Notes.ApiRef, parameters, AuthProvider);
 
-			return ParseJsonNotes (jsonString);
+			return ParseJsonNotes (jsonString, out latestSyncRevision);
 		}
 
-		public void UpdateNotes (IList<NoteInfo> noteUpdates)
+		public int UpdateNotes (IList<NoteInfo> noteUpdates, int expectedNewRevision)
 		{
 			// TODO: Error-handling in PUT, Serialize, and Deserialize
 			WebHelper helper = new WebHelper ();
 
 			string jsonResponseString =
-				helper.PutJson (BaseUrl + Notes.ApiRef, null, CreateNoteChangesJsonString (noteUpdates), AuthProvider);
-
-			// TODO: Not working on server yet, but this will let us do
-			//       a sanity check on what revision we pushed, *and*
-			//       let us update any cache of refs that we keep.
-			//ParseJsonNotes (jsonResponseString);
+				helper.PutJson (BaseUrl + Notes.ApiRef,
+				                null,
+				                CreateNoteChangesJsonString (noteUpdates, expectedNewRevision),
+				                AuthProvider);
+
+			// TODO: This response object could be extremely useful
+			using (System.IO.StreamWriter writer = System.IO.File.CreateText ("/home/sandy/lastPutResp"))
+				writer.Write (jsonResponseString);
+			
+			int? actualNewRevision;
+			ParseJsonNotes (jsonResponseString, out actualNewRevision);
+			if (!actualNewRevision.HasValue)
+				throw new ApplicationException ("No new sync revision provided in server response after uploading note changes");
+			return actualNewRevision.Value;
 		}
 
 		#endregion
@@ -146,7 +154,7 @@ namespace Tomboy.WebSync.Api
 
 		#region Private Methods
 
-		private IList<NoteInfo> ParseJsonNotes (string jsonString)
+		private IList<NoteInfo> ParseJsonNotes (string jsonString, out int? latestSyncRevision)
 		{
 			Hyena.Json.Deserializer deserializer =
 				new Hyena.Json.Deserializer (jsonString);
@@ -154,7 +162,14 @@ namespace Tomboy.WebSync.Api
 			Hyena.Json.JsonObject jsonObj =
 				obj as Hyena.Json.JsonObject;
 			Hyena.Json.JsonArray noteArray =
-				(Hyena.Json.JsonArray) jsonObj ["notes"];
+				(Hyena.Json.JsonArray) jsonObj [NotesElementName];
+
+			object val;
+			if (jsonObj.TryGetValue (LatestSyncRevisionElementName, out val))
+				latestSyncRevision = (int) val;
+			else
+				latestSyncRevision = null;
+				
 			return ParseJsonNoteArray (noteArray);
 		}
 
@@ -170,7 +185,7 @@ namespace Tomboy.WebSync.Api
 			return noteList;
 		}
 
-		private string CreateNoteChangesJsonString (IList<NoteInfo> noteUpdates)
+		private string CreateNoteChangesJsonString (IList<NoteInfo> noteUpdates, int? expectedNewRevision)
 		{
 			Hyena.Json.JsonObject noteChangesObj =
 				new Hyena.Json.JsonObject ();
@@ -178,7 +193,9 @@ namespace Tomboy.WebSync.Api
 				new Hyena.Json.JsonArray ();
 			foreach (NoteInfo note in noteUpdates)
 				noteChangesArray.Add (note.ToUpdateObject ());
-			noteChangesObj ["note-changes"] = noteChangesArray;
+			noteChangesObj [NoteChangesElementName] = noteChangesArray;
+			if (expectedNewRevision != null)
+				noteChangesObj [LatestSyncRevisionElementName] = expectedNewRevision;
 
 			// TODO: Handle errors
 			Hyena.Json.Serializer serializer =
@@ -188,5 +205,13 @@ namespace Tomboy.WebSync.Api
 		}
 		
 		#endregion
+
+		#region Private Constants
+
+		private const string LatestSyncRevisionElementName = "latest-sync-revision";
+		private const string NotesElementName = "notes";
+		private const string NoteChangesElementName = "note-changes";
+
+		#endregion
 	}
 }
diff --git a/Tomboy/Addins/WebSyncService/WebSyncServer.cs b/Tomboy/Addins/WebSyncService/WebSyncServer.cs
index 649e212..a8c3c48 100644
--- a/Tomboy/Addins/WebSyncService/WebSyncServer.cs
+++ b/Tomboy/Addins/WebSyncService/WebSyncServer.cs
@@ -54,8 +54,13 @@ namespace Tomboy.WebSync
 		
 		public bool BeginSyncTransaction ()
 		{
-			// TODO: Check connection and auth
-			RefreshUser ();
+			// TODO: Check connection and auth (is getting user resource a sufficient check?)
+			user = UserInfo.GetUser (serverUrl, userName, auth);
+			if (user.LatestSyncRevision.HasValue)
+				LatestRevision = user.LatestSyncRevision.Value;
+			else
+				VerifyLatestSyncRevision (user.LatestSyncRevision);
+			
 			pendingCommits = new List<NoteInfo> ();
 			return true;
 		}
@@ -69,10 +74,10 @@ namespace Tomboy.WebSync
 		
 		public bool CommitSyncTransaction ()
 		{
-			RefreshUser ();	// TODO: Test that latest sync rev hasn't changed
-			user.UpdateNotes (pendingCommits);
-			pendingCommits.Clear ();
-			// TODO: Check for problems
+			if (pendingCommits != null && pendingCommits.Count > 0) {
+				LatestRevision = user.UpdateNotes (pendingCommits, LatestRevision + 1);
+				pendingCommits.Clear ();
+			}
 			return true;
 		}
 		
@@ -94,19 +99,23 @@ namespace Tomboy.WebSync
 		
 		public IList<string> GetAllNoteUUIDs ()
 		{
-			RefreshUser ();	// TODO: Test that latest sync rev hasn't changed
 			List<string> uuids = new List<string> ();
-			foreach (NoteInfo noteInfo in user.GetNotes (false))
+			int? latestRevision;
+			IList<NoteInfo> serverNotes = user.GetNotes (false, out latestRevision);
+			VerifyLatestSyncRevision (latestRevision);
+			foreach (NoteInfo noteInfo in serverNotes)
 				uuids.Add (noteInfo.Guid);
 			return uuids;
 		}
 		
 		public IDictionary<string, NoteUpdate> GetNoteUpdatesSince (int revision)
 		{
-			RefreshUser ();	// TODO: Test that latest sync rev hasn't changed
 			Dictionary<string, NoteUpdate> updates =
 				new Dictionary<string, NoteUpdate> ();
-			foreach (NoteInfo noteInfo in user.GetNotes (true, revision)) {
+			int? latestRevision;
+			IList<NoteInfo> serverNotes = user.GetNotes (true, revision, out latestRevision);
+			VerifyLatestSyncRevision (latestRevision);
+			foreach (NoteInfo noteInfo in serverNotes) {
 				string noteXml = NoteConvert.ToNoteXml (noteInfo);
 				NoteUpdate update = new NoteUpdate (noteXml,
 				                                    noteInfo.Title,
@@ -123,31 +132,24 @@ namespace Tomboy.WebSync
 			}
 		}
 		
-		public int LatestRevision {
-			get {
-				// TODO: Is this really the right way to do this?
-				//       If we just pushed and update, should trust
-				//       value returned from the PUT. Other client
-				//       may have pushed a new rev in intervening time!
-				RefreshUser ();	// TODO: Test that latest sync rev hasn't changed
-				return user.LatestSyncRevision.Value;
-			}
-		}
+		public int LatestRevision { get; private set; }
 		
 		public void UploadNotes (IList<Note> notes)
 		{
-			foreach (Note note in notes) {
+			foreach (Note note in notes)
 				pendingCommits.Add (NoteConvert.ToNoteInfo (note));
-			}
 		}
 		
 		#endregion
 
 		#region Private Methods
-		
-		private void RefreshUser ()
+
+		private void VerifyLatestSyncRevision (int? latestRevision)
 		{
-			user = UserInfo.GetUser (serverUrl, userName, auth);
+			if (!latestRevision.HasValue)
+				throw new TomboySyncException ("No sync revision provided in server response");
+			if (latestRevision.Value != LatestRevision)
+				throw new TomboySyncException ("Latest revision on server has changed, please update restart your sync");
 		}
 
 		#endregion



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]