public async Task <bool> TryStartUpdateSession(string appId) { Trace.TraceInformation( $"Instance {_instanceId} will attempt to start update session for " + $"ApplicationId = {appId}, UpdateDomain = {_instanceUpdateDomain}"); UpdateSessionTransaction transaction = new UpdateSessionTransaction(_clusterId, _instanceId, _instanceUpdateDomain, appId); UpdateSessionStatus updateSessionStatus = await _updateSessionTable.FetchUpdateSessionStatus(_clusterId, appId); if (updateSessionStatus.UpdateDomainEntity == null || updateSessionStatus.UpdateDomainEntity.UpdateDomain == _instanceUpdateDomain) { if (updateSessionStatus.UpdateDomainEntity == null) { transaction.InsertUpdateDomain(); } transaction.MarkInstanceListAsModified(); } else if (!updateSessionStatus.InstancesEntities.Any()) // no instance in the current update domain is updating { // set a new update domain (if no other instance beats us to it) transaction.ReplaceUpdateDomain(updateSessionStatus); // will fail if current update domain changes transaction.FailIfInstanceListModified(updateSessionStatus); // will fail if instance list changes } else { return(false); } // enlist the current instance (this will succeed even if the active update domain is different but we // won't start the update session, see below) transaction.InsertOrReplaceInstance(); if (await _updateSessionTable.TryExecuteTransaction(transaction)) { // handle the case where an instance enlisted itself after the update domain has changed, string updateDomain = await _updateSessionTable.GetActiveUpdateDomain(_clusterId, appId); if (updateDomain != _instanceUpdateDomain) { // Note that deleting this row is optional because it will filtered out anyway when list of instances // of the active update domain is loaded (as a result, it's not an issue if this fails). // We delete it anyway to keep the table clean. await _updateSessionTable.DeleteInstanceEntity(_clusterId, _instanceId, appId); return(false); } Trace.TraceInformation( $"Instance {_instanceId} successfully started the update session for " + $"ApplicationId = {appId}, UpdateDomain = {_instanceUpdateDomain}"); return(true); } return(false); }
public async Task <bool> TryExecuteTransaction(UpdateSessionTransaction transaction) { try { await _table.ExecuteBatchAsync(transaction.BatchOperation); return(true); } catch (StorageException e) { if (e.RequestInformation.HttpStatusCode != 412 && // insert operation of an entity that already exists e.RequestInformation.HttpStatusCode != 409 // optimistic concurrency conflict based on Etag ) { throw; } } return(false); }