/// <summary>
        /// 获取Storage 通过这个媒介来处理jobagent的job的统一状态
        /// </summary>
        /// <returns></returns>
        private IHangfireStorage GetHangfireStorage(HttpContext httpContext, JobItem jobItem)
        {
            if (jobItem.Storage == null)
            {
                return(httpContext.RequestServices.GetService <IHangfireStorage>());
            }
            var storageFactory = httpContext.RequestServices.GetService <IStorageFactory>();

            if (storageFactory == null)
            {
                return(null);
            }
            return(storageFactory.CreateHangfireStorage(jobItem.Storage));
        }
Exemplo n.º 2
0
        public async Task InvokeAsync(HttpContext httpContext, RequestDelegate next)
        {
            httpContext.Response.ContentType = "text/plain";
            string message = string.Empty;

            try
            {
                if (!CheckAuth(httpContext, _options))
                {
                    message = "err:basic auth invaild!";
                    _logger.LogError(message);
                    return;
                }
                var agentClass  = httpContext.Request.Headers["x-job-agent-class"].ToString();
                var agentAction = httpContext.Request.Headers["x-job-agent-action"].ToString();
                var jobBody     = httpContext.Request.Headers["x-job-body"].ToString();
                if (string.IsNullOrEmpty(agentClass))
                {
                    message = "err:x-job-agent-class in headers can not be empty!";
                    _logger.LogError(message);
                    return;
                }

                if (string.IsNullOrEmpty(agentAction))
                {
                    message = $"err:x-job-agent-action in headers can not be empty!";
                    _logger.LogError(message);
                    return;
                }

                JobItem jobItem = null;
                if (!string.IsNullOrEmpty(jobBody))
                {
                    jobItem = Newtonsoft.Json.JsonConvert.DeserializeObject <JobItem>(jobBody);
                }

                if (jobItem == null)
                {
                    jobItem = new JobItem();
                }

                agentAction = agentAction.ToLower();
                var requestBody = await GetJobItem(httpContext);

                var agentClassType = GetAgentType(agentClass);
                var jobHeaders     = GetJobHeaders(httpContext);
                if (!string.IsNullOrEmpty(agentClassType.Item2))
                {
                    message = $"err:JobClass:{agentClass} GetType err:{agentClassType.Item2}";
                    _logger.LogError(message);
                    return;
                }

                if (!JobAgentServiceConfigurer.JobAgentDic.TryGetValue(agentClassType.Item1, out var metaData))
                {
                    message = $"err:JobClass:{agentClass} is not registered!";
                    _logger.LogWarning(message);
                    return;
                }



                if (!metaData.Transien)
                {
                    var job = (JobAgent)httpContext.RequestServices.GetRequiredService(agentClassType.Item1);
                    if (agentAction.Equals("run"))
                    {
                        //单例的 一次只能运行一次
                        if (job.JobStatus == JobStatus.Running || job.JobStatus == JobStatus.Stopping)
                        {
                            message = $"err:JobClass:{agentClass} can not start, is already Running!";
                            _logger.LogWarning(message);
                            return;
                        }
                        else if (job.JobStatus == JobStatus.Default)
                        {
                            job.Hang       = metaData.Hang;
                            job.AgentClass = agentClass;
                        }

                        var console = GetHangfireConsole(httpContext, agentClassType.Item1);
                        jobItem.JobParam = requestBody;
                        job.Run(jobItem, console, jobHeaders);
                        message = $"JobClass:{agentClass} run success!";
                        _logger.LogInformation(message);

                        return;
                    }
                    else if (agentAction.Equals("stop"))
                    {
                        if (job.JobStatus == JobStatus.Stopping)
                        {
                            message = $"err:JobClass:{agentClass} is Stopping!";
                            _logger.LogWarning(message);
                            return;
                        }

                        if (job.JobStatus == JobStatus.Stoped)
                        {
                            message = $"err:JobClass:{agentClass} is already Stoped!";
                            _logger.LogWarning(message);
                            return;
                        }
                        var console = GetHangfireConsole(httpContext, agentClassType.Item1);
                        job.Stop(jobItem, console, jobHeaders);
                        message = $"JobClass:{agentClass} stop success!";
                        _logger.LogInformation(message);
                        return;
                    }
                    else if (agentAction.Equals("detail"))
                    {
                        //获取job详情
                        message = job.GetJobInfo();
                        _logger.LogInformation(message);
                        return;
                    }

                    message = $"err:agentAction:{agentAction} invaild";
                    _logger.LogError(message);
                    return;
                }


                if (agentAction.Equals("run"))
                {
                    var job = (JobAgent)httpContext.RequestServices.GetRequiredService(agentClassType.Item1);
                    job.Singleton  = false;
                    job.AgentClass = agentClass;
                    job.Hang       = metaData.Hang;
                    job.Guid       = Guid.NewGuid().ToString("N");
                    job.TransitentJobDisposeEvent += transitentJob.JobRemove;
                    var jobAgentList = transitentJob.GetOrAdd(agentClass, x => new ConcurrentDictionary <string, JobAgent>());
                    jobAgentList.TryAdd(job.Guid, job);
                    var console = GetHangfireConsole(httpContext, agentClassType.Item1);
                    jobItem.JobParam = requestBody;
                    job.Run(jobItem, console, jobHeaders);
                    message = $"Transient JobClass:{agentClass} run success!";
                    _logger.LogInformation(message);

                    return;
                }
                else if (agentAction.Equals("stop"))
                {
                    if (!transitentJob.TryGetValue(agentClass, out var jobAgentList) || jobAgentList.Count < 1)
                    {
                        message = $"err:Transient JobClass:{agentClass} have no running job!";
                        _logger.LogWarning(message);
                        return;
                    }
                    var instanceCount = 0;
                    var stopedJobList = new List <JobAgent>();
                    foreach (var runingJob in jobAgentList)
                    {
                        if (runingJob.Value.JobStatus == JobStatus.Stopping)
                        {
                            continue;
                        }
                        if (runingJob.Value.JobStatus == JobStatus.Stoped)
                        {
                            stopedJobList.Add(runingJob.Value);
                            continue;
                        }
                        var console = GetHangfireConsole(httpContext, agentClassType.Item1);
                        runingJob.Value.Stop(jobItem, console, jobHeaders);
                        instanceCount++;
                    }

                    foreach (var stopedJob in stopedJobList)
                    {
                        jobAgentList.TryRemove(stopedJob.Guid, out _);
                    }

                    transitentJob.TryRemove(agentClass, out _);
                    message = $"JobClass:{agentClass},Instance Count:{instanceCount} stop success!";
                    _logger.LogInformation(message);
                    return;
                }
                else if (agentAction.Equals("detail"))
                {
                    if (!transitentJob.TryGetValue(agentClass, out var jobAgentList) || jobAgentList.Count < 1)
                    {
                        message = $"err:Transient JobClass:{agentClass} have no running job!";
                        _logger.LogWarning(message);
                        return;
                    }

                    var jobInfo       = new List <string>();
                    var stopedJobList = new List <JobAgent>();
                    foreach (var jobAgent in jobAgentList)
                    {
                        if (jobAgent.Value.JobStatus == JobStatus.Stoped)
                        {
                            stopedJobList.Add(jobAgent.Value);
                            continue;
                        }
                        jobInfo.Add(jobAgent.Value.GetJobInfo());
                    }
                    foreach (var stopedJob in stopedJobList)
                    {
                        jobAgentList.TryRemove(stopedJob.Guid, out _);
                    }
                    if (jobInfo.Count < 1)
                    {
                        message = $"err:Transient JobClass:{agentClass} have no running job!";
                        _logger.LogWarning(message);
                        return;
                    }
                    //获取job详情
                    message = $"Runing Instance Count:{jobInfo.Count},JobList:{string.Join("\r\n", jobInfo)}";
                    return;
                }

                message = $"err:agentAction:{agentAction} invaild";
                _logger.LogError(message);
            }
            catch (Exception e)
            {
                httpContext.Response.StatusCode = 500;
                await httpContext.Response.WriteAsync(e.ToString());
            }
            finally
            {
                if (!string.IsNullOrEmpty(message))
                {
                    if (message.StartsWith("err:"))
                    {
                        httpContext.Response.StatusCode = 500;
                    }
                    await httpContext.Response.WriteAsync(message);
                }
            }
        }