[outsourcing]! Use asp.net core to quickly build the background management system of small start-up companies (IV. quartz simple configuration and use)

The previous chapter introduces the simple configuration of log4net, this chapter introduces the simple use of quartz, the next chapter introduces my permission use, and then it ends

This chapter mainly introduces:

  • The use of quartz in asp.net core

Although this project is small, it is easy to expand, and the business behind it can be directly thrown in, making it more abundant

Bullshit, no introduction

1, Basic class configuration

Define IJobCenter interface in domain

  

The code is as follows:

  

public interface IJobCenter
    {
        /// <summary>
        /// Add scheduled task
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        Task<Result> AddScheduleJobAsync(TaskScheduleModel m);

        /// <summary>
        /// Pause scheduled tasks
        /// </summary>
        /// <param name="jobGroup"></param>
        /// <param name="jobName"></param>
        /// <returns></returns>
        Task<Result> StopScheduleJobAsync(string jobGroup, string jobName);

        /// <summary>
        /// Resume scheduled tasks
        /// </summary>
        /// <param name="jobGroup"></param>
        /// <param name="jobName"></param>
        /// <returns></returns>
        Task<Result> RunScheduleJobAsync(TaskScheduleModel m);
    }

Implementing IJobCenter in infrastructure

  

Remember to introduce nuget of quartz

  

 

The code is as follows:

  

/// <summary>
    /// Task scheduling center
    /// </summary>
    public class JobCenter:IJobCenter
    {
        
        public static IScheduler scheduler = null;
        public static async Task<IScheduler> GetSchedulerAsync()
        {
            if (scheduler != null)
            {
                return scheduler;
            }
            else
            {
                ISchedulerFactory schedf = new StdSchedulerFactory();
                IScheduler sched = await schedf.GetScheduler();
                return sched;
            }
        }
        /// <summary>
        /// Add task plan//Or start after process termination
        /// </summary>
        /// <returns></returns>
        public async Task<Result> AddScheduleJobAsync(TaskScheduleModel m)
        {
            Result result = new Result();
            try
            {
                if (m != null)
                {
                    DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(m.StarRunTime, 1);
                    DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(m.EndRunTime, 1);
                    scheduler = await GetSchedulerAsync();
                    IJobDetail job = JobBuilder.Create<HttpJob>()
                      .WithIdentity(m.JobName, m.JobGroup)
                      .Build();
                    ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                                                 .StartAt(starRunTime)
                                                 .EndAt(endRunTime)
                                                 .WithIdentity(m.JobName, m.JobGroup)
                                                 .WithCronSchedule(m.CronExpress)
                                                 .Build();
                    await scheduler.ScheduleJob(job, trigger);
                    await scheduler.Start();
                    result.Data = m;
                    return result;
                }
                return result.SetError("The incoming entity is empty");
            }
            catch (Exception ex)
            {
                Log4Net.Error($"[JobCenter_AddScheduleJobAsync]_{ex}");
                return result.SetError(ex.Message);
            }
        }

        /// <summary>
        /// Pause the specified task plan
        /// </summary>
        /// <returns></returns>
        public async Task<Result> StopScheduleJobAsync(string jobGroup, string jobName)
        {
            Result result = new Result();
            try
            {
                scheduler = await GetSchedulerAsync();
                //Pause task
                await scheduler.PauseJob(new JobKey(jobName, jobGroup));                
                var status = new StatusViewModel()
                {
                    Status = 0,
                    Msg = "Task plan suspended successfully",
                };
                result.Data = status.GetJson();
                return result;
            }
            catch (Exception ex)
            {
                Log4Net.Error($"[JobCenter_StopScheduleJobAsync]_{ex}");
                var status = new StatusViewModel()
                {
                    Status = -1,
                    Msg = "Failed to pause task plan",
                };
                result.Data = status.GetJson();
                return result;
            }
        }
        /// <summary>
        /// Restore the specified task plan**The task plan after the pause is recovered. If it is recovered after the program breaks down or the process is killed, this method is invalid
        /// </summary>
        /// <returns></returns>
        public async Task<Result> RunScheduleJobAsync(TaskScheduleModel sm)
        {
            Result result = new Result();
            try
            {
                #region Open task
                //scheduler = await GetSchedulerAsync();
                //DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(sm.StarRunTime, 1);
                //DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(sm.EndRunTime, 1);
                //IJobDetail job = JobBuilder.Create<HttpJob>()
                //  .WithIdentity(sm.JobName, sm.JobGroup)
                //  .Build();
                //ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                //                             .StartAt(starRunTime)
                //                             .EndAt(endRunTime)
                //                             .WithIdentity(sm.JobName, sm.JobGroup)
                //                             .WithCronSchedule(sm.CronExpress)
                //                             .Build();
                //await scheduler.ScheduleJob(job, trigger);
                //await scheduler.Start();
                #endregion
                scheduler = await GetSchedulerAsync();
                //resumejob recovery
                await scheduler.ResumeJob(new JobKey(sm.JobName, sm.JobGroup));

                var status = new StatusViewModel()
                {
                    Status = 0,
                    Msg = "Recovery task planned successfully",
                };
                result.Data = status.GetJson();
                return result;
            }
            catch (Exception ex)
            {
                Log4Net.Error($"[JobCenter_RunScheduleJobAsync]_{ex}");
                var status = new StatusViewModel()
                {
                    Status = -1,
                    Msg = "Recovery task plan failed",
                };
                result.Data = status.GetJson();
                return result;
            }
        }
    }

