ArticleGenerationService.java
25.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
package com.aigeo.article.service;
import com.aigeo.article.entity.ArticleGenerationTask;
import com.aigeo.article.repository.ArticleGenerationTaskRepository;
import com.aigeo.common.context.TenantContext;
import com.aigeo.common.enums.TaskStatus;
import com.aigeo.common.exception.BusinessException;
import com.aigeo.common.result.ResultCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.data.domain.PageRequest;
/**
* 文章生成服务层
*
* 负责管理文章生成任务的业务逻辑,包括任务的创建、更新、查询、
* 状态跟踪、批量操作等功能。支持AI自动生成文章内容、
* 多种内容模板、发布状态管理等
*
* @author AIGEO Team
* @since 1.0.0
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ArticleGenerationService {
private final ArticleGenerationTaskRepository taskRepository;
/**
* 获取所有文章生成任务
* @return 所有任务列表
*/
public List<ArticleGenerationTask> getAllTasks() {
log.debug("获取所有文章生成任务");
return taskRepository.findAll();
}
/**
* 根据公司ID获取文章生成任务列表
* @param companyId 公司ID
* @return 该公司的任务列表
* @throws BusinessException 当公司ID为空时抛出
*/
public List<ArticleGenerationTask> getTasksByCompanyId(Integer companyId) {
log.debug("获取公司文章生成任务,companyId: {}", companyId);
if (companyId == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID不能为空");
}
return taskRepository.findByCompanyId(companyId);
}
/**
* 根据用户ID获取文章生成任务列表
* @param userId 用户ID
* @return 该用户创建的任务列表
* @throws BusinessException 当用户ID为空时抛出
*/
public List<ArticleGenerationTask> getTasksByUserId(Integer userId) {
log.debug("获取用户文章生成任务,userId: {}", userId);
if (userId == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "用户ID不能为空");
}
return taskRepository.findByUserId(userId);
}
/**
* 根据任务状态获取文章生成任务列表
* @param status 任务状态
* @return 指定状态的任务列表
* @throws BusinessException 当状态为空时抛出
*/
public List<ArticleGenerationTask> getTasksByStatus(TaskStatus status) {
log.debug("根据状态获取文章生成任务,status: {}", status);
if (status == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务状态不能为空");
}
return taskRepository.findByStatus(status);
}
/**
* 根据公司ID和状态获取任务列表
* @param companyId 公司ID
* @param status 任务状态
* @return 匹配条件的任务列表
* @throws BusinessException 当参数为空时抛出
*/
public List<ArticleGenerationTask> getTasksByCompanyIdAndStatus(Integer companyId, TaskStatus status) {
log.debug("根据公司和状态获取任务,companyId: {}, status: {}", companyId, status);
if (companyId == null || status == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID和状态不能为空");
}
return taskRepository.findByCompanyIdAndStatus(companyId, status);
}
/**
* 分页查询公司的文章生成任务
* @param companyId 公司ID
* @param pageable 分页参数
* @return 分页结果
* @throws BusinessException 当公司ID为空时抛出
*/
public Page<ArticleGenerationTask> getTasksByCompanyIdWithPaging(Integer companyId, Pageable pageable) {
log.debug("分页查询公司文章生成任务,companyId: {}", companyId);
if (companyId == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID不能为空");
}
return taskRepository.findByCompanyIdOrderByCreatedAtDesc(companyId, pageable);
}
/**
* 根据ID获取文章生成任务
* @param id 任务ID
* @return 任务对象的Optional包装
* @throws BusinessException 当ID为空时抛出
*/
public Optional<ArticleGenerationTask> getTaskById(Integer id) {
log.debug("根据ID获取文章生成任务,id: {}", id);
if (id == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务ID不能为空");
}
return taskRepository.findById(id);
}
/**
* 根据文章主题模糊搜索任务
* @param companyId 公司ID
* @param articleTheme 文章主题关键词
* @return 匹配的任务列表
* @throws BusinessException 当参数为空时抛出
*/
public List<ArticleGenerationTask> searchTasksByTitle(Integer companyId, String articleTheme) {
log.debug("根据文章主题搜索任务,companyId: {}, articleTheme: {}", companyId, articleTheme);
if (companyId == null || !StringUtils.hasText(articleTheme)) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID和文章主题不能为空");
}
return taskRepository.findByCompanyIdAndArticleThemeContainingIgnoreCase(companyId, articleTheme);
}
/**
* 保存文章生成任务
* @param task 任务对象
* @return 保存后的任务
* @throws BusinessException 当任务对象为空或保存失败时抛出
*/
@Transactional
public ArticleGenerationTask saveTask(ArticleGenerationTask task) {
log.debug("保存文章生成任务,articleTheme: {}", task != null ? task.getArticleTheme() : null);
if (task == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务对象不能为空");
}
// 设置当前租户ID
if (task.getCompanyId() == null) {
task.setCompanyId(TenantContext.getCurrentTenantId());
}
// 新建任务时设置默认状态
if (task.getId() == null && task.getStatus() == null) {
task.setStatus(TaskStatus.PENDING);
}
try {
ArticleGenerationTask savedTask = taskRepository.save(task);
log.info("文章生成任务保存成功,id: {}, articleTheme: {}", savedTask.getId(), savedTask.getArticleTheme());
return savedTask;
} catch (Exception e) {
log.error("文章生成任务保存失败", e);
throw new BusinessException(ResultCode.SYSTEM_ERROR, "任务保存失败");
}
}
/**
* 批量保存文章生成任务
* @param tasks 任务列表
* @return 保存后的任务列表
* @throws BusinessException 当任务列表为空或保存失败时抛出
*/
@Transactional
public List<ArticleGenerationTask> batchSaveTasks(List<ArticleGenerationTask> tasks) {
log.debug("批量保存文章生成任务,数量: {}", tasks != null ? tasks.size() : 0);
if (tasks == null || tasks.isEmpty()) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务列表不能为空");
}
Integer companyId = TenantContext.getCurrentTenantId();
for (ArticleGenerationTask task : tasks) {
if (task.getCompanyId() == null) {
task.setCompanyId(companyId);
}
if (task.getStatus() == null) {
task.setStatus(TaskStatus.PENDING);
}
}
try {
List<ArticleGenerationTask> savedTasks = taskRepository.saveAll(tasks);
log.info("批量保存文章生成任务成功,数量: {}", savedTasks.size());
return savedTasks;
} catch (Exception e) {
log.error("批量保存文章生成任务失败", e);
throw new BusinessException(ResultCode.SYSTEM_ERROR, "批量保存任务失败");
}
}
/**
* 更新任务状态
* @param id 任务ID
* @param status 新状态
* @return 更新后的任务
* @throws BusinessException 当参数为空或任务不存在时抛出
*/
@Transactional
public ArticleGenerationTask updateTaskStatus(Integer id, TaskStatus status) {
log.debug("更新任务状态,id: {}, status: {}", id, status);
if (id == null || status == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务ID和状态不能为空");
}
ArticleGenerationTask task = taskRepository.findById(id)
.orElseThrow(() -> new BusinessException(ResultCode.DATA_NOT_FOUND, "任务不存在"));
task.setStatus(status);
task.setUpdatedAt(LocalDateTime.now());
try {
ArticleGenerationTask updatedTask = taskRepository.save(task);
log.info("任务状态更新成功,id: {}, status: {}", id, status);
return updatedTask;
} catch (Exception e) {
log.error("任务状态更新失败", e);
throw new BusinessException(ResultCode.SYSTEM_ERROR, "任务状态更新失败");
}
}
/**
* 更新任务进度
* @param id 任务ID
* @param progress 进度百分比(0-100)
* @return 更新后的任务
* @throws BusinessException 当参数无效或任务不存在时抛出
*/
@Transactional
public ArticleGenerationTask updateTaskProgress(Integer id, Integer progress) {
log.debug("更新任务进度,id: {}, progress: {}", id, progress);
if (id == null || progress == null || progress < 0 || progress > 100) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务ID不能为空,进度必须在0-100之间");
}
ArticleGenerationTask task = taskRepository.findById(id)
.orElseThrow(() -> new BusinessException(ResultCode.DATA_NOT_FOUND, "任务不存在"));
task.setProgress(progress);
task.setUpdatedAt(LocalDateTime.now());
try {
ArticleGenerationTask updatedTask = taskRepository.save(task);
log.info("任务进度更新成功,id: {}, progress: {}", id, progress);
return updatedTask;
} catch (Exception e) {
log.error("任务进度更新失败", e);
throw new BusinessException(ResultCode.SYSTEM_ERROR, "任务进度更新失败");
}
}
/**
* 删除文章生成任务
* @param id 任务ID
* @throws BusinessException 当ID为空或任务不存在时抛出
*/
@Transactional
public void deleteTask(Integer id) {
log.debug("删除文章生成任务,id: {}", id);
if (id == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务ID不能为空");
}
if (!taskRepository.existsById(id)) {
throw new BusinessException(ResultCode.DATA_NOT_FOUND, "任务不存在");
}
try {
taskRepository.deleteById(id);
log.info("文章生成任务删除成功,id: {}", id);
} catch (Exception e) {
log.error("文章生成任务删除失败", e);
throw new BusinessException(ResultCode.SYSTEM_ERROR, "任务删除失败");
}
}
/**
* 批量删除文章生成任务
* @param ids 任务ID列表
* @throws BusinessException 当ID列表为空时抛出
*/
@Transactional
public void batchDeleteTasks(List<Integer> ids) {
log.debug("批量删除文章生成任务,数量: {}", ids != null ? ids.size() : 0);
if (ids == null || ids.isEmpty()) {
throw new BusinessException(ResultCode.PARAM_ERROR, "任务ID列表不能为空");
}
try {
taskRepository.deleteAllById(ids);
log.info("批量删除文章生成任务成功,数量: {}", ids.size());
} catch (Exception e) {
log.error("批量删除文章生成任务失败", e);
throw new BusinessException(ResultCode.SYSTEM_ERROR, "批量删除任务失败");
}
}
/**
* 统计公司任务总数
* @param companyId 公司ID
* @return 任务总数
* @throws BusinessException 当公司ID为空时抛出
*/
public long countByCompanyId(Integer companyId) {
log.debug("统计公司任务总数,companyId: {}", companyId);
if (companyId == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID不能为空");
}
return taskRepository.countByCompanyId(companyId);
}
/**
* 统计公司指定状态的任务数量
* @param companyId 公司ID
* @param status 任务状态
* @return 任务数量
* @throws BusinessException 当参数为空时抛出
*/
public long countByCompanyIdAndStatus(Integer companyId, TaskStatus status) {
log.debug("统计公司指定状态任务数量,companyId: {}, status: {}", companyId, status);
if (companyId == null || status == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID和状态不能为空");
}
return taskRepository.countByCompanyIdAndStatus(companyId, status);
}
/**
* 查找最近更新的任务
* @param companyId 公司ID
* @param since 起始时间
* @return 最近更新的任务列表
* @throws BusinessException 当参数为空时抛出
*/
public List<ArticleGenerationTask> getRecentlyUpdatedTasks(Integer companyId, LocalDateTime since) {
log.debug("查找最近更新的任务,companyId: {}, since: {}", companyId, since);
if (companyId == null || since == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID和时间不能为空");
}
return taskRepository.findByUpdatedAtAfterOrderByUpdatedAtDesc(companyId, since);
}
/**
* 查找待处理的任务
* @param companyId 公司ID
* @return 待处理任务列表
* @throws BusinessException 当公司ID为空时抛出
*/
public List<ArticleGenerationTask> getPendingTasks(Integer companyId) {
log.debug("查找待处理任务,companyId: {}", companyId);
if (companyId == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID不能为空");
}
return taskRepository.findByCompanyIdAndStatus(companyId, TaskStatus.PENDING);
}
/**
* 查找正在处理的任务
* @param companyId 公司ID
* @return 正在处理的任务列表
* @throws BusinessException 当公司ID为空时抛出
*/
public List<ArticleGenerationTask> getRunningTasks(Integer companyId) {
log.debug("查找正在处理任务,companyId: {}", companyId);
if (companyId == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID不能为空");
}
return taskRepository.findByCompanyIdAndStatus(companyId, TaskStatus.PROCESSING);
}
/**
* 查找已完成的任务
* @param companyId 公司ID
* @return 已完成任务列表
* @throws BusinessException 当公司ID为空时抛出
*/
public List<ArticleGenerationTask> getCompletedTasks(Integer companyId) {
log.debug("查找已完成任务,companyId: {}", companyId);
if (companyId == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "公司ID不能为空");
}
return taskRepository.findByCompanyIdAndStatus(companyId, TaskStatus.COMPLETED);
}
/**
* 多条件搜索任务(分页)
* @param companyId 公司ID
* @param userId 用户ID
* @param status 任务状态
* @param articleTheme 文章主题
* @param startTime 开始时间
* @param endTime 结束时间
* @param pageable 分页参数
* @return 搜索结果分页数据
*/
public Page<ArticleGenerationTask> searchTasks(Integer companyId, Integer userId,
TaskStatus status, String articleTheme,
LocalDateTime startTime, LocalDateTime endTime,
Pageable pageable) {
log.debug("多条件搜索任务,companyId: {}, userId: {}, status: {}", companyId, userId, status);
return taskRepository.searchTasks(companyId, userId, status, articleTheme, startTime, endTime, pageable);
}
/**
* 检查任务队列是否已满
* @param companyId 公司ID
* @return 是否已满
*/
public boolean isTaskQueueFull(Integer companyId) {
log.debug("检查任务队列是否已满,companyId: {}", companyId);
long pendingCount = taskRepository.countByCompanyIdAndStatus(companyId, TaskStatus.PENDING);
long processingCount = taskRepository.countByCompanyIdAndStatus(companyId, TaskStatus.PROCESSING);
// 假设每个公司最大允许同时进行50个任务
return (pendingCount + processingCount) >= 50;
}
/**
* 获取最近完成的任务
* @param companyId 公司ID(可选)
* @param limit 返回数量限制
* @return 最近完成的任务列表
*/
public List<ArticleGenerationTask> getRecentCompletedTasks(Integer companyId, int limit) {
log.debug("获取最近完成的任务,companyId: {}, limit: {}", companyId, limit);
Pageable pageable = PageRequest.of(0, limit);
return taskRepository.findRecentCompletedTasks(companyId, TaskStatus.COMPLETED, pageable);
}
/**
* 检查任务是否存在
* @param id 任务ID
* @return 是否存在
*/
public boolean existsById(Integer id) {
log.debug("检查任务是否存在,id: {}", id);
if (id == null) return false;
return taskRepository.existsById(id);
}
/**
* 启动任务
* @param id 任务ID
* @return 是否启动成功
*/
@Transactional
public boolean startTask(Integer id) {
log.debug("启动任务,id: {}", id);
if (!taskRepository.existsById(id)) {
return false;
}
Optional<ArticleGenerationTask> taskOpt = taskRepository.findById(id);
if (taskOpt.isPresent()) {
ArticleGenerationTask task = taskOpt.get();
if (task.getStatus() == TaskStatus.PENDING || task.getStatus() == TaskStatus.FAILED) {
task.start();
taskRepository.save(task);
log.info("任务启动成功,id: {}", id);
return true;
}
}
return false;
}
/**
* 暂停任务
* @param id 任务ID
* @return 是否暂停成功
*/
@Transactional
public boolean pauseTask(Integer id) {
log.debug("暂停任务,id: {}", id);
Optional<ArticleGenerationTask> taskOpt = taskRepository.findById(id);
if (taskOpt.isPresent()) {
ArticleGenerationTask task = taskOpt.get();
if (task.getStatus() == TaskStatus.PROCESSING) {
task.setStatus(TaskStatus.PAUSED);
taskRepository.save(task);
log.info("任务暂停成功,id: {}", id);
return true;
}
}
return false;
}
/**
* 取消任务
* @param id 任务ID
* @return 是否取消成功
*/
@Transactional
public boolean cancelTask(Integer id) {
log.debug("取消任务,id: {}", id);
Optional<ArticleGenerationTask> taskOpt = taskRepository.findById(id);
if (taskOpt.isPresent()) {
ArticleGenerationTask task = taskOpt.get();
if (task.isCancellable()) {
task.cancel("用户手动取消");
taskRepository.save(task);
log.info("任务取消成功,id: {}", id);
return true;
}
}
return false;
}
/**
* 重试任务
* @param id 任务ID
* @return 是否重试成功
*/
@Transactional
public boolean retryTask(Integer id) {
log.debug("重试任务,id: {}", id);
Optional<ArticleGenerationTask> taskOpt = taskRepository.findById(id);
if (taskOpt.isPresent()) {
ArticleGenerationTask task = taskOpt.get();
if (task.canRetry()) {
task.incrementRetryCount();
task.setStatus(TaskStatus.PENDING);
task.setErrorMessage(null);
taskRepository.save(task);
log.info("任务重试成功,id: {}", id);
return true;
}
}
return false;
}
/**
* 检查任务是否正在运行
* @param id 任务ID
* @return 是否正在运行
*/
public boolean isTaskRunning(Integer id) {
log.debug("检查任务是否正在运行,id: {}", id);
Optional<ArticleGenerationTask> taskOpt = taskRepository.findById(id);
return taskOpt.map(ArticleGenerationTask::isRunning).orElse(false);
}
/**
* 获取任务执行日志
* @param id 任务ID
* @param level 日志级别
* @param limit 返回数量限制
* @return 日志列表
*/
public List<String> getTaskLogs(Integer id, String level, int limit) {
log.debug("获取任务执行日志,id: {}, level: {}, limit: {}", id, level, limit);
// 这里应该实现从日志系统获取任务相关的日志
// 暂时返回模拟数据
List<String> logs = new ArrayList<>();
logs.add("任务创建成功");
logs.add("开始执行任务");
logs.add("正在处理中...");
return logs.stream().limit(limit).collect(Collectors.toList());
}
/**
* 获取任务统计信息
* @param companyId 公司ID(可选)
* @param days 统计时间范围(天数)
* @return 统计信息
*/
public TaskStatistics getTaskStatistics(Integer companyId, int days) {
log.debug("获取任务统计信息,companyId: {}, days: {}", companyId, days);
LocalDateTime startTime = LocalDateTime.now().minusDays(days);
LocalDateTime endTime = LocalDateTime.now();
long totalTasks = taskRepository.countByConditions(companyId, null, startTime, endTime);
long pendingTasks = taskRepository.countByConditions(companyId, TaskStatus.PENDING, startTime, endTime);
long runningTasks = taskRepository.countByConditions(companyId, TaskStatus.PROCESSING, startTime, endTime);
long completedTasks = taskRepository.countByConditions(companyId, TaskStatus.COMPLETED, startTime, endTime);
long failedTasks = taskRepository.countByConditions(companyId, TaskStatus.FAILED, startTime, endTime);
double successRate = totalTasks > 0 ? (completedTasks * 100.0 / totalTasks) : 0.0;
Double averageExecutionTime = taskRepository.getAverageExecutionTime(companyId, startTime, endTime);
return new TaskStatistics(
totalTasks, pendingTasks, runningTasks, completedTasks, failedTasks,
successRate, averageExecutionTime != null ? averageExecutionTime : 0.0
);
}
/**
* 任务统计信息数据结构
*/
public static class TaskStatistics {
private final long totalTasks;
private final long pendingTasks;
private final long runningTasks;
private final long completedTasks;
private final long failedTasks;
private final double successRate;
private final double averageExecutionTime;
public TaskStatistics(long totalTasks, long pendingTasks, long runningTasks,
long completedTasks, long failedTasks, double successRate,
double averageExecutionTime) {
this.totalTasks = totalTasks;
this.pendingTasks = pendingTasks;
this.runningTasks = runningTasks;
this.completedTasks = completedTasks;
this.failedTasks = failedTasks;
this.successRate = successRate;
this.averageExecutionTime = averageExecutionTime;
}
// Getters
public long getTotalTasks() { return totalTasks; }
public long getPendingTasks() { return pendingTasks; }
public long getRunningTasks() { return runningTasks; }
public long getCompletedTasks() { return completedTasks; }
public long getFailedTasks() { return failedTasks; }
public double getSuccessRate() { return successRate; }
public double getAverageExecutionTime() { return averageExecutionTime; }
}
/**
* 清理已完成的任务
* @param retentionDays 保留天数
* @return 清理的任务数量
*/
@Transactional
public int cleanupCompletedTasks(int retentionDays) {
log.debug("清理已完成的任务,保留天数: {}", retentionDays);
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(retentionDays);
int deletedCount = taskRepository.deleteCompletedTasksBefore(TaskStatus.COMPLETED, cutoffDate);
log.info("清理已完成的任务成功,删除数量: {}", deletedCount);
return deletedCount;
}
}