/// <summary> /// /// </summary> /// <param name="delivery"></param> /// <param name="conflictBehavior">Indicates how conflicting deliveries will be handled.</param> /// <param name="importManager">The import manager that will be used to handle conflicting deliveries.</param> public DeliveryRollbackOperation HandleConflicts(DeliveryImportManager importManager, DeliveryConflictBehavior defaultConflictBehavior, bool getBehaviorFromConfiguration = true) { if (this.Delivery.Signature == null) { throw new InvalidOperationException("Cannot handle conflicts before a valid signature is given to the delivery."); } // ================================ // Ticket behavior DeliveryTicketBehavior ticketBehavior = DeliveryTicketBehavior.Abort; if (getBehaviorFromConfiguration) { string configuredTicketBehavior; if (Instance.Configuration.Options.TryGetValue("TicketBehavior", out configuredTicketBehavior)) { ticketBehavior = (DeliveryTicketBehavior)Enum.Parse(typeof(DeliveryTicketBehavior), configuredTicketBehavior); } } //prevent duplicate data in case two services runing on the same time if (ticketBehavior == DeliveryTicketBehavior.Abort) { using (SqlConnection sqlConnection = new SqlConnection(AppSettings.GetConnectionString("Edge.Core.Services", "SystemDatabase"))) { // @"DeliveryTicket_Get(@deliverySignature:Nvarchar, @deliveryID:Nvarchar, $workflowInstanceID:bigint)" SqlCommand command = EdgeConfiguration.DataManager.CreateCommand(string.Format("{0}({1})", AppSettings.Get(this.GetType(), "DeliveryTicket.SP"), "@deliverySignature:NvarChar,@deliveryID:NvarChar,@workflowInstanceID:bigint"), System.Data.CommandType.StoredProcedure); command.Parameters["@deliverySignature"].Value = Delivery.Signature; command.Parameters["@deliveryID"].Value = Delivery.DeliveryID.ToString("N"); command.Parameters["@workflowInstanceID"].Value = Instance.ParentInstance.InstanceID; command.Parameters["@workflowInstanceID"].Direction = System.Data.ParameterDirection.InputOutput; sqlConnection.Open(); command.Connection = sqlConnection; if (((DeliveryTicketStatus)command.ExecuteScalar()) == DeliveryTicketStatus.ClaimedByOther) { throw new Exception(String.Format("The current delivery signature is currently claimed by service instance ID {0}.", command.Parameters["@workflowInstanceID"].Value)); } } } // ================================ // Conflict behavior DeliveryConflictBehavior behavior = defaultConflictBehavior; if (getBehaviorFromConfiguration) { string configuredBehavior; if (Instance.Configuration.Options.TryGetValue("ConflictBehavior", out configuredBehavior)) { behavior = (DeliveryConflictBehavior)Enum.Parse(typeof(DeliveryConflictBehavior), configuredBehavior); } } if (behavior == DeliveryConflictBehavior.Ignore) { return(null); } Delivery[] conflicting = this.Delivery.GetConflicting(); Delivery[] toCheck = new Delivery[conflicting.Length + 1]; toCheck[0] = this.Delivery; conflicting.CopyTo(toCheck, 1); // Check whether the last commit was not rolled back for each conflicting delivery List <Delivery> toRollback = new List <Delivery>(); foreach (Delivery d in toCheck) { int rollbackIndex = -1; int commitIndex = -1; for (int i = 0; i < d.History.Count; i++) { if (d.History[i].Operation == DeliveryOperation.Committed) { commitIndex = i; } else if (d.History[i].Operation == DeliveryOperation.RolledBack) { rollbackIndex = i; } } if (commitIndex > rollbackIndex) { toRollback.Add(d); } } DeliveryRollbackOperation operation = null; if (toRollback.Count > 0) { if (behavior == DeliveryConflictBehavior.Rollback) { operation = new DeliveryRollbackOperation(); operation.AsyncDelegate = new Action <Delivery[]>(importManager.Rollback); operation.AsyncResult = operation.AsyncDelegate.BeginInvoke(toRollback.ToArray(), null, null); } else { StringBuilder guids = new StringBuilder(); for (int i = 0; i < toRollback.Count; i++) { guids.Append(toRollback[i].DeliveryID.ToString("N")); if (i < toRollback.Count - 1) { guids.Append(", "); } } throw new Exception("Conflicting deliveries found: " + guids.ToString()); } } return(operation); }
/// <summary> /// /// </summary> /// <param name="delivery"></param> /// <param name="conflictBehavior">Indicates how conflicting deliveries will be handled.</param> /// <param name="importManager">The import manager that will be used to handle conflicting deliveries.</param> public void HandleConflicts(DeliveryImportManager importManager, DeliveryConflictBehavior defaultConflictBehavior, bool getBehaviorFromConfiguration = true) { if (this.Delivery.Outputs.Count < 1) { return; } ServiceInstanceInfo parent = this.Instance; while (parent.ParentInstance != null) { parent = parent.ParentInstance; } foreach (DeliveryOutput output in this.Delivery.Outputs) { if (!output.PipelineInstanceID.HasValue) { output.PipelineInstanceID = parent.InstanceID; } } this.Delivery.Save(); // ================================ // Conflict behavior DeliveryConflictBehavior behavior = defaultConflictBehavior; if (getBehaviorFromConfiguration) { string configuredBehavior; if (Instance.Configuration.Options.TryGetValue("ConflictBehavior", out configuredBehavior)) { behavior = (DeliveryConflictBehavior)Enum.Parse(typeof(DeliveryConflictBehavior), configuredBehavior); } } var processing = new List <DeliveryOutput>(); var committed = new List <DeliveryOutput>(); foreach (DeliveryOutput output in this.Delivery.Outputs) { DeliveryOutput[] conflicts = output.GetConflicting(); foreach (DeliveryOutput conflict in conflicts) { if (conflict.PipelineInstanceIsRunning) { processing.Add(conflict); } if (conflict.Status == DeliveryOutputStatus.Committed || conflict.Status == DeliveryOutputStatus.Staged) { committed.Add(conflict); } } } if (processing.Count > 0) { foreach (var output in Delivery.Outputs) { output.Status = DeliveryOutputStatus.Canceled; } this.Delivery.Save(); throw new DeliveryConflictException("There are outputs with the same signatures currently being processed:") { ConflictingOutputs = processing.ToArray() }; // add list of output ids } if (behavior == DeliveryConflictBehavior.Ignore) { return; } if (committed.Count > 0) { foreach (var output in Delivery.Outputs) { output.Status = DeliveryOutputStatus.Canceled; } this.Delivery.Save(); throw new DeliveryConflictException("There are outputs with the same signatures are already committed\\staged:") { ConflictingOutputs = committed.ToArray() }; // add list of output ids } }
/// <summary> /// /// </summary> /// <param name="delivery"></param> /// <param name="conflictBehavior">Indicates how conflicting deliveries will be handled.</param> /// <param name="importManager">The import manager that will be used to handle conflicting deliveries.</param> public void HandleConflicts(DeliveryManager importManager, DeliveryConflictBehavior defaultConflictBehavior, bool getBehaviorFromConfiguration = true) { if (this.Delivery.Outputs.Count < 1) { return; } ServiceInstance parent = this.AsServiceInstance(); while (parent.ParentInstance != null) { parent = parent.ParentInstance; } foreach (DeliveryOutput output in this.Delivery.Outputs) { if (!output.PipelineInstanceID.HasValue) { output.PipelineInstanceID = parent.InstanceID; } } this.Delivery.Save(); // ================================ // Conflict behavior DeliveryConflictBehavior behavior = this.Configuration.ConflictBehavior != null ? this.Configuration.ConflictBehavior.Value : defaultConflictBehavior; var processing = new List <DeliveryOutput>(); var committed = new List <DeliveryOutput>(); foreach (DeliveryOutput output in this.Delivery.Outputs) { DeliveryOutput[] conflicts = output.GetConflicting(); foreach (DeliveryOutput conflict in conflicts) { if (conflict.PipelineInstanceID != null) { ServiceInstance instance = Environment.GetServiceInstance(conflict.PipelineInstanceID.Value, stateInfoOnly: true); if (instance.State != ServiceState.Ended) { processing.Add(conflict); } } if (conflict.Status == DeliveryOutputStatus.Committed || conflict.Status == DeliveryOutputStatus.Staged) { committed.Add(conflict); } } } if (processing.Count > 0) { foreach (var output in Delivery.Outputs) { output.Status = DeliveryOutputStatus.Canceled; } this.Delivery.Save(); throw new DeliveryConflictException("There are outputs with the same signatures currently being processed:") { ConflictingOutputs = processing.ToArray() }; // add list of output ids } if (behavior == DeliveryConflictBehavior.Ignore) { return; } if (committed.Count > 0) { foreach (var output in Delivery.Outputs) { output.Status = DeliveryOutputStatus.Canceled; } this.Delivery.Save(); throw new DeliveryConflictException("There are outputs with the same signatures are already committed\\staged:") { ConflictingOutputs = committed.ToArray() }; // add list of output ids } }