/// <summary> /// 执行队列,并快速返回结果 /// </summary> /// <param name="triggerParam"></param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> public ReturnT Execute(TriggerParam triggerParam) { var executor = this._executorFactory.GetTaskExecutor(triggerParam.GlueType); if (executor == null) { return(ReturnT.Failed($"glueType[{triggerParam.GlueType}] is not supported ")); } // 1. 根据JobId 获取 TaskQueue; 用于判断是否有正在执行的任务 if (RUNNING_QUEUE.TryGetValue(triggerParam.JobId, out var taskQueue)) { if (taskQueue.Executor != executor) //任务执行器变更 { return(ChangeJobQueue(triggerParam, executor)); } } if (taskQueue != null) //旧任务还在执行,判断执行策略 { //丢弃后续的 if (Constants.ExecutorBlockStrategy.DISCARD_LATER == triggerParam.ExecutorBlockStrategy) { return(ReturnT.Failed($"block strategy effect:{triggerParam.ExecutorBlockStrategy}")); } //覆盖较早的 if (Constants.ExecutorBlockStrategy.COVER_EARLY == triggerParam.ExecutorBlockStrategy) { return(taskQueue.Replace(triggerParam)); } } return(PushJobQueue(triggerParam, executor)); }
/// <summary> /// read Log /// </summary> /// <param name="logDateTime"></param> /// <param name="logId"></param> /// <param name="fromLineNum"></param> /// <returns></returns> private ReturnT Log(long logDateTime, long logId, int fromLineNum) { var ret = ReturnT.Success(null); ret.Content = this._jobLogger.ReadLog(logDateTime, logId, fromLineNum); return(ret); }
private ReturnT Kill(int jobId) { return(this._jobDispatcher.TryRemoveJobTask(jobId) ? ReturnT.SUCCESS : ReturnT.Success("job thread already killed.")); }
private ReturnT IdleBeat(IdleBeatRequest req) { if (req == null) { return(ReturnT.Failed("IdleBeat Error")); } return(this._jobDispatcher.IdleBeat(req.JobId)); }
/// <summary> /// read Log /// </summary> /// <returns></returns> private ReturnT Log(LogRequest req) { if (req == null) { return(ReturnT.Failed("Log Error")); } var ret = ReturnT.Success(null); ret.Content = this._jobLogger.ReadLog(req.LogDateTime, req.LogId, req.FromLineNum); return(ret); }
private ReturnT Kill(KillRequest req) { if (req == null) { return(ReturnT.Failed("Kill Error")); } return(this._jobDispatcher.TryRemoveJobTask(req.JobId) ? ReturnT.SUCCESS : ReturnT.Success("job thread already killed.")); }
public ReturnT Push(TriggerParam triggerParam) { if (!ID_IN_QUEUE.TryAdd(triggerParam.LogId, 0)) { this._logger.LogWarning("repeat job task,logId={logId},jobId={jobId}", triggerParam.LogId, triggerParam.JobId); return(ReturnT.Failed("repeat job task!")); } //this._logger.LogWarning("add job with logId={logId},jobId={jobId}",triggerParam.LogId,triggerParam.JobId); this.TASK_QUEUE.Enqueue(triggerParam); StartTask(); return(ReturnT.SUCCESS); }
private ReturnT PushJobQueue(TriggerParam triggerParam, ITaskExecutor executor) { if (RUNNING_QUEUE.TryGetValue(triggerParam.JobId, out var jobQueue)) { return(jobQueue.Push(triggerParam)); } //NewJobId jobQueue = new JobTaskQueue(executor, this._jobLogger, this._jobQueueLogger); jobQueue.CallBack += TriggerCallback; if (RUNNING_QUEUE.TryAdd(triggerParam.JobId, jobQueue)) { return(jobQueue.Push(triggerParam)); } return(ReturnT.Failed("add running queue executor error")); }
private ReturnT ChangeJobQueue(TriggerParam triggerParam, ITaskExecutor executor) { if (RUNNING_QUEUE.TryRemove(triggerParam.JobId, out var oldJobTask)) { oldJobTask.CallBack -= TriggerCallback; oldJobTask.Dispose(); //释放原来的资源 } JobTaskQueue jobQueue = new JobTaskQueue(executor, this._jobLogger, this._jobQueueLogger); jobQueue.CallBack += TriggerCallback; if (RUNNING_QUEUE.TryAdd(triggerParam.JobId, jobQueue)) { return(jobQueue.Push(triggerParam)); } return(ReturnT.Failed(" replace running queue executor error")); }
private async Task <ReturnT> InvokeRpcService(string methodName, object jsonObject) { var triedTimes = 0; ReturnT ret = null; while (triedTimes++ < this._addresses.Count) { var address = this._addresses[this._currentIndex]; this._currentIndex = (this._currentIndex + 1) % this._addresses.Count; if (!address.CheckAccessible()) { continue; } try { var json = await address.RequestUri.AppendPathSegment(methodName) .WithHeader("XXL-JOB-ACCESS-TOKEN", this._options.AccessToken) .PostJsonAsync(jsonObject) .ReceiveString(); //.ReceiveJson<ReturnT>(); ret = JsonConvert.DeserializeObject <ReturnT>(json); address.Reset(); } catch (Exception ex) { this._logger.LogError(ex, "request admin error.{0}", ex.Message); address.SetFail(); continue; } } if (ret == null) { ret = ReturnT.Failed("call admin fail"); } return(ret); }
private void StartTask() { if (this._cancellationTokenSource != null) { return; //running } this._cancellationTokenSource = new CancellationTokenSource(); var ct = this._cancellationTokenSource.Token; this._runTask = Task.Factory.StartNew(async() => { //ct.ThrowIfCancellationRequested(); while (!ct.IsCancellationRequested) { if (TASK_QUEUE.IsEmpty) { break; } ReturnT result = null; TriggerParam triggerParam = null; try { if (TASK_QUEUE.TryDequeue(out triggerParam)) { if (!ID_IN_QUEUE.TryRemove(triggerParam.LogId, out _)) { this._logger.LogWarning("remove queue failed,logId={logId},jobId={jobId},exists={exists}" , triggerParam.LogId, triggerParam.JobId, ID_IN_QUEUE.ContainsKey(triggerParam.LogId)); } //set log file; this._jobLogger.SetLogFile(triggerParam.LogDateTime, triggerParam.LogId); this._jobLogger.Log("<br>----------- xxl-job job execute start -----------<br>----------- Param:{0}", triggerParam.ExecutorParams); result = await this._executor.Execute(triggerParam); this._jobLogger.Log("<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:" + result.Code); } else { this._logger.LogWarning("Dequeue Task Failed"); } } catch (Exception ex) { result = ReturnT.Failed("Dequeue Task Failed:" + ex.Message); this._jobLogger.Log("<br>----------- JobThread Exception:" + ex.Message + "<br>----------- xxl-job job execute end(error) -----------"); } if (triggerParam != null) { CallBack?.Invoke(this, new HandleCallbackParam(triggerParam, result ?? ReturnT.FAIL)); } } this._cancellationTokenSource.Dispose(); this._cancellationTokenSource = null; }, this._cancellationTokenSource.Token); }
private async Task <ReturnT> InvokeRpcService(string methodName, List <object> parameterTypes, object parameters, bool polling = false) { var request = new RpcRequest { RequestId = Guid.NewGuid().ToString("N"), CreateMillisTime = DateTime.Now.GetTotalMilliseconds(), AccessToken = _options.AccessToken, ClassName = "com.xxl.job.core.biz.AdminBiz", MethodName = methodName, ParameterTypes = parameterTypes, Parameters = new List <object> { parameters } }; byte[] postBuf; using (var stream = new MemoryStream()) { HessianSerializer.SerializeRequest(stream, request); postBuf = stream.ToArray(); } var triedTimes = 0; var retList = new List <ReturnT>(); using (var client = this._clientFactory.CreateClient(Constants.DefaultHttpClientName)) { while (triedTimes++ < this._addresses.Count) { var address = this._addresses[this._currentIndex]; this._currentIndex = (this._currentIndex + 1) % this._addresses.Count; if (!address.CheckAccessible()) { continue; } Stream resStream; try { resStream = await DoPost(client, address, postBuf); address.Reset(); } catch (Exception ex) { this._logger.LogError(ex, "request admin error.{0}", ex.Message); address.SetFail(); continue; } RpcResponse res = null; try { /* * using (StreamReader reader = new StreamReader(resStream)) * { * string content = await reader.ReadToEndAsync(); * * this._logger.LogWarning(content); * } */ res = HessianSerializer.DeserializeResponse(resStream); } catch (Exception ex) { this._logger.LogError(ex, "DeserializeResponse error:{errorMessage}", ex.Message); } if (res == null) { retList.Add(ReturnT.Failed("response is null")); } else if (res.IsError) { retList.Add(ReturnT.Failed(res.ErrorMsg)); } else if (res.Result is ReturnT ret) { retList.Add(ret); } else { retList.Add(ReturnT.Failed("response is null")); } if (!polling) { return(retList[0]); } } if (retList.Count > 0) { return(retList.Last()); } } throw new Exception("xxl-rpc server address not accessible."); }
public async Task HandlerAsync(HttpRequest request, HttpResponse response) { var path = request.Path.Value; ReturnT ret = null; var arrParts = path.Split('/'); var method = arrParts[arrParts.Length - 1].ToLower(); if (!string.IsNullOrEmpty(this._options.AccessToken)) { var reqToken = ""; if (request.Headers.TryGetValue("XXL-JOB-ACCESS-TOKEN", out var tokenValues)) { reqToken = tokenValues[0].ToString(); } if (this._options.AccessToken != reqToken) { ret = ReturnT.Failed("ACCESS-TOKEN Auth Fail"); response.ContentType = "application/json;charset=utf-8"; await response.WriteAsync(JsonConvert.SerializeObject(ret)); return; } } try { string json = await CollectBody(request.Body); switch (method) { case "beat": ret = Beat(); break; case "idleBeat": ret = IdleBeat(JsonConvert.DeserializeObject <IdleBeatRequest>(json)); break; case "run": ret = Run(JsonConvert.DeserializeObject <TriggerParam>(json)); break; case "kill": ret = Kill(JsonConvert.DeserializeObject <KillRequest>(json)); break; case "log": ret = Log(JsonConvert.DeserializeObject <LogRequest>(json)); break; } } catch (Exception ex) { this._logger.LogError(ex, "响应出错" + ex.Message); ret = ReturnT.Failed("执行器内部错误"); } if (ret == null) { ret = ReturnT.Failed($"method {method} is not impl"); } response.ContentType = "application/json;charset=utf-8"; await response.WriteAsync(JsonConvert.SerializeObject(ret, new JsonSerializerSettings() { StringEscapeHandling = StringEscapeHandling.EscapeNonAscii })); }