115 lines
4.5 KiB
C#
115 lines
4.5 KiB
C#
using Butter.Types;
|
|
|
|
namespace Lactose.Jobs;
|
|
|
|
/// <summary>
|
|
/// Abstract class representing a job that can be executed asynchronously.
|
|
/// Provides events for job lifecycle (Started, ProgressChanged, Completed, Canceled, Failed).
|
|
/// Inherit from this class and implement the TaskJob method to define the job's functionality.
|
|
/// </summary>
|
|
public abstract class Job {
|
|
/// <summary>
|
|
/// Gets the unique identifier of the job.
|
|
/// </summary>
|
|
public virtual Guid Id { get; } = Guid.NewGuid();
|
|
/// <summary>
|
|
/// Gets or sets the parent job ID, if this is a sub-job.
|
|
/// </summary>
|
|
public virtual Guid? ParentJobId { get; set; }
|
|
/// <summary>
|
|
/// Gets the name of the job.
|
|
/// </summary>
|
|
public virtual string Name { get; } = "Unnamed Job";
|
|
/// <summary>
|
|
/// Gets the status tracker for this job.
|
|
/// </summary>
|
|
public virtual JobStatus JobStatus { get; }
|
|
Task? task;
|
|
CancellationTokenSource? cts;
|
|
|
|
/// <summary>
|
|
/// Initialises a new job instance.
|
|
/// </summary>
|
|
protected Job() => JobStatus = new JobStatus(this);
|
|
|
|
/// <summary>
|
|
/// Sets up the task and the cancellation token, then starts the task (triggering the Started event)
|
|
/// Also sets up a continuation to handle completion, failure, or cancellation of the task.
|
|
/// </summary>
|
|
public virtual void Start() {
|
|
JobStatus.Start();
|
|
cts = new CancellationTokenSource();
|
|
task = Task.Run(() => TaskJob(cts.Token));
|
|
|
|
task.ContinueWith(t => {
|
|
switch (JobStatus.Status) {
|
|
case EJobStatus.Canceled:
|
|
Canceled?.Invoke(this, JobStatus);
|
|
break;
|
|
case EJobStatus.Failed:
|
|
Failed?.Invoke(this, JobStatus);
|
|
break;
|
|
case EJobStatus.Running: // If still running or waiting, mark as completed
|
|
case EJobStatus.Waiting: //somebody forgot to update the status and the method returned.
|
|
case EJobStatus.Completed:
|
|
case EJobStatus.CompletedWithErrors:
|
|
Completed?.Invoke(this, JobStatus);
|
|
break;
|
|
case EJobStatus.Queued: // This should never happen
|
|
default:
|
|
Completed?.Invoke(this, JobStatus);
|
|
break;
|
|
}
|
|
Done?.Invoke(this, JobStatus);
|
|
}
|
|
);
|
|
|
|
Started?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override this method to implement the job's functionality. The provided CancellationToken can be used to check for cancellation requests.
|
|
/// Invoke ProgressChanged event to report progress updates.
|
|
/// </summary>
|
|
/// <param name="token">Cancellation toke to retrieve when a task cancellation has been requested</param>
|
|
protected abstract Task TaskJob(CancellationToken token);
|
|
|
|
/// <summary>
|
|
/// Cancels the job if it's running. Canceled event will be called by the callbacks on the task.
|
|
/// </summary>
|
|
public virtual void Cancel() => cts?.Cancel();
|
|
|
|
/// <summary>
|
|
/// Raised when the job starts running.
|
|
/// </summary>
|
|
public virtual event EventHandler? Started;
|
|
/// <summary>
|
|
/// Raised when the job makes progress. The JobStatus parameter contains the current progress (0 to 1).
|
|
/// </summary>
|
|
public virtual event EventHandler<JobStatus>? ProgressChanged;
|
|
/// <summary>
|
|
/// Raised when the job transitions from running to waiting (e.g., waiting for resources or sub jobs).
|
|
/// </summary>
|
|
public virtual event EventHandler<JobStatus>? StartedWaiting;
|
|
/// <summary>
|
|
/// Raised when the job transitions from waiting to running.
|
|
/// </summary>
|
|
public virtual event EventHandler<JobStatus>? FinishedWaiting;
|
|
/// <summary>
|
|
/// Raised when the job completes successfully.
|
|
/// </summary>
|
|
public virtual event EventHandler<JobStatus>? Completed;
|
|
/// <summary>
|
|
/// Raised when the job is canceled by the user or system.
|
|
/// </summary>
|
|
public virtual event EventHandler<JobStatus>? Canceled;
|
|
/// <summary>
|
|
/// Raised when the job fails due to an unhandled exception.
|
|
/// </summary>
|
|
public virtual event EventHandler<JobStatus>? Failed;
|
|
/// <summary>
|
|
/// Raised when the job is done, regardless of the final status (Completed, Canceled, or Failed).
|
|
/// </summary>
|
|
public virtual event EventHandler<JobStatus>? Done;
|
|
}
|