示例#1
0
        /// <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
            }
        }
示例#2
0
        /// <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);
        }