Beispiel #1
0
        public async Task RefreshLiveStates(bool fast)
        {
            try
            {
                var watch = new Stopwatch();
                watch.Start();
                var indexCodes = StaticData.Instruments
                                 .Where(x => x.Flow != (byte)FlowTypes.Ati && x.CompanyCode != Constants.CompanyCodes.IDXS)
                                 .Select(x => x.InsCode)
                                 .ToList();

                if (fast)
                {
                    indexCodes.RemoveFromIList(x => !Online.Data.ContainsKey(x));
                }

                OnOperationStart?.Invoke(this, indexCodes.Count * 2 + 3);

                var liveSrv   = StaticServiceFactory.Create <ILiveInstDataService>();
                var today     = DateTime.Now.Date;
                var savedData = await liveSrv.GetDefaultQuery()
                                .Where(x => x.DEven >= today)
                                .ToListAsync();

                OnOperationStep?.Invoke(this, EventArgs.Empty);
                int i = 0;
                var readWebSiteBlock = new TransformBlock <long, LiveInstData>(
                    async inxCode =>
                {
                    InstrumentLastInfo ins = null;
                    try
                    {
                        ins = await Online.FindAsync(null, inxCode);
                    }
                    catch (Exception ex)
                    {
                        _logger.WarnFormat("Cannot find instrument by code {0}; operation skip from this error.", ex, inxCode);
                        return(null);
                    }
                    if (ins == null)
                    {
                        _logger.WarnFormat("cannot find instrument with code {0}", inxCode);
                        return(null);
                    }
                    else
                    {
                        _logger.InfoFormat("instance {0} live data fetched {1}% completed", inxCode, Math.Ceiling(i++ *1.0 / indexCodes.Count * 100));
                    }

                    var r = new LiveInstData();
                    foreach (var field in r.GetFields().Where(x => x.Kind == FieldKinds.Primitive))
                    {
                        var value = ins.GetPropertyValue(field.Name);
                        r.SetValue(field.Name, Typing.ChangeType(value, field.PropertyType));
                    }
                    OnOperationStep?.Invoke(this, EventArgs.Empty);
                    return(r);
                }, new ExecutionDataflowBlockOptions
                {
                    MaxDegreeOfParallelism = 15
                });

                List <LiveInstData> newData   = new List <LiveInstData>();
                List <LiveInstData> dirtyData = new List <LiveInstData>();
                var writeLiveInstData         = new ActionBlock <LiveInstData>(r =>
                {
                    if (r == null)
                    {
                        return;
                    }

                    var savedInst = savedData.FirstOrDefault(x => x.InsCode == r.InsCode);
                    if (savedInst != null)
                    {
                        savedInst.ResetChanges();
                        foreach (var field in r.GetFields().Where(x => x.Kind == FieldKinds.Primitive))
                        {
                            var value = r.GetPropertyValue(field.Name);
                            savedInst.SetValue(field.Name, Typing.ChangeType(value, field.PropertyType));
                        }
                        if (savedInst.ChangeTracker.State == ObjectState.Modified)
                        {
                            dirtyData.Add(savedInst);
                        }
                    }
                    else
                    {
                        r.DEven = today;
                        newData.Add(r);
                    }

                    OnOperationStep?.Invoke(this, EventArgs.Empty);
                });

                readWebSiteBlock.LinkTo(writeLiveInstData);


                foreach (var code in indexCodes)
                {
                    readWebSiteBlock.Post(code);
                }

                readWebSiteBlock.Complete();
                await readWebSiteBlock.Completion;

                var ov = ObjectRegistry.GetObject <IValidationProvider>();
                newData.RemoveFromIList(x => !ov.Validate(x, Mode.OnInsert.ToString()).IsValid);
                if (newData.Count > 0)
                {
                    await liveSrv.Repository.BulkInsertAsync(newData);
                }
                OnOperationStep?.Invoke(this, EventArgs.Empty);

                dirtyData.RemoveFromIList(x => !ov.Validate(x, Mode.OnUpdate.ToString()).IsValid);
                if (dirtyData.Count > 0)
                {
                    await liveSrv.SaveEntitiesAsync(dirtyData.ToArray());
                }
                OnOperationStep?.Invoke(this, EventArgs.Empty);

                newData.Clear();
                newData.TrimExcess();
                dirtyData.Clear();
                dirtyData.TrimExcess();

                watch.Stop();
                _logger.InfoFormat("RefreshLiveStates take {0}ms", watch.ElapsedMilliseconds);
                OnOperationCompleted?.Invoke(this, EventArgs.Empty);
            }
            catch (Exception exception)
            {
                _logger.Error("RefreshLiveStates", exception);
                OnOperationBreak?.Invoke(this, exception);
            }
        }