Write a job service extensions extension, in which there is an add job service, which is used to add a startup service in the startup

  

The main function of this extension is to start the program, automatically query my task scheduling management table, query the status of the open task, and add it to the scheduled task

The table structure is roughly as follows:

  

Here we mainly pay attention to task group and task name. Where are these two together? They can be used for a unique task. Later, we will use different task groups and task names in httpjob

Distinguish the different logic they want to execute

  

The code is simple: as follows

  

public class HttpJob : IJob
    {
        
        /// <summary>
        /// adopt group and name Determine which task to execute (task execution logic) business logic is written after
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Execute(IJobExecutionContext context)
        {
            await Task.Run(() =>
            {
                var name = context.JobDetail.Key.Name;
                var group = context.JobDetail.Key.Group;
                if (group=="xx1"&&name=="xx2")
                {
                    //do something
                }

                if (group == "xx2" && name == "xx3")
                {
                    //do something also
                }
                Log4Net.Info($"Perform task_Name:{name}_Grop:{group}");
            });
        }
    }

Add ITaskService interface in domain, as follows

  

The code is as follows:

  

public interface ITaskService
    {
        //Get task list
        Result GetTaskList();
        //Add task
        Task<Result> AddTaskAsync(TaskScheduleModel model);
        //Modify task
        Task<Result> ModifyTaskAsync(TaskScheduleModel model);
        //Delete task
        Task<Result> DelTaskAsync(TaskScheduleModel model);
        //Suspend task
        Result PauseTask();
        //Open task
        Result StartTask();
    }

Implement this interface in application

  

The code is as follows:

