/// <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; } } } }