Пример #1
0
Файл: Info.cs Проект: lr030/ML
        internal static void TryFlushCachedModel(T model, Mutator mutator = null)
        {
            if (!(Configuration?.UseCaching == true && Current.Cache.OperationalStatus == EOperationalStatus.Operational))
            {
                return;
            }

            var key = mutator?.KeyPrefix + model.GetDataKey();

            CacheFactory.FlushModel <T>(key);
        }
Пример #2
0
Файл: Data.cs Проект: lr030/ML
        private static BulkDataOperation <T> BulkExecute(EActionType type, IEnumerable <T> models, Mutator mutator = null, bool rawMode = false)
        {
            ValidateState(type);

            var    logStep = "";
            object logObj  = null;

            if (models == null)
            {
                return(null);
            }

            var modelSet   = models.ToList();
            var modelCount = modelSet.Count;

            var silent = modelCount == 1 || Info <T> .Settings.Silent;

            var _timed = new TimeLog();

            if (modelSet.Count == 0)
            {
                return(null);
            }

            var resultPackage = new BulkDataOperation <T> {
                Type = type
            };

            // First let's obtain any ServiceTokenGuid set by the user.

            lock (_bulkSaveLock)
            {
                try
                {
                    var     successSet = new List <T>();
                    var     failureSet = new List <T>();
                    Clicker logClicker = null;

                    _timed.Start($"{type} bulk [Warm-up]", !silent);
                    if (!silent)
                    {
                        logClicker = modelSet.GetClicker(_timed.CurrentMessage, !silent);
                    }

                    resultPackage.Control = new ConcurrentDictionary <string, DataOperationControl <T> >();

                    var paralelizableClicker = logClicker;

                    if (!rawMode)
                    {
                        Parallel.ForEach(modelSet, new ParallelOptions {
                            MaxDegreeOfParallelism = 5
                        }, item =>
                        {
                            paralelizableClicker?.Click();

                            if (item.IsNew())
                            {
                                var tempKey = mutator?.KeyPrefix + item.ToJson().Sha512Hash();

                                if (resultPackage.Control.ContainsKey(tempKey))
                                {
                                    if (!silent)
                                    {
                                        Current.Log.Warn <T>(_timed.Log($"    [Warm-up] duplicated key: {tempKey}"));
                                    }
                                    failureSet.Add(item);
                                }
                                else
                                {
                                    resultPackage.Control[tempKey] = new DataOperationControl <T> {
                                        Current = item, IsNew = true, Original = null
                                    };
                                }

                                return;
                            }

                            var modelKey = mutator?.KeyPrefix + item.GetDataKey();

                            if (resultPackage.Control.ContainsKey(modelKey))
                            {
                                if (!silent)
                                {
                                    Current.Log.Warn <T>(_timed.Log($"Repeated Identifier: {modelKey}. Data: {item.ToJson()}"));
                                }
                                return;
                            }

                            resultPackage.Control[modelKey] = new DataOperationControl <T> {
                                Current = item
                            };
                        });

                        logClicker?.End();

                        _timed.Log($"{type} bulk  [Before]", false);

                        logClicker = modelSet.GetClicker(_timed.CurrentMessage);

                        logStep = "obtaining original keys";
                        var originalKeys = resultPackage.Control.Where(controlItem => !controlItem.Value.IsNew).Select(controlPair => controlPair.Key).ToList();

                        logStep = "obtaining original models";
                        var originalSet = Get(originalKeys).ToList();

                        logStep = _timed.Log("Populating Control structure");
                        var originalMap = originalSet.ToDictionary(i => i.GetDataKey(), i => i).ToList();

                        foreach (var item in originalMap)
                        {
                            resultPackage.Control[item.Key].Original = item.Value;
                        }

                        logStep = "processing Control structure";

                        foreach (var controlItem in resultPackage.Control)
                        {
                            if (!silent)
                            {
                                logClicker.Click();
                            }

                            var currentModel  = controlItem.Value.Current;
                            var originalModel = controlItem.Value.Original;

                            var canProceed = true;

                            logStep = "checking if model is new";

                            if (!controlItem.Value.IsNew)
                            {
                                logObj = currentModel;

                                originalModel = type == EActionType.Remove ? ProcBeforePipeline(EActionType.Remove, EActionScope.Model, mutator, currentModel, originalModel) : ProcBeforePipeline(controlItem.Value.IsNew ? EActionType.Insert : EActionType.Update, EActionScope.Model, mutator, currentModel, originalModel);

                                if (originalModel == null)
                                {
                                    failureSet.Add(currentModel);
                                    controlItem.Value.Success = false;
                                    controlItem.Value.Message = "Failed ProcBeforePipeline";
                                    canProceed = false;
                                }
                            }
                            else
                            {
                                if (type == EActionType.Remove) // So we're removing a New object. Just ignore.
                                {
                                    failureSet.Add(currentModel);
                                    controlItem.Value.Success = false;
                                    controlItem.Value.Message = $"Invalid {type} operation: Record is New()";
                                    canProceed = false;
                                }
                                else
                                {
                                    originalModel = currentModel;
                                }
                            }

                            if (canProceed)
                            {
                                logStep = "Adding model to process list";
                                logObj  = currentModel;

                                successSet.Add(originalModel);

                                if (type == EActionType.Remove)
                                {
                                    originalModel.BeforeRemove();
                                }
                                else
                                {
                                    if (!originalModel.IsNew())
                                    {
                                        originalModel.BeforeUpdate();
                                    }
                                    else
                                    {
                                        originalModel.BeforeInsert();
                                    }

                                    originalModel.BeforeSave();
                                }

                                controlItem.Value.Success = true;
                            }
                        }

                        if (!silent)
                        {
                            logClicker.End();
                        }

                        logStep = _timed.Log($"{type} {successSet.Count} models");

                        if (type == EActionType.Remove)
                        {
                            Info <T> .Settings.Adapter.BulkRemove(successSet);
                        }
                        else
                        {
                            Info <T> .Settings.Adapter.BulkUpsert(successSet);
                        }

                        if (!silent)
                        {
                            logClicker = modelSet.GetClicker($"{type} bulk   [After]");
                        }

                        logStep = _timed.Log("post-processing individual models");

                        Parallel.ForEach(resultPackage.Control.Where(i => i.Value.Success), new ParallelOptions {
                            MaxDegreeOfParallelism = 5
                        }, controlModel =>
                        {
                            var key = controlModel.Key;
                            if (!silent)
                            {
                                logClicker.Click();
                            }

                            if (type == EActionType.Remove)
                            {
                                controlModel.Value.Current.AfterRemove();
                                ProcAfterPipeline(EActionType.Remove, EActionScope.Model, mutator, controlModel.Value.Current, controlModel.Value.Original);
                            }
                            else
                            {
                                if (controlModel.Value.IsNew)
                                {
                                    controlModel.Value.Current.AfterInsert(key);
                                }
                                else
                                {
                                    controlModel.Value.Current.AfterUpdate(key);
                                }

                                controlModel.Value.Current.AfterSave(key);

                                ProcAfterPipeline(controlModel.Value.IsNew ? EActionType.Insert : EActionType.Update, EActionScope.Model, mutator, controlModel.Value.Current, controlModel.Value.Original);
                            }

                            CacheFactory.FlushModel <T>(key);
                        });

                        resultPackage.Success = successSet;
                        resultPackage.Failure = failureSet;

                        logStep = _timed.Log($"{type} bulk operation complete. Success: {resultPackage.Success.Count} | Failure: {resultPackage.Failure.Count}");

                        if (!silent)
                        {
                            logClicker.End();
                        }
                        _timed.End(false);
                    }
                    else //RawMode means no triggers. AT ALL.
                    {
                        if (type == EActionType.Remove)
                        {
                            Info <T> .Settings.Adapter.BulkRemove(modelSet);
                        }
                        else
                        {
                            Info <T> .Settings.Adapter.BulkUpsert(modelSet);
                        }
                    }

                    return(resultPackage);
                }
                catch (Exception e)
                {
                    if (!silent)
                    {
                        Current.Log.Add <T>(e);
                    }
                    var ex = new Exception($"{type} - Error while {logStep} {logObj?.ToJson()}: {e.Message}", e);

                    _timed.End();
                    throw ex;
                }
            }
        }