Skip to content
This repository has been archived by the owner on Feb 29, 2020. It is now read-only.

Commit

Permalink
Fix a large part of the problem described in Issue #615. This is a su…
Browse files Browse the repository at this point in the history
…bset of Pull Request #614 with just the subset I think can be merged as per the conversation with @phvannor.
  • Loading branch information
masojus committed Mar 12, 2015
1 parent a70812d commit a28ae32
Showing 1 changed file with 77 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,104 +132,104 @@ private async Task ExecuteAllOperationsAsync(OperationBatch batch)
// keep taking out operations and executing them until queue is empty or operation finds the bookmark or batch is aborted
while (operation != null)
{
bool success = await this.ExecuteOperationAsync(operation, batch);

if (batch.AbortReason.HasValue)
using (await this.OperationQueue.LockItemAsync(operation.ItemId, this.CancellationToken))
{
break;
}
bool success = await this.ExecuteOperationAsync(operation, batch);

if (success)
{
// we successfuly executed an operation so remove it from queue
await this.OperationQueue.DeleteAsync(operation.Id, operation.Version);
}
if (batch.AbortReason.HasValue)
{
break;
}

// get next operation
operation = await this.OperationQueue.PeekAsync(operation.Sequence, this.tableKind, this.tableNames);
if (success)
{
// we successfuly executed an operation so remove it from queue
await this.OperationQueue.DeleteAsync(operation.Id, operation.Version);
}

// get next operation
operation = await this.OperationQueue.PeekAsync(operation.Sequence, this.tableKind, this.tableNames);
}
}
}

private async Task<bool> ExecuteOperationAsync(MobileServiceTableOperation operation, OperationBatch batch)
{
using (await this.OperationQueue.LockItemAsync(operation.ItemId, this.CancellationToken))
if (operation.IsCancelled || this.CancellationToken.IsCancellationRequested)
{
if (operation.IsCancelled || this.CancellationToken.IsCancellationRequested)
{
return false;
}
return false;
}

operation.Table = await this.context.GetTable(operation.TableName);
await this.LoadOperationItem(operation, batch);
operation.Table = await this.context.GetTable(operation.TableName);
await this.LoadOperationItem(operation, batch);

if (this.CancellationToken.IsCancellationRequested)
{
return false;
}
if (this.CancellationToken.IsCancellationRequested)
{
return false;
}

await TryUpdateOperationState(operation, MobileServiceTableOperationState.Attempted, batch);
await TryUpdateOperationState(operation, MobileServiceTableOperationState.Attempted, batch);

// strip out system properties before executing the operation
operation.Item = MobileServiceSyncTable.RemoveSystemPropertiesKeepVersion(operation.Item);
// strip out system properties before executing the operation
operation.Item = MobileServiceSyncTable.RemoveSystemPropertiesKeepVersion(operation.Item);

JObject result = null;
Exception error = null;
try
{
result = await batch.SyncHandler.ExecuteTableOperationAsync(operation);
}
catch (Exception ex)
{
error = ex;
}

if (error != null)
{
await TryUpdateOperationState(operation, MobileServiceTableOperationState.Failed, batch);
JObject result = null;
Exception error = null;
try
{
result = await batch.SyncHandler.ExecuteTableOperationAsync(operation);
}
catch (Exception ex)
{
error = ex;
}

if (TryAbortBatch(batch, error))
{
// there is no error to save in sync error and no result to capture
// this operation will be executed again next time the push happens
return false;
}
}
if (error != null)
{
await TryUpdateOperationState(operation, MobileServiceTableOperationState.Failed, batch);

// save the result if ExecuteTableOperation did not throw
if (error == null && result.IsValidItem() && operation.CanWriteResultToStore)
if (TryAbortBatch(batch, error))
{
await TryStoreOperation(() => this.Store.UpsertAsync(operation.TableName, result, fromServer: true), batch, Resources.SyncStore_FailedToUpsertItem);
// there is no error to save in sync error and no result to capture
// this operation will be executed again next time the push happens
return false;
}
else if (error != null)
}

// save the result if ExecuteTableOperation did not throw
if (error == null && result.IsValidItem() && operation.CanWriteResultToStore)
{
await TryStoreOperation(() => this.Store.UpsertAsync(operation.TableName, result, fromServer: true), batch, Resources.SyncStore_FailedToUpsertItem);
}
else if (error != null)
{
HttpStatusCode? statusCode = null;
string rawResult = null;
var iox = error as MobileServiceInvalidOperationException;
if (iox != null && iox.Response != null)
{
HttpStatusCode? statusCode = null;
string rawResult = null;
var iox = error as MobileServiceInvalidOperationException;
if (iox != null && iox.Response != null)
{
statusCode = iox.Response.StatusCode;
Tuple<string, JToken> content = await MobileServiceTable.ParseContent(iox.Response, this.client.SerializerSettings);
rawResult = content.Item1;
result = content.Item2.ValidItemOrNull();
}
var syncError = new MobileServiceTableOperationError(operation.Id,
operation.Version,
operation.Kind,
statusCode,
operation.TableName,
operation.Item,
rawResult,
result)
{
TableKind = this.tableKind,
Context = this.context
};
await batch.AddSyncErrorAsync(syncError);
statusCode = iox.Response.StatusCode;
Tuple<string, JToken> content = await MobileServiceTable.ParseContent(iox.Response, this.client.SerializerSettings);
rawResult = content.Item1;
result = content.Item2.ValidItemOrNull();
}

bool success = error == null;
return success;
var syncError = new MobileServiceTableOperationError(operation.Id,
operation.Version,
operation.Kind,
statusCode,
operation.TableName,
operation.Item,
rawResult,
result)
{
TableKind = this.tableKind,
Context = this.context
};
await batch.AddSyncErrorAsync(syncError);
}

bool success = error == null;
return success;
}

private async Task TryUpdateOperationState(MobileServiceTableOperation operation, MobileServiceTableOperationState state, OperationBatch batch)
Expand Down

0 comments on commit a28ae32

Please sign in to comment.