private static async Task <ScheduleView> GetScheduleView(Guid sid) { using (var scope = new Core.ScopeDbContext()) { var db = scope.GetDbContext(); var model = db.Schedules.FirstOrDefault(x => x.Id == sid && x.Status != (int)ScheduleStatus.Deleted); if (model != null) { ScheduleView view = new ScheduleView() { Schedule = model }; view.Keepers = (from t in db.ScheduleKeepers join u in db.SystemUsers on t.UserId equals u.Id where t.ScheduleId == model.Id && !string.IsNullOrEmpty(u.Email) select new KeyValuePair <string, string>(u.RealName, u.Email) ).ToList(); view.Children = (from c in db.ScheduleReferences join t in db.Schedules on c.ChildId equals t.Id where c.ScheduleId == model.Id && c.ChildId != model.Id select new { t.Id, t.Title } ).ToDictionary(x => x.Id, x => x.Title); await LoadPluginFile(db, model); return(view); } throw new InvalidOperationException($"不存在的任务id:{sid}"); } }
private static ScheduleContext GetScheduleContext(Guid sid) { using (var scope = new Core.ScopeDbContext()) { var db = scope.GetDbContext(); var model = db.Schedules.FirstOrDefault(x => x.Id == sid && x.Status != (int)ScheduleStatus.Deleted); if (model != null) { ScheduleContext context = new ScheduleContext() { Schedule = model }; if (model.MetaType == (int)ScheduleMetaType.Http) { context.HttpOption = db.ScheduleHttpOptions.FirstOrDefault(x => x.ScheduleId == sid); } context.Keepers = (from t in db.ScheduleKeepers join u in db.SystemUsers on t.UserId equals u.Id where t.ScheduleId == model.Id && !string.IsNullOrEmpty(u.Email) select new KeyValuePair <string, string>(u.RealName, u.Email) ).ToList(); context.Children = (from c in db.ScheduleReferences join t in db.Schedules on c.ChildId equals t.Id where c.ScheduleId == model.Id && c.ChildId != model.Id select new { t.Id, t.Title } ).ToDictionary(x => x.Id, x => x.Title); return(context); } throw new InvalidOperationException($"不存在的任务id:{sid}"); } }
public static void Register() { var setting = ConfigurationCache.NodeSetting; using (var scope = new Core.ScopeDbContext()) { bool isCreate = false; var db = scope.GetDbContext(); var node = db.ServerNodes.FirstOrDefault(x => x.NodeName == setting.IdentityName); if (node == null) { isCreate = true; node = new ServerNodeEntity(); } node.NodeName = setting.IdentityName; node.NodeType = setting.Role; node.MachineName = Environment.MachineName; node.AccessProtocol = setting.Protocol; node.Host = $"{setting.IP}:{setting.Port}"; node.AccessSecret = Guid.NewGuid().ToString("n"); node.Status = 2; node.LastUpdateTime = DateTime.Now; if (isCreate) { db.ServerNodes.Add(node); } db.SaveChanges(); } }
/// <summary> /// 更新节点状态 /// </summary> /// <param name="isStarted"></param> /// <param name="isOnStop"></param> private static void MarkNode(bool isStarted, bool isOnStop = false) { var setting = ConfigurationCache.NodeSetting; using (var scope = new Core.ScopeDbContext()) { bool isCreate = false; var db = scope.GetDbContext(); var node = db.ServerNodes.FirstOrDefault(x => x.NodeName == setting.IdentityName); if (isStarted) { if (node == null) { isCreate = true; node = new ServerNodeEntity(); } string secret = Guid.NewGuid().ToString("n"); node.NodeName = setting.IdentityName; node.NodeType = setting.Role; node.MachineName = setting.MachineName; node.AccessProtocol = setting.Protocol; node.Host = $"{setting.IP}:{setting.Port}"; node.Priority = setting.Priority; node.MaxConcurrency = setting.MaxConcurrency; node.Status = 2; node.AccessSecret = secret; if (isCreate) { db.ServerNodes.Add(node); } else { db.ServerNodes.Update(node); } if (db.SaveChanges() > 0) { AccessSecret = secret; } } else { if (node != null) { node.Status = isOnStop ? 0 : 1; node.AccessSecret = null; db.ServerNodes.Update(node); if (db.SaveChanges() > 0) { AccessSecret = string.Empty; } } //释放锁 db.Database.ExecuteSqlRaw( $"update schedulelocks set status=0,lockedtime=null,lockednode=null where status=1 and lockednode='{setting.IdentityName}'"); } } }
public static void Shutdown() { using (var scope = new Core.ScopeDbContext()) { var db = scope.GetDbContext(); var node = db.ServerNodes.FirstOrDefault(x => x.NodeName == ConfigurationCache.NodeSetting.IdentityName); if (node != null) { node.Status = 0; db.SaveChanges(); } } }
/// <summary> /// 根据任务id插入 /// </summary> /// <param name="sid"></param> /// <returns></returns> public static async Task <bool> InsertById(Guid sid) { bool success = false; using (var scope = new Core.ScopeDbContext()) { var entity = await scope.GetDbContext().ScheduleDelayeds.FirstOrDefaultAsync(x => x.Id == sid && x.Status != (int)ScheduleDelayStatus.Ready); if (entity != null) { return(InsertByEntity(entity)); } } return(success); }
/// <summary> /// 节点恢复就绪任务 /// </summary> private static void ReadyRecovery() { using (var scope = new Core.ScopeDbContext()) { var db = scope.GetDbContext(); List <ScheduleDelayedEntity> list = (from t in db.ScheduleDelayeds join e in db.ScheduleExecutors on t.Id equals e.ScheduleId where e.WorkerName == ConfigurationCache.NodeSetting.IdentityName && t.Status == (int)ScheduleDelayStatus.Ready select t).ToList(); list.AsParallel().ForAll(t => { InsertByEntity(t); }); } }
private static void StartedEvent(Guid sid, DateTime?nextRunTime) { using (var scope = new Core.ScopeDbContext()) { var db = scope.GetDbContext(); //每次运行成功后更新任务的运行情况 var task = db.Schedules.FirstOrDefault(x => x.Id == sid); if (task == null) { return; } task.LastRunTime = DateTime.Now; task.NextRunTime = nextRunTime; task.TotalRunCount += 1; db.SaveChanges(); } }
/// <summary> /// 更新节点状态 /// </summary> /// <param name="isStarted"></param> /// <param name="isOnStop"></param> private static void MarkNode(bool isStarted, bool isOnStop = false) { var setting = ConfigurationCache.NodeSetting; using (var scope = new Core.ScopeDbContext()) { bool isCreate = false; var db = scope.GetDbContext(); var node = db.ServerNodes.FirstOrDefault(x => x.NodeName == setting.IdentityName); if (isStarted) { if (node == null) { isCreate = true; node = new ServerNodeEntity(); } node.NodeName = setting.IdentityName; node.NodeType = setting.Role; node.MachineName = Environment.MachineName; node.AccessProtocol = setting.Protocol; node.Host = $"{setting.IP}:{setting.Port}"; node.Priority = setting.Priority; node.Status = 2; node.AccessSecret = Guid.NewGuid().ToString("n"); if (isCreate) { db.ServerNodes.Add(node); } } else { if (node != null) { node.Status = isOnStop ? 0 : 1; if (isOnStop) { node.AccessSecret = null; } } } if (db.SaveChanges() > 0) { AccessSecret = node.AccessSecret; } } }
/// <summary> /// 根据条件删除日志 /// </summary> /// <param name="sid"></param> /// <param name="category"></param> /// <param name="startdate"></param> /// <param name="enddate"></param> /// <returns></returns> public async Task <int> DeleteLog(Guid?sid, int?category, DateTime?startdate, DateTime?enddate) { IQueryable <SystemLogEntity> query = _repositoryFactory.SystemLogs.Table; StringBuilder sqlBulder = new StringBuilder("delete from systemlogs where 1=1 "); if (sid.HasValue) { query = query.Where(x => x.ScheduleId == sid.Value); sqlBulder.Append($"and scheduleid='{sid.Value}' "); } if (category.HasValue) { query = query.Where(x => x.Category == category.Value); sqlBulder.Append($"and category={category.Value} "); } if (startdate.HasValue) { query = query.Where(x => x.CreateTime >= startdate.Value); sqlBulder.Append($"and createtime>='{startdate.Value.ToString("yyyy-MM-dd")}' "); } if (enddate.HasValue) { query = query.Where(x => x.CreateTime < enddate.Value); sqlBulder.Append($"and createtime<'{enddate.Value.ToString("yyyy-MM-dd")}' "); } int rows = await query.CountAsync(); _ = Task.Run(() => { using (var scope = new Core.ScopeDbContext()) { scope.GetDbContext().Database.ExecuteSqlRaw(sqlBulder.ToString()); } }); return(rows); }
private static async Task Start(IHosSchedule schedule) { JobDataMap map = new JobDataMap { new KeyValuePair <string, object> ("instance", schedule), }; string jobKey = schedule.Main.Id.ToString(); try { IJobDetail job = JobBuilder.Create().OfType(schedule.GetQuartzJobType()).WithIdentity(jobKey).UsingJobData(map).Build(); //添加监听器 var listener = new JobRunListener(jobKey); listener.OnSuccess += StartedEvent; _scheduler.ListenerManager.AddJobListener(listener, KeyMatcher <JobKey> .KeyEquals(new JobKey(jobKey))); ITrigger trigger = GetTrigger(schedule.Main); await _scheduler.ScheduleJob(job, trigger, schedule.CancellationTokenSource.Token); using (var scope = new Core.ScopeDbContext()) { var db = scope.GetDbContext(); var task = db.Schedules.FirstOrDefault(x => x.Id == schedule.Main.Id); if (task != null) { task.NextRunTime = TimeZoneInfo.ConvertTimeFromUtc(trigger.GetNextFireTimeUtc().Value.UtcDateTime, TimeZoneInfo.Local); await db.SaveChangesAsync(); } } } catch (Exception ex) { throw new SchedulerException(ex); } LogHelper.Info($"任务[{schedule.Main.Title}]启动成功!", schedule.Main.Id); _ = Task.Run(async() => { while (true) { if (schedule.RunnableInstance == null) { break; } var log = schedule.RunnableInstance.ReadLog(); if (log != null) { LogManager.Queue.Write(new SystemLogEntity { Category = log.Category, Message = log.Message, ScheduleId = log.ScheduleId, Node = log.Node, StackTrace = log.StackTrace, TraceId = log.TraceId, CreateTime = log.CreateTime }); } else { await Task.Delay(3000); } } }); }
/// <summary> /// worker健康检查 /// </summary> public void WorkerHealthCheck() { var workers = _repositoryFactory.ServerNodes.Where(x => x.NodeType == "worker" && x.Status != 0).ToList(); if (!workers.Any()) { return; } //允许最大失败次数 int allowMaxFailed = ConfigurationCache.GetField <int>("System_WorkerUnHealthTimes"); if (allowMaxFailed <= 0) { allowMaxFailed = 3; } //遍历处理 workers.ForEach(async(w) => { using (var scope = new Core.ScopeDbContext()) { var db = scope.GetDbContext(); _serverClient.Server = w; //初始化计数器 ConfigurationCache.WorkerUnHealthCounter.TryAdd(w.NodeName, 0); var success = await _serverClient.HealthCheck(); if (success) { w.LastUpdateTime = DateTime.Now; db.ServerNodes.Update(w); await db.SaveChangesAsync(); ConfigurationCache.WorkerUnHealthCounter[w.NodeName] = 0; } else { //获取已失败次数 int failedCount = ConfigurationCache.WorkerUnHealthCounter[w.NodeName]; System.Threading.Interlocked.Increment(ref failedCount); if (failedCount >= allowMaxFailed) { w.Status = 0;//标记下线,实际上可能存在因为网络抖动等原因导致检查失败但worker进程还在运行的情况 db.ServerNodes.Update(w); //释放该节点占据的锁 var locks = db.ScheduleLocks.Where(x => x.LockedNode == w.NodeName && x.Status == 1).ToList(); locks.ForEach(x => { x.Status = 0; x.LockedNode = null; x.LockedTime = null; }); db.ScheduleLocks.UpdateRange(locks); await db.SaveChangesAsync(); //重置计数器 ConfigurationCache.WorkerUnHealthCounter[w.NodeName] = 0; } else { ConfigurationCache.WorkerUnHealthCounter[w.NodeName] = failedCount; } } } }); }