Esempio n. 1
0
        /// <summary>
        /// Synchronizes the specified job.
        /// </summary>
        /// <param name="job">The job.</param>
        /// <param name="filterBuilders">The filter builders.</param>
        /// <param name="fieldUpdaters">The field updaters.</param>
        /// <param name="item">The item.</param>
        /// <param name="context">The context.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="System.ArgumentException">At least one key field should be specified.</exception>
        /// <exception cref="System.NotSupportedException"></exception>
        private bool Synchronize(
            IProcessSynchronizer job,
            IList<IFieldFilterBuilder> filterBuilders,
            IList<IFieldUpdater> fieldUpdaters,
            ProviderItem item,
            SynchronizationContext context)
        {
            if (filterBuilders.Count == 0)
                throw new ArgumentException("At least one key field should be specified.");

            var failedAttempts = 0;
            Random random = null;

            while (true)
            {
                try
                {
                    using (var transactionScope = TransactionUtils.CreateTransactionScope())
                    {
                        var dynamicItem = job.CreateDynamicItem(item);
                        var filterList = filterBuilders.Select(filterBuilder => filterBuilder.GetFilter(dynamicItem)).ToList();
                        var itemsToSynchronize = RuntimeDatabase.FindItems(job.ProcessName, filterList);
                        bool isSuccessful;

                        switch (job.Action)
                        {
                            case ESyncAction.Insert:
                                isSuccessful = itemsToSynchronize.Count > 0 || ExecuteInsert(job, fieldUpdaters, dynamicItem, context);
                                break;

                            case ESyncAction.Update:
                                isSuccessful = UpdateItems(job, itemsToSynchronize, fieldUpdaters, dynamicItem, context);
                                break;

                            case ESyncAction.InsertOrUpdate:
                                isSuccessful = itemsToSynchronize.Count > 0
                                                   ? UpdateItems(job, itemsToSynchronize, fieldUpdaters, dynamicItem, context)
                                                   : ExecuteInsert(job, fieldUpdaters, dynamicItem, context);
                                break;

                            default:
                                throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Action \"{0}\" is not supported.", job.Action));
                        }

                        if (isSuccessful)
                            transactionScope.Complete();

                        return isSuccessful;
                    }
                }
                catch (Exception ex)
                {
                    ++failedAttempts;

                    if (failedAttempts < MaximumAttempts && CanRetry(ex))
                    {
                        Logger.Log(LogSeverity.Error, "eSync", ex);
                        Logger.Log(LogSeverity.Warning, "eSync", "A recoverable error occurred. The transaction will be rerun.");

                        if (random == null)
                        {
                            random = new Random(Thread.CurrentThread.ManagedThreadId);
                        }

                        var delay = MinimumRetryDelay + TimeSpan.FromSeconds((MaximumRetryDelay - MinimumRetryDelay).TotalSeconds * random.NextDouble());

                        Thread.Sleep(delay);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }