Esempio n. 1
0
        private void DoConfigWork(Object state)
        {
            var list = AppConfig.FindAll();
            var next = DateTime.MinValue;

            foreach (var item in list)
            {
                if (!item.Enable || item.PublishTime.Year < 2000)
                {
                    continue;
                }

                using var span = _tracer?.NewSpan("AutoPublish", item);

                // 时间到了,发布,或者计算最近一个到期应用
                if (item.PublishTime <= DateTime.Now)
                {
                    item.Publish();
                }
                else if (item.PublishTime < next || next.Year < 2000)
                {
                    next = item.PublishTime;
                }
            }

            // 如果下一个到期应用时间很短,主动调整定时器
            if (next.Year > 2000)
            {
                var ts = next - DateTime.Now;
                if (ts.TotalMilliseconds < _timer.Period)
                {
                    _timer.SetNext((Int32)ts.TotalMilliseconds);
                }
            }
        }
Esempio n. 2
0
        /// <summary>异步保存</summary>
        public void SaveAsync()
        {
            if (_timer == null)
            {
                _timer = new TimerX(s => Save(_File.GetBasePath(), s as DataCache), this, 100, 10 * 60 * 1000)
                {
                    Async = true
                };
                //_timer = TimerX.Delay(s =>
                //{
                //    Save(_File.GetFullPath(), this);

                //    _timer = null;
                //}, 3000);
            }
            _timer.SetNext(100);
        }
Esempio n. 3
0
        private void Process(Object state)
        {
            var list     = state as ICollection <IEntity>;
            var ss       = Session;
            var dal      = ss.Dal;
            var useTrans = dal.DbType == DatabaseType.SQLite;

            var speed = Speed;

            if (Debug || list.Count > 10000)
            {
                var cost = speed == 0 ? 0 : list.Count * 1000 / speed;
                XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t保存 {list.Count:n0}\t预测耗时 {cost:n0}ms");
            }

            var rs = new List <Int32>();
            var sw = Stopwatch.StartNew();

            // 开启事务保存
            if (useTrans)
            {
                dal.BeginTransaction();
            }
            try
            {
                // 禁用自动关闭连接
                dal.Session.SetAutoClose(false);

                foreach (var item in list)
                {
                    try
                    {
                        // 加入队列时已经Valid一次,这里不需要再次Valid
                        rs.Add(item.SaveWithoutValid());
                    }
                    catch { }
                }

                if (useTrans)
                {
                    dal.Commit();
                }
            }
            catch
            {
                if (useTrans)
                {
                    dal.Rollback();
                }
                throw;
            }
            finally
            {
                sw.Stop();
                dal.Session.SetAutoClose(null);
            }

            // 根据繁忙程度动态调节
            // 大于1000个对象时,说明需要加快持久化间隔,缩小周期
            // 小于1000个对象时,说明持久化太快了,加大周期
            var p = Period;

            if (list.Count > 1000)
            {
                p = p * 1000 / list.Count;
            }
            else
            {
                p = p * 1000 / list.Count;
            }

            // 最小间隔
            if (p < 500)
            {
                p = 500;
            }
            // 最大间隔
            if (p > 5000)
            {
                p = 5000;
            }

            if (p != Period)
            {
                Period        = p;
                _Timer.Period = p;
            }

            var ms = sw.Elapsed.TotalMilliseconds;

            Speed = ms == 0 ? 0 : (Int32)(list.Count * 1000 / ms);
            if (Debug || list.Count > 10000)
            {
                XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t耗时 {ms:n0}ms\t速度 {speed:n0}tps\t周期 {p:n0}ms");
            }

            //if (Completed != null)
            //{
            //    var k = 0;
            //    foreach (var item in list)
            //    {
            //        Completed(this, new EventArgs<IEntity, Int32>(item, rs[k++]));
            //    }
            //}

            // 马上再来一次,以便于连续处理数据
            _Timer.SetNext(-1);
        }