public class TaskService : BaseService, ITaskService
    {
        private IJobCenter jobCenter = ServiceCollectionExtension.Get<IJobCenter>();
        private MvcIdentity identity = (ServiceCollectionExtension.HttpContext.User.Identity as MvcIdentity);

        public async Task<Result> AddTaskAsync(TaskScheduleModel model)
        {
            Result result = new Result();

            if (model == null)
            {
                return result.SetError("Model Cannot be empty!");
            }
            if (string.IsNullOrEmpty(model.JobName))
            {
                return result.SetError("JobName Cannot be empty!");
            }
            if (string.IsNullOrEmpty(model.JobGroup))
            {
                return result.SetError("JobGroup Cannot be empty!");
            }
            if (model.StarRunTime == null)
            {
                model.StarRunTime = DateTime.Now;
            }
            if (model.EndRunTime == null)
            {
                model.EndRunTime = DateTime.MaxValue.AddDays(-1);
            }
            var info = await jobCenter.AddScheduleJobAsync(model);
            if (info.Status != 200)
            {
                return result.SetError(info.Message);
            }
            base.Add(new TaskSchedule
            {
                Id = Guid.NewGuid().ToString("N"),
                CreateAuthr = identity.Name,
                CronExpress = model.CronExpress,
                EndRunTime = model.EndRunTime,
                StarRunTime = model.StarRunTime,
                JobGroup = model.JobGroup,
                JobName = model.JobName,
                RunStatus = model.RunStatus

            }, true);
            return result;
        }

        public async Task<Result> DelTaskAsync(TaskScheduleModel model)
        {
            Result result = new Result();
            if (model == null)
            {
                return result.SetError("Model Cannot be empty!");
            }
            if (string.IsNullOrEmpty(model.JobName))
            {
                return result.SetError("JobName Cannot be empty!");
            }
            if (string.IsNullOrEmpty(model.JobGroup))
            {
                return result.SetError("JobGroup Cannot be empty!");
            }
            //search
            var taskInfo = base.Single<TaskSchedule>(t => t.Id.Equals(model.Id));
            var info = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);
            if (!info.Status.Equals(200))
            {
                return result.SetError(info.Message);
            }
            //del
            base.Delete(taskInfo, true);
            return result;
        }

        public Result GetTaskList()
        {
            Result result = new Result();
            var query = base.Where<TaskSchedule>(t => !t.RunStatus.Equals(TaskJobStatus.JobHasDel)).Select(t => new
            {
                t.Id,
                t.JobGroup,
                t.JobName,
                t.RunStatus,
                t.StarRunTime,
                t.UpdateTime,
                t.CronExpress,
                t.EndRunTime,
                t.CreateTime
            }).ToList();
            List<TaskScheduleModel> _list = new List<TaskScheduleModel>();
            query.ForEach(t =>
            {
                _list.Add(new TaskScheduleModel()
                {
                    Id = t.Id,
                    JobGroup = t.JobGroup,
                    JobName = t.JobName,
                    _RunStatus = ((TaskJobStatus)t.RunStatus).GetString(),
                    StarRunTime = t.StarRunTime,
                    UpdateTime = t.UpdateTime,
                    CronExpress = t.CronExpress,
                    EndRunTime = t.EndRunTime,
                    CreateTime = t.CreateTime
                });
            });
            result.Data = _list;
            return result;
        }

        public async Task<Result> ModifyTaskAsync(TaskScheduleModel model)
        {
            Result result = new Result();

            if (model == null)
            {
                return result.SetError("Model Cannot be empty!");
            }
            if (string.IsNullOrEmpty(model.JobName))
            {
                return result.SetError("JobName Cannot be empty!");
            }
            if (string.IsNullOrEmpty(model.JobGroup))
            {
                return result.SetError("JobGroup Cannot be empty!");
            }
            if (model.StarRunTime == null)
            {
                model.StarRunTime = DateTime.Now;
            }
            if (model.EndRunTime == null)
            {
                model.EndRunTime = DateTime.MaxValue.AddDays(-1);
            }
            //modify
            var taskInfo = base.Single<TaskSchedule>(t => t.Id.Equals(model.Id));

            if (taskInfo == null)
            {
                return result.SetError("No such task!");
            }
            //cron
            if (!taskInfo.CronExpress.Equals(model.CronExpress))
            {
                taskInfo.CronExpress = model.CronExpress;
                var stopInfo = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);
                if (!stopInfo.Status.Equals(200))
                {
                    return result.SetError(stopInfo.Message);
                }

                var info = await jobCenter.AddScheduleJobAsync(model);
                if (!stopInfo.Status.Equals(200))
                {
                    return result.SetError(info.Message);
                }
            }


            //state
            if (!taskInfo.RunStatus.Equals(model.RunStatus))
            {
                taskInfo.RunStatus = model.RunStatus;
                if (model.RunStatus != (int)TaskJobStatus.PauseJob)
                {
                    var stopInfo = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);
                    if (!stopInfo.Status.Equals(200))
                    {
                        return result.SetError(stopInfo.Message);
                    }
                    var info = await jobCenter.AddScheduleJobAsync(model);
                    if (!stopInfo.Status.Equals(200))
                    {
                        return result.SetError(info.Message);
                    }
                }
                else
                {
                    var stopInfo = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);
                    if (!stopInfo.Status.Equals(200))
                    {
                        return result.SetError(stopInfo.Message);
                    }
                }
            }
            //
            taskInfo.CreateAuthr = identity.Name;
            taskInfo.UpdateTime = DateTime.Now;
            taskInfo.EndRunTime = model.EndRunTime;
            taskInfo.StarRunTime = model.StarRunTime;
            taskInfo.JobGroup = model.JobGroup;
            taskInfo.JobName = model.JobName;

            base.Update(taskInfo, true);
            return result;
        }

        public Result PauseTask()
        {
            throw new NotImplementedException();
        }

        public Result StartTask()
        {
            throw new NotImplementedException();
        }
    }
