xxl-job的dotnet core 执行器实现
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

134 lines
4.6 KiB

// Copyright (c) Xuanye Wang. All rights reserved.
// Licensed under MIT license
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using DotXxlJob.Core.Models;
namespace DotXxlJob.Core.Internal
{
internal class JobQueue
{
private readonly ConcurrentQueue<Job> _jobs = new ConcurrentQueue<Job>();
private readonly IJobLogger _jobLogger;
private CancellationTokenSource? _cancellationTokenSource;
private Task? _runningTask;
public JobQueue(IJobExecutor executor, IJobLogger jobLogger)
{
Executor = executor;
_jobLogger = jobLogger;
}
public IJobExecutor Executor { get; private set; } = null!;
public event EventHandler<JobCompletedArgs>? OnJobTaskCompleted;
public async Task SetExecutor(IJobExecutor executor)
{
Executor = executor;
//TODO: cancel all pending jobs
await Stop();
_jobs.Clear();
}
public void EnqueueJob(Job job)
{
_jobs.Enqueue(job);
_runningTask = Start();
}
public bool IsRunning()
{
return _cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested;
}
public async Task Replace(Job job)
{
_jobs.Clear();
await Stop();
EnqueueJob(job);
}
private Task Start()
{
if (_cancellationTokenSource != null)
{
return _runningTask!;
}
_cancellationTokenSource = new CancellationTokenSource();
var ct = _cancellationTokenSource.Token;
return Task.Factory.StartNew(async () =>
{
while (!ct.IsCancellationRequested)
{
if (_jobs.IsEmpty)
{
//_logger.LogInformation("task queue is empty!");
break;
}
TaskResult? result = null;
Job? jobTask = null;
try
{
if (_jobs.TryDequeue(out jobTask))
{
//TODO: set Logger;
//_jobLogger.SetLogFile(jobTask.LogDateTime, jobTask.LogId);
//_jobLogger.Log("<br>----------- xxl-job job execute start -----------<br>----------- Param:{0}", jobTask.ExecutorParams);
var exectorToken = ct;
CancellationTokenSource? timeoutCts = null;
if (jobTask.ExecutorTimeout > 0)
{
timeoutCts = new CancellationTokenSource(jobTask.ExecutorTimeout * 1000);
exectorToken = CancellationTokenSource.CreateLinkedTokenSource(exectorToken, timeoutCts.Token).Token;
}
result = await Executor.ExecuteAsync(new JobExecuteContext(_jobLogger) { }, jobTask!, exectorToken);
if (timeoutCts != null && timeoutCts.IsCancellationRequested)
{
result = TaskResult.Timeout();
timeoutCts.Dispose();
timeoutCts = null;
}
//_jobLogger.Log("<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:" + result.Code);
}
}
catch (Exception ex)
{
result = TaskResult.Failure("Dequeue Task Failed:" + ex.Message);
//_jobLogger.Log("<br>----------- JobThread Exception:" + ex.Message + "<br>----------- xxl-job job execute end(error) -----------");
}
if (jobTask != null)
{
OnJobTaskCompleted?.Invoke(this, new JobCompletedArgs() { Job = jobTask, TaskResult = result! });
}
}
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
}, _cancellationTokenSource.Token);
}
private Task Stop()
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
return _runningTask!;
}
}
}