/// <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; } } } }
/// <summary> /// Logs the error. /// </summary> /// <param name="session">The session.</param> /// <param name="message">The message.</param> /// <param name="stackTrace">The stack trace.</param> /// <param name="item">The item.</param> private void LogError(IESyncSession session, string message, string stackTrace = "", ProviderItem item = null) { if (session == null) return; try { var error = DynamicTypeManager.NewEditableRoot<IESyncError>(Constants.ESyncErrorProcessName); error.AllowLazyLoading = true; error.SessionId = session.Id; error.Message = message; error.StackTrace = stackTrace; error.Item = item != null ? item.GetXElement().ToString() : string.Empty; ((ISavable)error).Save(); } catch (Exception ex) { Logger.Log(LogSeverity.Error, "LOG ESYNC ERROR", ex); } }