View Code

Then we build the web page

Create taskinfo controller in website

  

The code is very simple. It just makes a jump

  

Create view

  

The code is as follows:

@{
    ViewData["title"] = "Scheduled task management";
}
<div class="row search">
    <div class="form-inline">
        <input type="text" class="form-control" placeholder="Task name" ng-model="search.username" />
    </div>

    <button class="btn btn-primary" type="button" ng-click="pagechanged(true)">search</button>
    <button class="btn btn-primary" type="button" ng-click="addTask()">Add task</button>
    <button class="btn btn-primary" type="button" csv-header="getHeader()" ng-csv="_getCsv()" filename="taskList.csv" add-bom="true">export</button>
</div>
@*Popup *@
<div class="modal fade in" id="addmodel" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="mymodallabel">
    <div class="modal-dialog modal-lg" role="document" style="height:100%">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">close</span></button>
                <h4>Planned task management</h4>
            </div>
            <div class="modal-body" ng-form="mymodel">
                <div class="row">
                    <div class="form-group col-sm-6">
                        <label class="control-label col-sm-4">Task force:</label>
                        <div class="col-sm-8">
                            <input type="text" class="form-control" ng-model="task.jobGroup" required placeholder="Task force" />
                        </div>
                    </div>
                    <div class="form-group col-sm-6">
                        <label class="control-label col-sm-4">Task name:</label>
                        <div class="col-sm-8">
                            <input type="text" class="form-control" ng-model="task.jobName" required placeholder="Task name" />
                        </div>
                    </div>
                    <div class="form-group col-sm-6">
                        <label class="control-label col-sm-4">CronExpress:</label>
                        <div class="col-sm-8">
                            <input type="text" class="form-control" ng-model="task.cronExpress" required placeholder="CronExpress" />
                        </div>
                    </div>
                    <div class="form-group col-sm-6">
                        <label class="control-label col-sm-4">running state :</label>
                        <div class="col-sm-8">
                            <select class="form-control" required ng-model="task.runStatus">
                                @*<option value="1">whole</option>*@
                                <option value="1" selected>Performing tasks</option>
                                <option value="2">Suspending task</option>
                                <option value="4">Task close</option>
                            </select>
                        </div>
                    </div>
                    <div class="form-group col-sm-6">
                        <label class="control-label col-sm-4">start time:</label>
                        <div class="col-sm-8">
                            <input type="text" class="form-control mydatetimepicker" ng-model="task.starRunTime" ng-max-date="task.starRunTime||defaultDate" placeholder="Start date" />

                        </div>
                    </div>
                    <div class="form-group col-sm-6">
                        <label class="control-label col-sm-4">End time:</label>
                        <div class="col-sm-8">
                            <input type="text" class="form-control mydatetimepicker" ng-model="task.endRunTime" ng-min-date="task.starRunTime" ng-max-date="defaultDate" placeholder="End date" />

                        </div>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-success" ng-disabled="mymodel.$invalid" ng-click="saveTask()">preservation</button>
            </div>
        </div>
    </div>
</div>


<table class="table table-hover table-condensed table-bordered" style="width:auto;">
    <thead>
        <tr style="height: 35px;">
            <th>Task force</th>
            <th>task</th>
            <th>CronExpress</th>
            <th>start time</th>
            <th>End time</th>
            <th>running state </th>
            <th>Creation time</th>
            <th>Modification time</th>
            <th>operation</th>
        </tr>
    </thead>
    <tbody class="wait-loaded">
        <tr ng-repeat="m in list track by m.id">
            <td>{{m.jobGroup}}</td>
            <td>{{m.jobName}}</td>
            <td>{{m.cronExpress}}</td>
            <td>{{m.starRunTime}}</td>
            <td>{{m.endRunTime}}</td>
            <td>{{m._RunStatus}}</td>
            <td>{{m.createTime}}</td>
            <td>{{m.updateTime}}</td>
            <td>
                <button class="btn btn-success" ng-click="edit(m)">edit</button>
                <button class="btn btn-danger" ng-click="delete(m)">delete</button>
            </td>
        </tr>
    </tbody>
