TellmeRevitPluging/Services/TaskManager.cs

266 lines
7.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using RevitHttpControl.Models;
namespace RevitHttpControl.Services
{
/// <summary>
/// 任务管理器
/// </summary>
public class TaskManager
{
private static readonly Lazy<TaskManager> _instance = new Lazy<TaskManager>(() => new TaskManager());
/// <summary>
/// 单例实例
/// </summary>
public static TaskManager Instance => _instance.Value;
/// <summary>
/// 任务状态存储
/// </summary>
private readonly ConcurrentDictionary<Guid, TaskStatusResponse> _tasks;
/// <summary>
/// 上次清理时间
/// </summary>
private DateTime _lastCleanupTime;
/// <summary>
/// 清理间隔(小时)
/// </summary>
private const int CLEANUP_INTERVAL_HOURS = 1;
/// <summary>
/// 私有构造函数
/// </summary>
private TaskManager()
{
_tasks = new ConcurrentDictionary<Guid, TaskStatusResponse>();
_lastCleanupTime = DateTime.UtcNow;
}
/// <summary>
/// 创建新任务
/// </summary>
/// <returns>任务ID</returns>
public Guid CreateTask(string executionId = null)
{
// 检查是否需要清理过期任务
CheckAndCleanupIfNeeded();
var taskId = Guid.NewGuid();
var effectiveExecutionId = string.IsNullOrWhiteSpace(executionId)
? taskId.ToString()
: executionId;
var task = new TaskStatusResponse
{
TaskId = taskId,
Status = TaskStatus.Pending,
CreatedAt = DateTime.UtcNow,
ExecutionId = effectiveExecutionId
};
_tasks.TryAdd(taskId, task);
return taskId;
}
/// <summary>
/// 检查并在需要时清理过期任务
/// </summary>
private void CheckAndCleanupIfNeeded()
{
var now = DateTime.UtcNow;
if (now.Subtract(_lastCleanupTime).TotalHours >= CLEANUP_INTERVAL_HOURS)
{
CleanupExpiredTasks();
_lastCleanupTime = now;
}
}
/// <summary>
/// 设置任务为运行状态
/// </summary>
/// <param name="taskId">任务ID</param>
public void SetTaskRunning(Guid taskId)
{
if (_tasks.TryGetValue(taskId, out var task))
{
task.Status = TaskStatus.Running;
}
}
/// <summary>
/// 完成任务
/// </summary>
/// <param name="taskId">任务ID</param>
/// <param name="result">任务结果</param>
public void CompleteTask(Guid taskId, object result)
{
if (_tasks.TryGetValue(taskId, out var task))
{
task.Status = TaskStatus.Completed;
task.Result = result;
task.CompletedAt = DateTime.UtcNow;
NotifyTaskResultInBackground(task);
}
}
/// <summary>
/// 任务失败
/// </summary>
/// <param name="taskId">任务ID</param>
/// <param name="errorMessage">错误消息</param>
public void FailTask(Guid taskId, string errorMessage)
{
if (_tasks.TryGetValue(taskId, out var task))
{
task.Status = TaskStatus.Failed;
task.ErrorMessage = errorMessage;
task.CompletedAt = DateTime.UtcNow;
NotifyTaskResultInBackground(task);
}
}
/// <summary>
/// 后台触发任务结果回调,避免阻塞调用线程
/// </summary>
/// <param name="task">任务状态</param>
private static void NotifyTaskResultInBackground(TaskStatusResponse task)
{
System.Threading.Tasks.Task.Run(() =>
{
try
{
TaskCallbackService.NotifyTaskResult(task);
}
catch
{
// 回调失败不影响主流程
}
});
}
/// <summary>
/// 取消任务
/// </summary>
/// <param name="taskId">任务ID</param>
public void CancelTask(Guid taskId)
{
if (_tasks.TryGetValue(taskId, out var task))
{
task.Status = TaskStatus.Cancelled;
task.CompletedAt = DateTime.UtcNow;
}
}
/// <summary>
/// 获取任务状态
/// </summary>
/// <param name="taskId">任务ID</param>
/// <returns>任务状态响应</returns>
public TaskStatusResponse GetTaskStatus(Guid taskId)
{
_tasks.TryGetValue(taskId, out var task);
return task;
}
/// <summary>
/// 检查任务是否存在
/// </summary>
/// <param name="taskId">任务ID</param>
/// <returns>是否存在</returns>
public bool TaskExists(Guid taskId)
{
return _tasks.ContainsKey(taskId);
}
/// <summary>
/// 获取任务结果(仅用于向后兼容)
/// </summary>
/// <param name="taskId">任务ID</param>
/// <returns>任务结果</returns>
public object GetTaskResult(Guid taskId)
{
if (_tasks.TryGetValue(taskId, out var task) && task.Status == TaskStatus.Completed)
{
return task.Result;
}
return null;
}
/// <summary>
/// 存储统计结果(用于向后兼容现有代码)
/// </summary>
/// <param name="taskId">任务ID</param>
/// <param name="count">统计数量</param>
public void StoreStatsResult(Guid taskId, int count)
{
CompleteTask(taskId, count);
}
/// <summary>
/// 获取统计结果(用于向后兼容现有代码)
/// </summary>
/// <param name="taskId">任务ID</param>
/// <returns>统计数量如果不存在返回null</returns>
public int? GetStatsResult(Guid taskId)
{
if (_tasks.TryGetValue(taskId, out var task) &&
task.Status == TaskStatus.Completed &&
task.Result is int count)
{
return count;
}
return null;
}
/// <summary>
/// 清理过期任务创建超过24小时的已完成任务
/// </summary>
public void CleanupExpiredTasks()
{
var expiredTime = DateTime.UtcNow.AddHours(-24);
var expiredTasks = new List<Guid>();
foreach (var kvp in _tasks)
{
var task = kvp.Value;
if ((task.Status == TaskStatus.Completed ||
task.Status == TaskStatus.Failed ||
task.Status == TaskStatus.Cancelled) &&
task.CreatedAt < expiredTime)
{
expiredTasks.Add(kvp.Key);
}
}
foreach (var taskId in expiredTasks)
{
_tasks.TryRemove(taskId, out _);
}
}
/// <summary>
/// 获取任务总数
/// </summary>
/// <returns>任务总数</returns>
public int GetTaskCount()
{
return _tasks.Count;
}
/// <summary>
/// 获取指定状态的任务数量
/// </summary>
/// <param name="status">任务状态</param>
/// <returns>任务数量</returns>
public int GetTaskCountByStatus(TaskStatus status)
{
return _tasks.Values.Count(t => t.Status == status);
}
}
}