Esempio n. 4
0
        private void Process(Object state)
        {
            var list = state as ICollection <IEntity>;
            var ss   = Session;
            var dal  = ss.Dal;

            var speed = Speed;

            if (Debug || list.Count > 100_000)
            {
                var cost = speed == 0 ? 0 : list.Count * 1000 / speed;
                XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t保存 {list.Count:n0}\t预测耗时 {cost:n0}ms");
            }

            var sw = Stopwatch.StartNew();

            // 分批
            var batchSize = 5000;

            for (var i = 0; i < list.Count();)
            {
                var batch = list.Skip(i).Take(batchSize).ToList();

                try
                {
                    batch.SaveWithoutValid();
                }
                catch (Exception ex)
                {
                    // 保存失败,写回去
                    foreach (var entity in list)
                    {
                        Entities.TryAdd(entity, entity);
                    }
                    Interlocked.Add(ref _count, list.Count);

                    if (Error != null)
                    {
                        Error(this, new EventArgs <Exception>(ex));
                    }
                    else
                    {
                        XTrace.WriteException(ex);
                    }
                }

                i += batch.Count;
            }

            sw.Stop();

            // 根据繁忙程度动态调节
            // 大于1000个对象时,说明需要加快持久化间隔,缩小周期
            // 小于1000个对象时,说明持久化太快了,加大周期
            var p = Period;

            if (list.Count > 1000)
            {
                p = p * 1000 / list.Count;
            }
            else
            {
                p = p * 1000 / list.Count;
            }

            // 最小间隔
            if (p < 500)
            {
                p = 500;
            }
            // 最大间隔
            if (p > 5000)
            {
                p = 5000;
            }

            if (p != Period)
            {
                Period        = p;
                _Timer.Period = p;
            }

            var ms = sw.Elapsed.TotalMilliseconds;

            Speed = ms == 0 ? 0 : (Int32)(list.Count * 1000 / ms);
            if (Debug || list.Count > 10000)
            {
                XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t保存 {list.Count:n0}\t耗时 {ms:n0}ms\t速度 {speed:n0}tps\t周期 {p:n0}ms");
            }

            // 马上再来一次,以便于连续处理数据
            _Timer.SetNext(-1);
        }
Esempio n. 5
0
        public void Start()
        {
            var job = Job;

            // 参数检查
            var expession = job.Cron;

            if (expession.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(job.Cron));
            }

            var cmd = job.Method;

            if (cmd.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(job.Method));
            }

            // 标识相同,不要处理
            var id = $"{expession}@{cmd}";

            if (id == _id && _timer != null)
            {
                return;
            }

            var cron = new Cron();

            if (!cron.Parse(expession))
            {
                throw new InvalidOperationException($"无效表达式 {expession}");
            }

            // 找到类和方法
            var p = cmd.LastIndexOf('.');

            if (p <= 0)
            {
                throw new InvalidOperationException($"无效作业方法 {cmd}");
            }

            var type   = cmd.Substring(0, p).GetTypeEx();
            var method = type?.GetMethodEx(cmd.Substring(p + 1));

            if (method == null || !method.IsStatic)
            {
                throw new InvalidOperationException($"无效作业方法 {cmd}");
            }

            _action = method.As <Action <String> >();
            if (_action == null)
            {
                throw new InvalidOperationException($"无效作业方法 {cmd}");
            }

            JobService.WriteLog("启用", true, $"作业[{job.Name}],定时 {job.Cron},方法 {job.Method}", job);

            // 实例化定时器,原定时器销毁
            _timer.TryDispose();
            _timer = new TimerX(DoJobWork, job, expession)
            {
                Async = true
            };

            // 如果下一次执行时间在未来,表示用户希望尽快执行一次
            var ts = job.NextTime - DateTime.Now;

            if (ts.TotalMilliseconds >= 1000)
            {
                _timer.SetNext((Int32)ts.TotalMilliseconds);
            }
            else
            {
                job.NextTime = _timer.Cron.GetNext(_timer.NextTime);
            }
            job.Update();

            _id = id;
        }