</table>
<div class="mypager wait-loaded">
    <ul uib-pagination total-items="search.recordcount" items-per-page="search.pagesize" ng-change="pagechanged()" ng-model="search.pageindex" max-size="7"
        class="pagination-sm" boundary-links="true" num-pages="search.numpages" boundary-link-numbers="true" first-text="home page" last-text="Last " previous-text="previous page" next-text="next page"></ul>
    <div class="recordcount">common {{search.recordcount}} strip</div>
</div>
@section scripts{
    <script type="text/javascript">
        $angular.add(function ($scope, $query, $timeout, $sce) {
            $scope.getHeader = function () { return ["Task force", "task", "CronExpress", "start time", "End time", "running state ", "Creation time", "Modification time"] };


            $scope._getCsv = function () {
                var model = _.cloneDeep($scope.search);
                model.pageSize = 10000000;
                var promise = $query.post("/webapi/GetTaskList", model, function (response) {
                    var objList = angular.fromJson(response.data);
                    var getArray = [];
                    _.forEach(objList, function (item) {
                        getArray.push({
                            "jobGroup": item.jobGroup,
                            "jobName": item.jobName,
                            "cronExpress": item.cronExpress,
                            "starRunTime": item.starRunTime,
                            "endRunTime": item.endRunTime,
                            "_RunStatus": item._RunStatus,
                            "createTime": item.createTime,
                            "updateTime": item.updateTime
                        });
                    });
                    return getArray;
                });
                return promise;
            };
            $scope.search = { pageindex: 1, pagesize: 10, gender: "-1", order: 1, status: "-1" };
            $scope.setorder = function (index) {
                if (index == math.abs($scope.search.order)) {
                    index = -$scope.search.order;
                }
                $scope.search.order = index;
                $scope.pagechanged(true);
            };
            //query
            $scope.pagechanged = function (reindex) {
                if (reindex) {
                    $scope.search.pageindex = 1;
                }
                $query.post("/webapi/GetTaskList", $scope.search, function (response) {
                    if (response.status === 200) {
                        $scope.list = response.data;
                        $scope.search.recordcount = response.recordcount;
                    } else {
                        $alert(response.message);
                    }
                });
            };


            $scope.pagechanged();

            //Add task
            $scope.addTask = function () {
                $("#addmodel").modal("show");
                $scope.task = { id: -1 };
            };
            //preservation
            $scope.saveTask = function () {
                $query.post("/webapi/AddTaskAsync", $scope.task, function (response) {
                    $("#addmodel").modal("hide");
                    $scope.pagechanged();
                });
            };
            $scope.edit = function (m) {
                $("#addmodel").modal("show");
                m.id = m.id;
                $scope.task = m;

            }

            //delete type
            $scope.delete = function (m) {
                m.id = m.id;
                $scope.task = m;
                $Confirm("Are you sure to delete?The operation is not recoverable!", function () {
                    $query.post("/webapi/DelTaskAsync", $scope.task, function (response) {
                        $scope.pagechanged();
                    });
                });
            }
        });
    </script>
}
View Code

And then the effect came out

  

This table will call a web API interface to get data

  

In this web API, we directly call the method of repacking in ITaskService

  

The code here is as follows:

  

#region Planning task module
        [HttpPost]
        public Result GetTaskList()
        {
            return _taskService.GetTaskList();
        }
        [HttpPost]
        public async Task<Result> AddTaskAsync([FromBody]TaskScheduleModel model)
        {
            if (model != null && !string.IsNullOrEmpty(model.Id)&&!model.Id.Equals("-1"))
            {
                return await _taskService.ModifyTaskAsync(model);
            }
            return await _taskService.AddTaskAsync(model);
        }

        public async Task<Result> DelTaskAsync([FromBody]TaskScheduleModel model)
        {
            return await _taskService.DelTaskAsync(model);
        }
        #endregion

II. Operation test

Add service instead

  

Forget it. The screenshot of the running test is not easy to explain. Record a video tomorrow to explain it. That's it today

The next chapter mainly talks about the authority. I thought I would finish it today, but I was a little sleepy,

This article is dedicated to my youth of one and a half years of asp.net core development. Good night!

  

Tags: angular Javascript

Posted on Sun, 10 May 2020 20:53:57 -0700 by 3r0ss