paiban/NPP.SmartSchedue.Api/Repositories/Notification/NotificationTaskRepository.cs
Developer 058d8edffa 添加通知系统和工作任务分配功能
- 新增通知系统完整架构,包含通知设置、历史记录、任务管理等核心功能
- 实现工作任务分配服务,支持人员和设备的智能分配
- 添加人员分组管理功能,支持灵活的通知目标配置
- 完善相关枚举定义和数据传输对象

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 08:34:01 +08:00

284 lines
11 KiB
C#
Raw 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.Generic;
using System.Threading.Tasks;
using System.Linq;
using NPP.SmartSchedue.Api.Contracts.Core.Repositories;
using NPP.SmartSchedue.Api.Contracts.Domain.Notification;
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
using NPP.SmartSchedue.Api.Core.Repositories;
using ZhonTai.Admin.Core.Db.Transaction;
namespace NPP.SmartSchedue.Api.Repositories.Notification;
/// <summary>
/// 通知任务仓储实现
/// 决策点6定时任务支持定时检查和触发通知
/// 业务思考:
/// 1. 支持一次性任务和周期性任务Cron表达式
/// 2. 任务状态管理(待执行、执行中、已完成、失败、取消)
/// 3. 任务重试机制和失效时间控制
/// 4. 任务执行结果记录和错误处理
/// </summary>
public class NotificationTaskRepository : AppRepositoryBase<NotificationTaskEntity>, INotificationTaskRepository
{
public NotificationTaskRepository(UnitOfWorkManagerCloud uowm) : base(uowm)
{
}
/// <summary>
/// 根据通知设置ID获取任务列表
/// </summary>
public async Task<List<NotificationTaskEntity>> GetByNotificationSettingIdAsync(long notificationSettingId)
{
return await Select
.Where(t => t.NotificationSettingId == notificationSettingId)
.Include(t => t.NotificationSetting)
.OrderByDescending(t => t.CreatedTime)
.ToListAsync();
}
/// <summary>
/// 根据任务状态获取任务列表
/// </summary>
public async Task<List<NotificationTaskEntity>> GetByTaskStatusAsync(NotificationStatusEnum taskStatus)
{
return await Select
.Where(t => t.TaskStatus == (int)taskStatus)
.Include(t => t.NotificationSetting)
.OrderByDescending(t => t.CreatedTime)
.ToListAsync();
}
/// <summary>
/// 根据启用状态获取任务列表
/// </summary>
public async Task<List<NotificationTaskEntity>> GetByEnabledAsync(bool enabled)
{
return await Select
.Where(t => t.IsEnabled == enabled)
.Include(t => t.NotificationSetting)
.OrderByDescending(t => t.CreatedTime)
.ToListAsync();
}
/// <summary>
/// 根据业务类型和业务ID获取任务列表
/// </summary>
public async Task<List<NotificationTaskEntity>> GetByBusinessAsync(string businessType, long? businessId = null)
{
var query = Select.Where(t => t.BusinessType == businessType);
if (businessId.HasValue)
query = query.Where(t => t.BusinessId == businessId.Value);
return await query
.Include(t => t.NotificationSetting)
.OrderByDescending(t => t.CreatedTime)
.ToListAsync();
}
/// <summary>
/// 获取待执行的任务列表
/// 业务逻辑:查询计划执行时间已到达且任务状态为待执行的任务
/// </summary>
public async Task<List<NotificationTaskEntity>> GetPendingTasksAsync(DateTime currentTime)
{
return await Select
.Where(t => t.IsEnabled == true)
.Where(t => t.TaskStatus == (int)NotificationStatusEnum.Pending)
.Where(t => t.PlannedExecutionTime <= currentTime)
.Where(t => t.ExpirationTime == null || t.ExpirationTime > currentTime) // 排除已过期的任务
.Include(t => t.NotificationSetting)
.OrderBy(t => t.PlannedExecutionTime) // 按计划时间升序排序
.ToListAsync();
}
/// <summary>
/// 获取需要执行的定时任务列表基于Cron表达式
/// 业务逻辑:
/// 1. 查询启用的周期性任务
/// 2. 检查下次执行时间是否已到达
/// 3. 验证任务未过期且未达到最大执行次数
/// </summary>
public async Task<List<NotificationTaskEntity>> GetCronTasksForExecutionAsync(DateTime currentTime)
{
return await Select
.Where(t => t.IsEnabled == true)
.Where(t => !string.IsNullOrWhiteSpace(t.CronExpression)) // 有Cron表达式的周期性任务
.Where(t => t.TaskStatus != (int)NotificationStatusEnum.Cancelled)
.Where(t => t.NextExecutionTime <= currentTime) // 下次执行时间已到
.Where(t => t.ExpirationTime == null || t.ExpirationTime > currentTime) // 未过期
.Where(t => t.MaxExecutionCount == null || t.ExecutionCount < t.MaxExecutionCount) // 未达到最大执行次数
.Include(t => t.NotificationSetting)
.OrderBy(t => t.NextExecutionTime)
.ToListAsync();
}
/// <summary>
/// 更新任务执行状态
/// 业务逻辑:更新任务状态、执行结果、错误信息等
/// </summary>
public async Task UpdateExecutionStatusAsync(long taskId, NotificationStatusEnum taskStatus, string executionResult = "", string errorMessage = "")
{
var currentTime = DateTime.Now;
await UpdateDiy
.Set(t => t.TaskStatus, (int)taskStatus)
.Set(t => t.LastExecutionTime, currentTime)
.SetIf(!string.IsNullOrWhiteSpace(executionResult), t => t.ExecutionResult, executionResult)
.SetIf(!string.IsNullOrWhiteSpace(errorMessage), t => t.ErrorMessage, errorMessage)
.Set(t => t.ModifiedTime, currentTime)
.Where(t => t.Id == taskId)
.ExecuteAffrowsAsync();
}
/// <summary>
/// 更新任务下次执行时间
/// 业务场景周期性任务完成后根据Cron表达式计算下次执行时间
/// </summary>
public async Task UpdateNextExecutionTimeAsync(long taskId, DateTime? nextExecutionTime)
{
await UpdateDiy
.Set(t => t.NextExecutionTime, nextExecutionTime)
.Set(t => t.ModifiedTime, DateTime.Now)
.Where(t => t.Id == taskId)
.ExecuteAffrowsAsync();
}
/// <summary>
/// 增加任务执行次数
/// 业务逻辑:记录任务执行统计,用于控制最大执行次数和成功率分析
/// </summary>
public async Task IncrementExecutionCountAsync(long taskId, bool isSuccess)
{
var task = await Select.Where(t => t.Id == taskId).FirstAsync();
if (task == null) return;
await UpdateDiy
.Set(t => t.ExecutionCount, task.ExecutionCount + 1)
.SetIf(isSuccess, t => t.SuccessCount, task.SuccessCount + 1)
.SetIf(!isSuccess, t => t.FailureCount, task.FailureCount + 1)
.Set(t => t.ModifiedTime, DateTime.Now)
.Where(t => t.Id == taskId)
.ExecuteAffrowsAsync();
}
/// <summary>
/// 检查任务是否应该停止执行
/// 业务规则:
/// 1. 任务被禁用
/// 2. 任务已取消
/// 3. 已达到最大执行次数
/// 4. 任务已过期
/// 5. 连续失败次数过多
/// </summary>
public async Task<bool> ShouldStopExecutionAsync(long taskId)
{
var task = await Select.Where(t => t.Id == taskId).FirstAsync();
if (task == null) return true;
var currentTime = DateTime.Now;
// 检查基本停止条件
if (!task.IsEnabled ||
task.TaskStatus == (int)NotificationStatusEnum.Cancelled ||
(task.ExpirationTime.HasValue && task.ExpirationTime.Value <= currentTime) ||
(task.MaxExecutionCount.HasValue && task.ExecutionCount >= task.MaxExecutionCount.Value))
{
return true;
}
// 检查连续失败次数(如果设置了最大重试次数)
if (task.MaxRetryCount.HasValue && task.FailureCount >= task.MaxRetryCount.Value)
{
return true;
}
return false;
}
/// <summary>
/// 获取过期的任务列表
/// 业务场景:定期清理过期任务,释放系统资源
/// </summary>
public async Task<List<NotificationTaskEntity>> GetExpiredTasksAsync(DateTime expiredBefore)
{
return await Select
.Where(t => t.ExpirationTime <= expiredBefore)
.Where(t => t.TaskStatus != (int)NotificationStatusEnum.Cancelled) // 排除已取消的任务
.OrderBy(t => t.ExpirationTime)
.ToListAsync();
}
/// <summary>
/// 清理过期的任务
/// 业务逻辑:将过期任务状态设为已取消,而不是物理删除,保留审计记录
/// </summary>
public async Task<int> CleanupExpiredTasksAsync(DateTime expiredBefore)
{
var currentTime = DateTime.Now;
var affectedRows = await UpdateDiy
.Set(t => t.TaskStatus, (int)NotificationStatusEnum.Cancelled)
.Set(t => t.ErrorMessage, "任务已过期自动取消")
.Set(t => t.ModifiedTime, currentTime)
.Where(t => t.ExpirationTime <= expiredBefore)
.Where(t => t.TaskStatus != (int)NotificationStatusEnum.Cancelled)
.ExecuteAffrowsAsync();
return (int)affectedRows;
}
/// <summary>
/// 获取需要重试的失败任务列表
/// 业务场景:定时重试失败的任务,提高通知送达率
/// </summary>
public async Task<List<NotificationTaskEntity>> GetFailedTasksForRetryAsync()
{
var currentTime = DateTime.Now;
return await Select
.Where(t => t.TaskStatus == (int)NotificationStatusEnum.Failed)
.Where(t => t.IsEnabled == true)
.Where(t => t.NextRetryTime <= currentTime) // 重试时间已到
.Where(t => t.MaxRetryCount == null || t.RetryCount < t.MaxRetryCount) // 未达到最大重试次数
.Where(t => t.ExpirationTime == null || t.ExpirationTime > currentTime) // 未过期
.Include(t => t.NotificationSetting)
.OrderBy(t => t.NextRetryTime)
.ToListAsync();
}
/// <summary>
/// 更新任务重试信息
/// 业务逻辑:更新重试次数和下次重试时间
/// </summary>
public async Task UpdateRetryInfoAsync(long taskId, int retryCount, DateTime? nextRetryTime)
{
await UpdateDiy
.Set(t => t.RetryCount, retryCount)
.Set(t => t.NextRetryTime, nextRetryTime)
.Set(t => t.ModifiedTime, DateTime.Now)
.Where(t => t.Id == taskId)
.ExecuteAffrowsAsync();
}
/// <summary>
/// 批量更新任务状态
/// 业务场景:批量操作,提高性能
/// </summary>
public async Task<int> BatchUpdateTaskStatusAsync(List<long> taskIds, NotificationStatusEnum status, string reason = "")
{
if (!taskIds.Any()) return 0;
var currentTime = DateTime.Now;
var affectedRows = await UpdateDiy
.Set(t => t.TaskStatus, (int)status)
.SetIf(!string.IsNullOrWhiteSpace(reason), t => t.ErrorMessage, reason)
.Set(t => t.ModifiedTime, currentTime)
.Where(t => taskIds.Contains(t.Id))
.ExecuteAffrowsAsync();
return (int)affectedRows;
}
}