Esempio n. 1
0
        /// <summary>
        /// Adds the validation errors.
        /// </summary>
        /// <param name="editItem">The edit item.</param>
        /// <param name="context">The context.</param>
        private static void AddValidationErrors(IEditableRoot editItem, SynchronizationContext context)
        {
            var brokenRules = ((IBusinessObject)editItem).GetAllBrokenRules(true);

            context.AddError(
                editItem.Id > 0
                    ? string.Format(CultureInfo.InvariantCulture, "Item {0} is invalid and cannot be saved.", editItem.Id)
                    : "Item is invalid and cannot be saved.");

            foreach (var brokenRule in brokenRules.Where(x => !string.IsNullOrEmpty(x.Description)))
                context.AddError(brokenRule.Description);
        }
Esempio n. 2
0
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <exception cref="System.InvalidOperationException">No key fields were specified.</exception>
        public void Execute(JobExecutionContext context)
        {
            var startTime = DateTime.Now;

            Ioc.SatisfyImportsOnce(this);

            var processName = string.Empty;

            try
            {
                processName = GetProcessName(context);
                var isSuccessful = true;

                Logger.Log(
                    LogSeverity.Information,
                    "ESYNC",
                    string.Format(CultureInfo.InvariantCulture, "Process \"{0}\" synchronization started.", processName));

                var synchronizer = GetProcessSynchronizer(context);
                var session = CreateESyncSession(startTime, context);

                try
                {
                    var filterBuilders = CreateKeyFilterBuilders(synchronizer);
                    if (filterBuilders.Count == 0)
                        throw new InvalidOperationException("No key fields were specified.");

                    var fieldUpdaters = CreateFieldUpdaters(synchronizer);

                    var dpContext = new DataProviderContext();
                    var lastSuccessfulSession = GetLastSuccessfulSession(synchronizer);
                    if (lastSuccessfulSession != null)
                        dpContext.LastSuccessDate = lastSuccessfulSession.EndTime;

                    var data = GetData(synchronizer.DataProvider, dpContext);

                    session = LogItemsRetrieved(session, data.Count);

                    for (var i = 0; i < data.Count; ++i)
                    {
                        if (SyncServiceJob.IsStopped)
                        {
                            isSuccessful = false;
                            LogError(session, "The synchronization session was stopped.");
                            break;
                        }

                        var item = data[i];
                        var syncContext = new SynchronizationContext();

                        try
                        {
                            var result = Synchronize(synchronizer, filterBuilders, fieldUpdaters, item, syncContext);

                            isSuccessful = isSuccessful && result;

                            if (!result || syncContext.Errors.Count > 0 || syncContext.Warnings.Count > 0)
                            {
                                var description = GetDescription(syncContext);

                                Logger.Log(
                                    LogSeverity.Error,
                                    "ESYNC",
                                    string.Format(
                                        CultureInfo.InvariantCulture,
                                        "Synchronization failed for process \"{0}\", record {1}:{2}{3}",
                                        processName,
                                        i + 1,
                                        Environment.NewLine,
                                        description));

                                LogError(
                                    session,
                                    string.Format(CultureInfo.InvariantCulture, "Failed to synchronize record {0}.", i + 1),
                                    description,
                                    item);
                            }
                        }
                        catch (Exception ex)
                        {
                            isSuccessful = false;

                            Logger.Log(LogSeverity.Error, "ESYNC", ex);
                            LogError(session, string.Format(CultureInfo.InvariantCulture, "Failed to synchronize record {0}.", i + 1), ex.ToString());
                        }
                    }
                }
                catch (Exception ex)
                {
                    isSuccessful = false;
                    Logger.Log(LogSeverity.Error, "ESYNC", ex);
                    LogError(session, ex.Message, ex.ToString());
                }

                if (session != null)
                {
                    session.EndTime = DateTime.Now;
                    session.IsSuccessful = isSuccessful;
                    ((ISavable)session).Save();
                }
            }
            catch (Exception ex)
            {
                Logger.Log(LogSeverity.Error, GetType().ToString(), ex);
            }
            finally
            {
                //Csla.ApplicationContext.User = new UnauthenticatedPrincipal();
                Logger.Log(LogSeverity.Information, "ESYNC", string.Format(CultureInfo.InvariantCulture, "Process \"{0}\" synchronization finished.", processName));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Executes the update.
        /// </summary>
        /// <param name="job">The job.</param>
        /// <param name="itemId">The item identifier.</param>
        /// <param name="fieldUpdaters">The field updaters.</param>
        /// <param name="dynamicItem">The dynamic item.</param>
        /// <param name="context">The context.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        private bool ExecuteUpdate(
            IProcessSynchronizer job,
            int itemId,
            IEnumerable<IFieldUpdater> fieldUpdaters,
            ISyncDynamicItem dynamicItem,
            SynchronizationContext context)
        {
            try
            {
                var criteria = new DetailCriteria(itemId) { AllowLazyLoading = true };
                var editItem = DynamicTypeManager.GetEditableRoot<IEditableRoot>(job.ProcessName, criteria);

                if (editItem == null || editItem.Id != itemId)
                {
                    context.AddError(string.Format(CultureInfo.InvariantCulture, "Failed to load item with Id = {0}.", itemId));
                    return false;
                }

                foreach (var fieldUpdater in fieldUpdaters)
                {
                    fieldUpdater.Update(dynamicItem, editItem);

                    if (fieldUpdater.IsKey)
                    {
                        editItem.KeyFields.Add(fieldUpdater.FieldName);
                    }
                }

                if (!((ITrackStatus)editItem).IsValid)
                {
                    AddValidationErrors(editItem, context);
                    return false;
                }

                ((ISavable)editItem).Save();

                return true;
            }
            catch (Exception ex)
            {
                context.AddException(ex);
            }

            return false;
        }
Esempio n. 4
0
 /// <summary>
 /// Updates the items.
 /// </summary>
 /// <param name="job">The job.</param>
 /// <param name="itemsToSynchronize">The items to synchronize.</param>
 /// <param name="fieldUpdaters">The field updaters.</param>
 /// <param name="dynamicItem">The dynamic item.</param>
 /// <param name="context">The context.</param>
 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
 private bool UpdateItems(
     IProcessSynchronizer job,
     IEnumerable<int> itemsToSynchronize,
     IEnumerable<IFieldUpdater> fieldUpdaters,
     ISyncDynamicItem dynamicItem,
     SynchronizationContext context)
 {
     return itemsToSynchronize.Aggregate(true, (current, id) => current && ExecuteUpdate(job, id, fieldUpdaters, dynamicItem, context));
 }
Esempio n. 5
0
        /// <summary>
        /// Executes the insert.
        /// </summary>
        /// <param name="job">The job.</param>
        /// <param name="fieldUpdaters">The field updaters.</param>
        /// <param name="dynamicItem">The dynamic item.</param>
        /// <param name="context">The context.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        private bool ExecuteInsert(
            IProcessSynchronizer job, IEnumerable<IFieldUpdater> fieldUpdaters, ISyncDynamicItem dynamicItem, SynchronizationContext context)
        {
            try
            {
                var editItem = DynamicTypeManager.NewEditableRoot<IEditableRoot>(job.ProcessName);
                editItem.AllowLazyLoading = true;

                foreach (var fieldUpdater in fieldUpdaters)
                {
                    fieldUpdater.Update(dynamicItem, editItem);

                    if (fieldUpdater.IsKey)
                    {
                        editItem.KeyFields.Add(fieldUpdater.FieldName);
                    }
                }

                if (!((ITrackStatus)editItem).IsValid)
                {
                    AddValidationErrors(editItem, context);
                    return false;
                }

                ((ISavable)editItem).Save();

                return true;
            }
            catch (Exception ex)
            {
                context.AddException(ex);
            }

            return false;
        }
Esempio n. 6
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;
                    }
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Gets the description.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns>System.String.</returns>
        private static string GetDescription(SynchronizationContext context)
        {
            var sb = new StringBuilder();

            if (context.Errors.Count > 0)
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "Errors:").AppendLine();
                foreach (var errorMessage in context.Errors)
                {
                    sb.AppendFormat(CultureInfo.InvariantCulture, "- {0}", errorMessage).AppendLine();
                }
            }

            if (context.Warnings.Count > 0)
            {
                if (sb.Length > 0)
                    sb.AppendLine();

                sb.AppendFormat(CultureInfo.InvariantCulture, "Warnings:").AppendLine();
                foreach (var warningMessage in context.Warnings)
                {
                    sb.AppendFormat(CultureInfo.InvariantCulture, "- {0}", warningMessage).AppendLine();
                }
            }

            if (context.Exceptions.Count > 0)
            {
                if (sb.Length > 0)
                    sb.AppendLine();

                sb.AppendFormat(CultureInfo.InvariantCulture, "Exceptions:").AppendLine();
                foreach (var exception in context.Exceptions)
                {
                    sb.AppendLine(exception.ToString());
                }
            }

            return sb.ToString();
        }